package handlers

import (
	"encoding/json"
	"net/http"
	"time"

	"github.com/breakpilot/ai-compliance-sdk/internal/iace"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// ImportGroundTruth handles POST /projects/:id/benchmark/import-gt
// Stores Ground Truth data in project metadata.ground_truth.
func (h *IACEHandler) ImportGroundTruth(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	ctx := c.Request.Context()
	project, err := h.store.GetProject(ctx, projectID)
	if err != nil || project == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
		return
	}

	var gt iace.GroundTruth
	if err := c.ShouldBindJSON(&gt); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ground truth JSON: " + err.Error()})
		return
	}

	if gt.ImportedAt == "" {
		gt.ImportedAt = time.Now().Format("2006-01-02")
	}

	// Merge into existing metadata
	meta := make(map[string]json.RawMessage)
	if project.Metadata != nil {
		_ = json.Unmarshal(project.Metadata, &meta)
	}
	gtJSON, _ := json.Marshal(gt)
	meta["ground_truth"] = gtJSON

	mergedMeta, _ := json.Marshal(meta)
	err = h.store.UpdateProjectMetadata(ctx, projectID, mergedMeta)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to store ground truth"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message":     "ground truth imported",
		"entry_count": len(gt.Entries),
		"source_file": gt.SourceFile,
	})
}

// RunBenchmark handles GET /projects/:id/benchmark?gt_project_id=:gtId
// Compares engine hazards from project :id against GT from project :gtId.
// If gt_project_id is omitted, looks for GT in the same project's metadata.
func (h *IACEHandler) RunBenchmark(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	ctx := c.Request.Context()

	// Determine GT source
	gtProjectID := projectID
	if gtParam := c.Query("gt_project_id"); gtParam != "" {
		parsed, err := uuid.Parse(gtParam)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "invalid gt_project_id"})
			return
		}
		gtProjectID = parsed
	}

	// Load GT
	gtProject, err := h.store.GetProject(ctx, gtProjectID)
	if err != nil || gtProject == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "GT project not found"})
		return
	}
	gt, err := iace.ParseGroundTruth(gtProject.Metadata)
	if err != nil || gt == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "no ground truth data in project metadata"})
		return
	}

	// Load engine hazards + mitigations
	hazards, err := h.store.ListHazards(ctx, projectID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load hazards"})
		return
	}
	mitigations, err := h.store.ListMitigationsByProject(ctx, projectID)
	if err != nil {
		mitigations = nil
	}

	result := iace.CompareBenchmark(gt, hazards, mitigations)
	result.RiskComparison, result.RiskAgreement = iace.ComputeRiskComparison(result.MatchedPairs)
	c.JSON(http.StatusOK, result)
}

// GetBenchmarkSummary handles GET /projects/:id/benchmark/summary
// Returns lightweight coverage metrics without full match details.
func (h *IACEHandler) GetBenchmarkSummary(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	ctx := c.Request.Context()

	gtProjectID := projectID
	if gtParam := c.Query("gt_project_id"); gtParam != "" {
		parsed, err := uuid.Parse(gtParam)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "invalid gt_project_id"})
			return
		}
		gtProjectID = parsed
	}

	gtProject, err := h.store.GetProject(ctx, gtProjectID)
	if err != nil || gtProject == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "GT project not found"})
		return
	}
	gt, err := iace.ParseGroundTruth(gtProject.Metadata)
	if err != nil || gt == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "no ground truth data"})
		return
	}

	hazards, err := h.store.ListHazards(ctx, projectID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load hazards"})
		return
	}
	mitigations, _ := h.store.ListMitigationsByProject(ctx, projectID)

	result := iace.CompareBenchmark(gt, hazards, mitigations)

	c.JSON(http.StatusOK, gin.H{
		"coverage_score":     result.CoverageScore,
		"measure_coverage":   result.MeasureCoverage,
		"total_gt":           result.TotalGT,
		"total_engine":       result.TotalEngine,
		"matched_count":      len(result.MatchedPairs),
		"missing_count":      len(result.MissingFromEngine),
		"extra_count":        len(result.ExtraInEngine),
		"category_breakdown": result.CategoryBreakdown,
	})
}
