package security

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"time"

	v1 "github.com/hatchet-dev/hatchet/pkg/repository"

	"github.com/rs/zerolog"
)

type SecurityCheck interface {
	Check()
}

type DefaultSecurityCheck struct {
	Enabled  bool
	Endpoint string
	Logger   *zerolog.Logger
	Version  string
	Repo     v1.SecurityCheckRepository
}

func NewSecurityCheck(opts *DefaultSecurityCheck, repo v1.SecurityCheckRepository) SecurityCheck {
	return DefaultSecurityCheck{
		Enabled:  opts.Enabled,
		Endpoint: opts.Endpoint,
		Logger:   opts.Logger,
		Version:  opts.Version,
		Repo:     repo,
	}
}

func (a DefaultSecurityCheck) Check() {
	if !a.Enabled {
		return
	}

	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("panic in check: %v", r)
		}
	}()

	a.Logger.Debug().Msgf("Fetching security alerts for version %s", a.Version)

	ident, err := a.Repo.GetIdent()
	if err != nil {
		a.Logger.Debug().Msgf("Error fetching security alerts: %s", err)
		return
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	reqURL := fmt.Sprintf("%s/check?version=%s&tag=%s", a.Endpoint, a.Version, ident)
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
	if err != nil {
		a.Logger.Debug().Msgf("Error creating security check request: %s", err)
		return
	}

	resp, err := http.DefaultClient.Do(req) // #nosec
	if err != nil {
		a.Logger.Debug().Msgf("Error making request to security endpoint: %s", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		a.Logger.Debug().Msgf("Unexpected status code from security endpoint: %d", resp.StatusCode)
		return
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		a.Logger.Debug().Msgf("Error reading response body: %s", err)
		return
	}

	if len(body) == 0 {
		a.Logger.Debug().Msg("No security alerts found")
		return
	}

	a.Logger.Error().Msgf("Security Alert:\n\n%s\n******************\n", body)
}
