// DEPRECATED: This file implements UCCA-specific escalation handlers (E0-E3 workflow).
// The primary escalation system is now Python backend-compliance escalation_routes.py
// (/api/compliance/escalations). These UCCA handlers remain only for assessment-review
// workflows and will be removed in a future release.
package handlers

import (
	"net/http"
	"time"

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

// EscalationHandlers handles escalation-related API endpoints.
type EscalationHandlers struct {
	store           *ucca.EscalationStore
	assessmentStore *ucca.Store
	trigger         *ucca.EscalationTrigger
}

// NewEscalationHandlers creates new escalation handlers.
func NewEscalationHandlers(store *ucca.EscalationStore, assessmentStore *ucca.Store) *EscalationHandlers {
	return &EscalationHandlers{
		store:           store,
		assessmentStore: assessmentStore,
		trigger:         ucca.DefaultEscalationTrigger(),
	}
}

// ============================================================================
// GET /sdk/v1/ucca/escalations - List escalations
// ============================================================================

// ListEscalations returns escalations for a tenant with optional filters.
func (h *EscalationHandlers) ListEscalations(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

	status := c.Query("status")
	level := c.Query("level")

	var assignedTo *uuid.UUID
	if assignedToStr := c.Query("assigned_to"); assignedToStr != "" {
		if id, err := uuid.Parse(assignedToStr); err == nil {
			assignedTo = &id
		}
	}

	// If user is a reviewer, filter to their assignments by default
	userID := rbac.GetUserID(c)
	if c.Query("my_reviews") == "true" && userID != uuid.Nil {
		assignedTo = &userID
	}

	escalations, err := h.store.ListEscalations(c.Request.Context(), tenantID, status, level, assignedTo)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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

// ============================================================================
// GET /sdk/v1/ucca/escalations/:id - Get single escalation
// ============================================================================

// GetEscalation returns a single escalation by ID.
func (h *EscalationHandlers) GetEscalation(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

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

	// Get history
	history, _ := h.store.GetEscalationHistory(c.Request.Context(), id)

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

// ============================================================================
// POST /sdk/v1/ucca/escalations - Create escalation (manual)
// ============================================================================

// CreateEscalation creates a manual escalation for an assessment.
func (h *EscalationHandlers) CreateEscalation(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	userID := rbac.GetUserID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

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

	// Get the assessment
	assessment, err := h.assessmentStore.GetAssessment(c.Request.Context(), req.AssessmentID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	if assessment == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "assessment not found"})
		return
	}

	// Determine escalation level
	result := &ucca.AssessmentResult{
		Feasibility:      assessment.Feasibility,
		RiskLevel:        assessment.RiskLevel,
		RiskScore:        assessment.RiskScore,
		TriggeredRules:   assessment.TriggeredRules,
		DSFARecommended:  assessment.DSFARecommended,
		Art22Risk:        assessment.Art22Risk,
	}
	level, reason := h.trigger.DetermineEscalationLevel(result)

	// Calculate due date based on SLA
	responseHours, _ := ucca.GetDefaultSLA(level)
	var dueDate *time.Time
	if responseHours > 0 {
		due := time.Now().UTC().Add(time.Duration(responseHours) * time.Hour)
		dueDate = &due
	}

	// Create escalation
	escalation := &ucca.Escalation{
		TenantID:         tenantID,
		AssessmentID:     req.AssessmentID,
		EscalationLevel:  level,
		EscalationReason: reason,
		Status:           ucca.EscalationStatusPending,
		DueDate:          dueDate,
	}

	// For E0, auto-approve
	if level == ucca.EscalationLevelE0 {
		escalation.Status = ucca.EscalationStatusApproved
		approveDecision := ucca.EscalationDecisionApprove
		escalation.Decision = &approveDecision
		now := time.Now().UTC()
		escalation.DecisionAt = &now
		autoNotes := "Automatische Freigabe (E0)"
		escalation.DecisionNotes = &autoNotes
	}

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

	// Add history entry
	h.store.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
		EscalationID: escalation.ID,
		Action:       "created",
		NewStatus:    string(escalation.Status),
		NewLevel:     string(escalation.EscalationLevel),
		ActorID:      userID,
		Notes:        reason,
	})

	// For E1/E2/E3, try to auto-assign
	if level != ucca.EscalationLevelE0 {
		role := ucca.GetRoleForLevel(level)
		reviewer, err := h.store.GetNextAvailableReviewer(c.Request.Context(), tenantID, role)
		if err == nil && reviewer != nil {
			h.store.AssignEscalation(c.Request.Context(), escalation.ID, reviewer.UserID, role)
			h.store.IncrementReviewerCount(c.Request.Context(), reviewer.UserID)
			h.store.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
				EscalationID: escalation.ID,
				Action:       "auto_assigned",
				OldStatus:    string(ucca.EscalationStatusPending),
				NewStatus:    string(ucca.EscalationStatusAssigned),
				ActorID:      userID,
				Notes:        "Automatisch zugewiesen an: " + reviewer.UserName,
			})
		}
	}

	c.JSON(http.StatusCreated, escalation)
}

// ============================================================================
// POST /sdk/v1/ucca/escalations/:id/assign - Assign escalation
// ============================================================================

// AssignEscalation assigns an escalation to a reviewer.
func (h *EscalationHandlers) AssignEscalation(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

	userID := rbac.GetUserID(c)

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

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

	role := ucca.GetRoleForLevel(escalation.EscalationLevel)

	if err := h.store.AssignEscalation(c.Request.Context(), id, req.AssignedTo, role); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	h.store.IncrementReviewerCount(c.Request.Context(), req.AssignedTo)
	h.store.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
		EscalationID: id,
		Action:       "assigned",
		OldStatus:    string(escalation.Status),
		NewStatus:    string(ucca.EscalationStatusAssigned),
		ActorID:      userID,
	})

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

// ============================================================================
// POST /sdk/v1/ucca/escalations/:id/review - Start review
// ============================================================================

// StartReview marks an escalation as being reviewed.
func (h *EscalationHandlers) StartReview(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

	userID := rbac.GetUserID(c)
	if userID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "user ID required"})
		return
	}

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

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

	h.store.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
		EscalationID: id,
		Action:       "review_started",
		OldStatus:    string(escalation.Status),
		NewStatus:    string(ucca.EscalationStatusInReview),
		ActorID:      userID,
	})

	c.JSON(http.StatusOK, gin.H{"message": "review started"})
}

// ============================================================================
// POST /sdk/v1/ucca/escalations/:id/decide - Make decision
// ============================================================================

// DecideEscalation makes a decision on an escalation.
func (h *EscalationHandlers) DecideEscalation(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

	userID := rbac.GetUserID(c)
	if userID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "user ID required"})
		return
	}

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

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

	if err := h.store.DecideEscalation(c.Request.Context(), id, req.Decision, req.DecisionNotes, req.Conditions); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Decrement reviewer count
	if escalation.AssignedTo != nil {
		h.store.DecrementReviewerCount(c.Request.Context(), *escalation.AssignedTo)
	}

	newStatus := "decided"
	switch req.Decision {
	case ucca.EscalationDecisionApprove:
		newStatus = string(ucca.EscalationStatusApproved)
	case ucca.EscalationDecisionReject:
		newStatus = string(ucca.EscalationStatusRejected)
	case ucca.EscalationDecisionModify:
		newStatus = string(ucca.EscalationStatusReturned)
	case ucca.EscalationDecisionEscalate:
		newStatus = "escalated"
	}

	h.store.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
		EscalationID: id,
		Action:       "decision_made",
		OldStatus:    string(escalation.Status),
		NewStatus:    newStatus,
		ActorID:      userID,
		Notes:        req.DecisionNotes,
	})

	c.JSON(http.StatusOK, gin.H{"message": "decision recorded", "status": newStatus})
}

// ============================================================================
// GET /sdk/v1/ucca/escalations/stats - Get statistics
// ============================================================================

// GetEscalationStats returns escalation statistics.
func (h *EscalationHandlers) GetEscalationStats(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

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

	c.JSON(http.StatusOK, stats)
}

// ============================================================================
// DSB Pool Management
// ============================================================================

// ListDSBPool returns the DSB review pool for a tenant.
func (h *EscalationHandlers) ListDSBPool(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

	role := c.Query("role")
	members, err := h.store.GetDSBPoolMembers(c.Request.Context(), tenantID, role)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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

// AddDSBPoolMember adds a member to the DSB pool.
func (h *EscalationHandlers) AddDSBPoolMember(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

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

	member.TenantID = tenantID
	member.IsActive = true
	if member.MaxConcurrentReviews == 0 {
		member.MaxConcurrentReviews = 10
	}

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

	c.JSON(http.StatusCreated, member)
}
