package handlers

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

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

// ============================================================================
// Evidence & Verification Plans
// ============================================================================

// UploadEvidence handles POST /projects/:id/evidence
// Creates a new evidence record for a project.
func (h *IACEHandler) UploadEvidence(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	var req struct {
		MitigationID       *uuid.UUID `json:"mitigation_id,omitempty"`
		VerificationPlanID *uuid.UUID `json:"verification_plan_id,omitempty"`
		FileName           string     `json:"file_name" binding:"required"`
		FilePath           string     `json:"file_path" binding:"required"`
		FileHash           string     `json:"file_hash" binding:"required"`
		FileSize           int64      `json:"file_size" binding:"required"`
		MimeType           string     `json:"mime_type" binding:"required"`
		Description        string     `json:"description,omitempty"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)

	evidence := &iace.Evidence{
		ProjectID:          projectID,
		MitigationID:       req.MitigationID,
		VerificationPlanID: req.VerificationPlanID,
		FileName:           req.FileName,
		FilePath:           req.FilePath,
		FileHash:           req.FileHash,
		FileSize:           req.FileSize,
		MimeType:           req.MimeType,
		Description:        req.Description,
		UploadedBy:         userID,
	}

	if err := h.store.CreateEvidence(c.Request.Context(), evidence); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	newVals, _ := json.Marshal(evidence)
	h.store.AddAuditEntry(
		c.Request.Context(), projectID, "evidence", evidence.ID,
		iace.AuditActionCreate, userID.String(), nil, newVals,
	)

	c.JSON(http.StatusCreated, gin.H{"evidence": evidence})
}

// ListEvidence handles GET /projects/:id/evidence
func (h *IACEHandler) ListEvidence(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	evidence, err := h.store.ListEvidence(c.Request.Context(), projectID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if evidence == nil {
		evidence = []iace.Evidence{}
	}

	c.JSON(http.StatusOK, gin.H{"evidence": evidence, "total": len(evidence)})
}

// CreateVerificationPlan handles POST /projects/:id/verification-plan
func (h *IACEHandler) CreateVerificationPlan(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	var req iace.CreateVerificationPlanRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	req.ProjectID = projectID

	plan, err := h.store.CreateVerificationPlan(c.Request.Context(), req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)
	newVals, _ := json.Marshal(plan)
	h.store.AddAuditEntry(
		c.Request.Context(), projectID, "verification_plan", plan.ID,
		iace.AuditActionCreate, userID.String(), nil, newVals,
	)

	c.JSON(http.StatusCreated, gin.H{"verification_plan": plan})
}

// UpdateVerificationPlan handles PUT /verification-plan/:vid
func (h *IACEHandler) UpdateVerificationPlan(c *gin.Context) {
	planID, err := uuid.Parse(c.Param("vid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid verification plan ID"})
		return
	}

	var updates map[string]interface{}
	if err := c.ShouldBindJSON(&updates); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	plan, err := h.store.UpdateVerificationPlan(c.Request.Context(), planID, updates)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if plan == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "verification plan not found"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"verification_plan": plan})
}

// CompleteVerification handles POST /verification-plan/:vid/complete
func (h *IACEHandler) CompleteVerification(c *gin.Context) {
	planID, err := uuid.Parse(c.Param("vid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid verification plan ID"})
		return
	}

	var req struct {
		Result string `json:"result" binding:"required"`
		Passed *bool  `json:"passed"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)

	if err := h.store.CompleteVerification(
		c.Request.Context(), planID, req.Result, userID.String(),
	); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "verification completed"})
}

// ============================================================================
// Frontend-compatible /verifications routes
// ============================================================================

// ListVerificationPlans handles GET /projects/:id/verifications
func (h *IACEHandler) ListVerificationPlans(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	plans, err := h.store.ListVerificationPlans(c.Request.Context(), projectID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Enrich with linked hazard/mitigation names
	hazards, _ := h.store.ListHazards(c.Request.Context(), projectID)
	mitigations, _ := h.store.ListMitigationsByProject(c.Request.Context(), projectID)
	hazardMap := make(map[uuid.UUID]string, len(hazards))
	for _, hz := range hazards {
		hazardMap[hz.ID] = hz.Name
	}
	mitMap := make(map[uuid.UUID]string, len(mitigations))
	for _, m := range mitigations {
		mitMap[m.ID] = m.Name
	}

	type enrichedPlan struct {
		iace.VerificationPlan
		LinkedHazardName     string `json:"linked_hazard_name,omitempty"`
		LinkedMitigationName string `json:"linked_mitigation_name,omitempty"`
	}
	enriched := make([]enrichedPlan, 0, len(plans))
	for _, p := range plans {
		ep := enrichedPlan{VerificationPlan: p}
		if p.HazardID != nil {
			ep.LinkedHazardName = hazardMap[*p.HazardID]
		}
		if p.MitigationID != nil {
			ep.LinkedMitigationName = mitMap[*p.MitigationID]
		}
		enriched = append(enriched, ep)
	}

	c.JSON(http.StatusOK, gin.H{"verifications": enriched, "total": len(enriched)})
}

// CreateVerificationAlias handles POST /projects/:id/verifications
// Frontend-compatible alias that maps linked_mitigation_id to mitigation_id.
func (h *IACEHandler) CreateVerificationAlias(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	var body struct {
		Title              string  `json:"title" binding:"required"`
		Description        string  `json:"description"`
		Method             string  `json:"method" binding:"required"`
		LinkedMitigationID *string `json:"linked_mitigation_id"`
		LinkedHazardID     *string `json:"linked_hazard_id"`
		MitigationID       *string `json:"mitigation_id"`
		HazardID           *string `json:"hazard_id"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	req := iace.CreateVerificationPlanRequest{
		ProjectID:   projectID,
		Title:       body.Title,
		Description: body.Description,
		Method:      iace.VerificationMethod(body.Method),
	}

	midStr := body.MitigationID
	if midStr == nil {
		midStr = body.LinkedMitigationID
	}
	if midStr != nil {
		mid, err := uuid.Parse(*midStr)
		if err == nil {
			req.MitigationID = &mid
		}
	}

	hidStr := body.HazardID
	if hidStr == nil {
		hidStr = body.LinkedHazardID
	}
	if hidStr != nil {
		hid, err := uuid.Parse(*hidStr)
		if err == nil {
			req.HazardID = &hid
		}
	}

	plan, err := h.store.CreateVerificationPlan(c.Request.Context(), req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)
	newVals, _ := json.Marshal(plan)
	h.store.AddAuditEntry(
		c.Request.Context(), projectID, "verification_plan", plan.ID,
		iace.AuditActionCreate, userID.String(), nil, newVals,
	)

	c.JSON(http.StatusCreated, plan)
}

// DeleteVerificationPlan handles DELETE /projects/:id/verifications/:vid
func (h *IACEHandler) DeleteVerificationPlan(c *gin.Context) {
	projectID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project ID"})
		return
	}

	planID, err := uuid.Parse(c.Param("vid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid verification plan ID"})
		return
	}

	if err := h.store.DeleteVerificationPlan(c.Request.Context(), planID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	userID := rbac.GetUserID(c)
	h.store.AddAuditEntry(
		c.Request.Context(), projectID, "verification_plan", planID,
		iace.AuditActionDelete, userID.String(), nil, nil,
	)

	c.JSON(http.StatusOK, gin.H{"message": "verification plan deleted"})
}

// CompleteVerificationAlias handles POST /projects/:id/verifications/:vid/complete
func (h *IACEHandler) CompleteVerificationAlias(c *gin.Context) {
	h.CompleteVerification(c)
}
