package admin

import (
	"context"
	"crypto/subtle"
	"log"
	"strings"
	"time"

	"boostai-backend/internal/config"
	"boostai-backend/internal/database"
	"boostai-backend/internal/http/respond"
	"boostai-backend/internal/seeddata"

	"github.com/gofiber/fiber/v2"
)

const (
	ReseedHeaderName = "X-Admin-Reseed-Secret"
	ReseedConfirm    = "RESEED"
)

type Runner interface {
	Run(ctx context.Context, mockDataDir string) (seeddata.Summary, error)
}

type Handler struct {
	cfg    *config.Config
	runner runFunc
}

type runFunc func(timeoutCtx context.Context, mockDataDir string) (seeddata.Summary, error)

type reseedRequest struct {
	Confirm string `json:"confirm"`
}

type reseedResponse struct {
	OK          bool             `json:"ok"`
	Environment string           `json:"environment"`
	TriggeredBy string           `json:"triggered_by,omitempty"`
	TriggeredAt time.Time        `json:"triggered_at"`
	Summary     seeddata.Summary `json:"summary"`
}

func NewHandler(db *database.DB, cfg *config.Config) *Handler {
	return &Handler{
		cfg: cfg,
		runner: func(timeoutCtx context.Context, mockDataDir string) (seeddata.Summary, error) {
			return seeddata.Run(timeoutCtx, db, mockDataDir)
		},
	}
}

func (h *Handler) ReseedDatabase(c *fiber.Ctx) error {
	if !h.cfg.AdminReseedEnabled {
		return respond.Error(c, fiber.StatusNotFound, "not_found", "The requested endpoint does not exist")
	}

	if strings.TrimSpace(h.cfg.AdminReseedSecret) == "" {
		return respond.Error(c, fiber.StatusServiceUnavailable, "admin_reseed_unavailable", "Admin reseed is not configured")
	}

	providedSecret := strings.TrimSpace(c.Get(ReseedHeaderName))
	if subtle.ConstantTimeCompare([]byte(providedSecret), []byte(h.cfg.AdminReseedSecret)) != 1 {
		return respond.Error(c, fiber.StatusForbidden, "forbidden", "Valid reseed secret required")
	}

	var req reseedRequest
	if err := c.BodyParser(&req); err != nil {
		return respond.Error(c, fiber.StatusBadRequest, "invalid_request", "Invalid request body")
	}
	if strings.TrimSpace(req.Confirm) != ReseedConfirm {
		return respond.Error(c, fiber.StatusBadRequest, "invalid_request", "confirm must equal RESEED")
	}

	triggeredBy, _ := c.Locals("auth.email").(string)
	userID, _ := c.Locals("auth.user_id").(int64)
	startedAt := time.Now().UTC()
	log.Printf("admin reseed requested environment=%s user_id=%d email=%s ip=%s", h.cfg.Environment, userID, triggeredBy, c.IP())

	timeoutCtx, cancelTimeout := context.WithTimeout(context.Background(), 2*time.Minute)
	defer cancelTimeout()

	summary, err := h.runner(timeoutCtx, h.cfg.MockDataDir)
	if err != nil {
		log.Printf("admin reseed failed environment=%s user_id=%d email=%s err=%v", h.cfg.Environment, userID, triggeredBy, err)
		return respond.Error(c, fiber.StatusInternalServerError, "admin_reseed_failed", err.Error())
	}

	log.Printf("admin reseed completed environment=%s user_id=%d email=%s users=%d assignments=%d student_answers=%d", h.cfg.Environment, userID, triggeredBy, summary.Users, summary.Assignments, summary.StudentAnswers)

	return c.JSON(reseedResponse{
		OK:          true,
		Environment: h.cfg.Environment,
		TriggeredBy: triggeredBy,
		TriggeredAt: startedAt,
		Summary:     summary,
	})
}
