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"
)

// ============================================================================
// Mitigations
// ============================================================================

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

	hazardID, err := uuid.Parse(c.Param("hid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid hazard ID"})
		return
	}

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

	// Override hazard ID from URL path
	req.HazardID = hazardID

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

	// Update hazard status to mitigated
	h.store.UpdateHazard(c.Request.Context(), hazardID, map[string]interface{}{
		"status": string(iace.HazardStatusMitigated),
	})

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

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

// UpdateMitigation handles PUT /mitigations/:mid
// Updates a mitigation measure with the provided fields.
func (h *IACEHandler) UpdateMitigation(c *gin.Context) {
	mitigationID, err := uuid.Parse(c.Param("mid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"})
		return
	}

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

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

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

// VerifyMitigation handles POST /mitigations/:mid/verify
// Marks a mitigation as verified with a verification result.
func (h *IACEHandler) VerifyMitigation(c *gin.Context) {
	mitigationID, err := uuid.Parse(c.Param("mid"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mitigation ID"})
		return
	}

	var req struct {
		VerificationResult string `json:"verification_result" binding:"required"`
	}
	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.VerifyMitigation(
		c.Request.Context(), mitigationID, req.VerificationResult, userID.String(),
	); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "mitigation verified"})
}

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

// 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
	}

	// Audit trail
	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
// Lists all evidence records for a project.
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
// Creates a new verification plan for a project.
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
	}

	// Override project ID from URL path
	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
	}

	// Audit trail
	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
// Updates a verification plan with the provided fields.
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
// Marks a verification plan as completed with a result.
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"`
	}
	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"})
}
