package ucca

import (
	"fmt"
	"time"

	"github.com/google/uuid"
)

// EscalationLevel represents the escalation level (E0-E3).
type EscalationLevel string

const (
	EscalationLevelE0 EscalationLevel = "E0" // Auto-Approve
	EscalationLevelE1 EscalationLevel = "E1" // Team-Lead Review
	EscalationLevelE2 EscalationLevel = "E2" // DSB Consultation
	EscalationLevelE3 EscalationLevel = "E3" // DSB + Legal Review
)

// EscalationStatus represents the status of an escalation.
type EscalationStatus string

const (
	EscalationStatusPending   EscalationStatus = "pending"
	EscalationStatusAssigned  EscalationStatus = "assigned"
	EscalationStatusInReview  EscalationStatus = "in_review"
	EscalationStatusApproved  EscalationStatus = "approved"
	EscalationStatusRejected  EscalationStatus = "rejected"
	EscalationStatusReturned  EscalationStatus = "returned"
)

// EscalationDecision represents the decision made on an escalation.
type EscalationDecision string

const (
	EscalationDecisionApprove  EscalationDecision = "approve"
	EscalationDecisionReject   EscalationDecision = "reject"
	EscalationDecisionModify   EscalationDecision = "modify"
	EscalationDecisionEscalate EscalationDecision = "escalate"
)

// Escalation represents an escalation record for a UCCA assessment.
type Escalation struct {
	ID                 uuid.UUID           `json:"id" db:"id"`
	TenantID           uuid.UUID           `json:"tenant_id" db:"tenant_id"`
	AssessmentID       uuid.UUID           `json:"assessment_id" db:"assessment_id"`
	EscalationLevel    EscalationLevel     `json:"escalation_level" db:"escalation_level"`
	EscalationReason   string              `json:"escalation_reason" db:"escalation_reason"`
	AssignedTo         *uuid.UUID          `json:"assigned_to,omitempty" db:"assigned_to"`
	AssignedRole       *string             `json:"assigned_role,omitempty" db:"assigned_role"`
	AssignedAt         *time.Time          `json:"assigned_at,omitempty" db:"assigned_at"`
	Status             EscalationStatus    `json:"status" db:"status"`
	ReviewerID         *uuid.UUID          `json:"reviewer_id,omitempty" db:"reviewer_id"`
	ReviewerNotes      *string             `json:"reviewer_notes,omitempty" db:"reviewer_notes"`
	ReviewedAt         *time.Time          `json:"reviewed_at,omitempty" db:"reviewed_at"`
	Decision           *EscalationDecision `json:"decision,omitempty" db:"decision"`
	DecisionNotes      *string             `json:"decision_notes,omitempty" db:"decision_notes"`
	DecisionAt         *time.Time          `json:"decision_at,omitempty" db:"decision_at"`
	Conditions         []string            `json:"conditions" db:"conditions"`
	CreatedAt          time.Time           `json:"created_at" db:"created_at"`
	UpdatedAt          time.Time           `json:"updated_at" db:"updated_at"`
	DueDate            *time.Time          `json:"due_date,omitempty" db:"due_date"`
	NotificationSent   bool                `json:"notification_sent" db:"notification_sent"`
	NotificationSentAt *time.Time          `json:"notification_sent_at,omitempty" db:"notification_sent_at"`
}

// EscalationHistory represents an audit trail entry for escalation changes.
type EscalationHistory struct {
	ID           uuid.UUID `json:"id" db:"id"`
	EscalationID uuid.UUID `json:"escalation_id" db:"escalation_id"`
	Action       string    `json:"action" db:"action"`
	OldStatus    string    `json:"old_status,omitempty" db:"old_status"`
	NewStatus    string    `json:"new_status,omitempty" db:"new_status"`
	OldLevel     string    `json:"old_level,omitempty" db:"old_level"`
	NewLevel     string    `json:"new_level,omitempty" db:"new_level"`
	ActorID      uuid.UUID `json:"actor_id" db:"actor_id"`
	ActorRole    string    `json:"actor_role,omitempty" db:"actor_role"`
	Notes        string    `json:"notes,omitempty" db:"notes"`
	CreatedAt    time.Time `json:"created_at" db:"created_at"`
}

// DSBPoolMember represents a member of the DSB review pool.
type DSBPoolMember struct {
	ID                  uuid.UUID `json:"id" db:"id"`
	TenantID            uuid.UUID `json:"tenant_id" db:"tenant_id"`
	UserID              uuid.UUID `json:"user_id" db:"user_id"`
	UserName            string    `json:"user_name" db:"user_name"`
	UserEmail           string    `json:"user_email" db:"user_email"`
	Role                string    `json:"role" db:"role"`
	IsActive            bool      `json:"is_active" db:"is_active"`
	MaxConcurrentReviews int      `json:"max_concurrent_reviews" db:"max_concurrent_reviews"`
	CurrentReviews      int       `json:"current_reviews" db:"current_reviews"`
	CreatedAt           time.Time `json:"created_at" db:"created_at"`
	UpdatedAt           time.Time `json:"updated_at" db:"updated_at"`
}

// EscalationSLA represents SLA configuration for an escalation level.
type EscalationSLA struct {
	ID                     uuid.UUID       `json:"id" db:"id"`
	TenantID               uuid.UUID       `json:"tenant_id" db:"tenant_id"`
	EscalationLevel        EscalationLevel `json:"escalation_level" db:"escalation_level"`
	ResponseHours          int             `json:"response_hours" db:"response_hours"`
	ResolutionHours        int             `json:"resolution_hours" db:"resolution_hours"`
	NotifyOnCreation       bool            `json:"notify_on_creation" db:"notify_on_creation"`
	NotifyOnApproachingSLA bool            `json:"notify_on_approaching_sla" db:"notify_on_approaching_sla"`
	NotifyOnSLABreach      bool            `json:"notify_on_sla_breach" db:"notify_on_sla_breach"`
	ApproachingSLAHours    int             `json:"approaching_sla_hours" db:"approaching_sla_hours"`
	AutoEscalateOnBreach   bool            `json:"auto_escalate_on_breach" db:"auto_escalate_on_breach"`
	CreatedAt              time.Time       `json:"created_at" db:"created_at"`
	UpdatedAt              time.Time       `json:"updated_at" db:"updated_at"`
}

// EscalationWithAssessment combines escalation with assessment summary.
type EscalationWithAssessment struct {
	Escalation
	AssessmentTitle       string `json:"assessment_title"`
	AssessmentFeasibility string `json:"assessment_feasibility"`
	AssessmentRiskScore   int    `json:"assessment_risk_score"`
	AssessmentDomain      string `json:"assessment_domain"`
}

// EscalationStats provides statistics for escalations.
type EscalationStats struct {
	TotalPending   int                       `json:"total_pending"`
	TotalInReview  int                       `json:"total_in_review"`
	TotalApproved  int                       `json:"total_approved"`
	TotalRejected  int                       `json:"total_rejected"`
	ByLevel        map[EscalationLevel]int   `json:"by_level"`
	OverdueSLA     int                       `json:"overdue_sla"`
	ApproachingSLA int                       `json:"approaching_sla"`
	AvgResolutionHours float64               `json:"avg_resolution_hours"`
}

// EscalationTrigger contains the logic to determine escalation level.
type EscalationTrigger struct {
	// Thresholds
	E1RiskThreshold int // Risk score threshold for E1 (default: 20)
	E2RiskThreshold int // Risk score threshold for E2 (default: 40)
	E3RiskThreshold int // Risk score threshold for E3 (default: 60)
}

// DefaultEscalationTrigger returns the default escalation trigger configuration.
func DefaultEscalationTrigger() *EscalationTrigger {
	return &EscalationTrigger{
		E1RiskThreshold: 20,
		E2RiskThreshold: 40,
		E3RiskThreshold: 60,
	}
}

// DetermineEscalationLevel determines the appropriate escalation level for an assessment.
func (t *EscalationTrigger) DetermineEscalationLevel(result *AssessmentResult) (EscalationLevel, string) {
	reasons := []string{}

	// E3: Highest priority checks
	// - BLOCK rules triggered
	// - Risk > 60
	// - Art. 22 risk (automated individual decisions)
	hasBlock := false
	for _, rule := range result.TriggeredRules {
		if rule.Severity == "BLOCK" {
			hasBlock = true
			reasons = append(reasons, "BLOCK-Regel ausgelöst: "+rule.Code)
			break
		}
	}

	if hasBlock || result.RiskScore > t.E3RiskThreshold || result.Art22Risk {
		if result.RiskScore > t.E3RiskThreshold {
			reasons = append(reasons, "Risiko-Score über 60")
		}
		if result.Art22Risk {
			reasons = append(reasons, "Art. 22 DSGVO Risiko (automatisierte Entscheidungen)")
		}
		return EscalationLevelE3, joinReasons(reasons, "E3 erforderlich: ")
	}

	// E2: Medium priority checks
	// - Art. 9 data (special categories)
	// - DSFA recommended
	// - Risk 40-60
	hasArt9 := false
	for _, rule := range result.TriggeredRules {
		if rule.Code == "R-002" || rule.Code == "A-002" { // Art. 9 rules
			hasArt9 = true
			reasons = append(reasons, "Besondere Datenkategorien (Art. 9 DSGVO)")
			break
		}
	}

	// BetrVG E3: Very high conflict score without consultation
	if result.BetrvgConflictScore >= 75 && !result.Intake.WorksCouncilConsulted {
		reasons = append(reasons, "BetrVG-Konfliktpotenzial sehr hoch (Score "+fmt.Sprintf("%d", result.BetrvgConflictScore)+") ohne BR-Konsultation")
		return EscalationLevelE3, joinReasons(reasons, "E3 erforderlich: ")
	}

	if hasArt9 || result.DSFARecommended || result.RiskScore > t.E2RiskThreshold {
		if result.DSFARecommended {
			reasons = append(reasons, "DSFA empfohlen")
		}
		if result.RiskScore > t.E2RiskThreshold {
			reasons = append(reasons, "Risiko-Score 40-60")
		}
		return EscalationLevelE2, joinReasons(reasons, "DSB-Konsultation erforderlich: ")
	}

	// BetrVG E2: High conflict score
	if result.BetrvgConflictScore >= 50 && result.BetrvgConsultationRequired && !result.Intake.WorksCouncilConsulted {
		reasons = append(reasons, "BetrVG-Mitbestimmung erforderlich (Score "+fmt.Sprintf("%d", result.BetrvgConflictScore)+"), BR nicht konsultiert")
		return EscalationLevelE2, joinReasons(reasons, "BR-Konsultation erforderlich: ")
	}

	// E1: Low priority checks
	// - WARN rules triggered
	// - Risk 20-40
	hasWarn := false
	for _, rule := range result.TriggeredRules {
		if rule.Severity == "WARN" {
			hasWarn = true
			reasons = append(reasons, "WARN-Regel ausgelöst")
			break
		}
	}

	if hasWarn || result.RiskScore > t.E1RiskThreshold {
		if result.RiskScore > t.E1RiskThreshold {
			reasons = append(reasons, "Risiko-Score 20-40")
		}
		return EscalationLevelE1, joinReasons(reasons, "Team-Lead Review erforderlich: ")
	}

	// E0: Auto-approve
	// - Only INFO rules
	// - Risk < 20
	return EscalationLevelE0, "Automatische Freigabe: Nur INFO-Regeln, niedriges Risiko"
}

// GetDefaultSLA returns the default SLA for an escalation level.
func GetDefaultSLA(level EscalationLevel) (responseHours, resolutionHours int) {
	switch level {
	case EscalationLevelE0:
		return 0, 0 // Auto-approve, no SLA
	case EscalationLevelE1:
		return 24, 72 // 1 day response, 3 days resolution
	case EscalationLevelE2:
		return 8, 48 // 8 hours response, 2 days resolution
	case EscalationLevelE3:
		return 4, 24 // 4 hours response, 1 day resolution (urgent)
	default:
		return 24, 72
	}
}

// GetRoleForLevel returns the required role for reviewing an escalation level.
func GetRoleForLevel(level EscalationLevel) string {
	switch level {
	case EscalationLevelE0:
		return "" // No review needed
	case EscalationLevelE1:
		return "team_lead"
	case EscalationLevelE2:
		return "dsb"
	case EscalationLevelE3:
		return "dsb" // DSB + Legal, but DSB is primary
	default:
		return "dsb"
	}
}

func joinReasons(reasons []string, prefix string) string {
	if len(reasons) == 0 {
		return prefix
	}
	result := prefix
	for i, r := range reasons {
		if i > 0 {
			result += "; "
		}
		result += r
	}
	return result
}

// CreateEscalationRequest is the request to create an escalation.
type CreateEscalationRequest struct {
	AssessmentID uuid.UUID `json:"assessment_id" binding:"required"`
}

// AssignEscalationRequest is the request to assign an escalation.
type AssignEscalationRequest struct {
	AssignedTo uuid.UUID `json:"assigned_to" binding:"required"`
}

// DecideEscalationRequest is the request to make a decision on an escalation.
type DecideEscalationRequest struct {
	Decision      EscalationDecision `json:"decision" binding:"required"`
	DecisionNotes string             `json:"decision_notes"`
	Conditions    []string           `json:"conditions,omitempty"`
}
