package handlers

import (
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"

	"github.com/breakpilot/ai-compliance-sdk/internal/rbac"
	"github.com/breakpilot/ai-compliance-sdk/internal/ucca"
)

// ObligationsHandlers handles API requests for the generic obligations framework
type ObligationsHandlers struct {
	registry *ucca.ObligationsRegistry
	store    *ucca.ObligationsStore // Optional: for persisting assessments
}

// NewObligationsHandlers creates a new ObligationsHandlers instance
func NewObligationsHandlers() *ObligationsHandlers {
	return &ObligationsHandlers{
		registry: ucca.NewObligationsRegistry(),
	}
}

// NewObligationsHandlersWithStore creates a new ObligationsHandlers with a store
func NewObligationsHandlersWithStore(store *ucca.ObligationsStore) *ObligationsHandlers {
	return &ObligationsHandlers{
		registry: ucca.NewObligationsRegistry(),
		store:    store,
	}
}

// RegisterRoutes registers all obligations-related routes
func (h *ObligationsHandlers) RegisterRoutes(r *gin.RouterGroup) {
	obligations := r.Group("/obligations")
	{
		// Assessment endpoints
		obligations.POST("/assess", h.AssessObligations)
		obligations.GET("/:assessmentId", h.GetAssessment)

		// Grouping/filtering endpoints
		obligations.GET("/:assessmentId/by-regulation", h.GetByRegulation)
		obligations.GET("/:assessmentId/by-deadline", h.GetByDeadline)
		obligations.GET("/:assessmentId/by-responsible", h.GetByResponsible)

		// Export endpoints
		obligations.POST("/export/memo", h.ExportMemo)
		obligations.POST("/export/direct", h.ExportMemoFromOverview)

		// Metadata endpoints
		obligations.GET("/regulations", h.ListRegulations)
		obligations.GET("/regulations/:regulationId/decision-tree", h.GetDecisionTree)

		// Quick check endpoint (no persistence)
		obligations.POST("/quick-check", h.QuickCheck)
	}
}

// AssessObligations assesses which obligations apply based on provided facts
// POST /sdk/v1/ucca/obligations/assess
func (h *ObligationsHandlers) AssessObligations(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Tenant ID required"})
		return
	}

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

	if req.Facts == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Facts are required"})
		return
	}

	// Evaluate all regulations against the facts
	overview := h.registry.EvaluateAll(tenantID, req.Facts, req.OrganizationName)

	// Generate warnings if any
	var warnings []string
	if len(overview.ApplicableRegulations) == 0 {
		warnings = append(warnings, "Keine der konfigurierten Regulierungen scheint anwendbar zu sein. Bitte prüfen Sie die eingegebenen Daten.")
	}
	if overview.ExecutiveSummary.OverdueObligations > 0 {
		warnings = append(warnings, "Es gibt überfällige Pflichten, die sofortige Aufmerksamkeit erfordern.")
	}

	// Optionally persist the assessment
	if h.store != nil {
		assessment := &ucca.ObligationsAssessment{
			ID:               overview.ID,
			TenantID:         tenantID,
			OrganizationName: req.OrganizationName,
			Facts:            req.Facts,
			Overview:         overview,
			Status:           "completed",
			CreatedAt:        time.Now(),
			UpdatedAt:        time.Now(),
			CreatedBy:        rbac.GetUserID(c),
		}
		if err := h.store.CreateAssessment(c.Request.Context(), assessment); err != nil {
			// Log but don't fail - assessment was still generated
			c.Set("store_error", err.Error())
		}
	}

	c.JSON(http.StatusOK, ucca.ObligationsAssessResponse{
		Overview: overview,
		Warnings: warnings,
	})
}

// GetAssessment retrieves a stored assessment by ID
// GET /sdk/v1/ucca/obligations/:assessmentId
func (h *ObligationsHandlers) GetAssessment(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	assessmentID := c.Param("assessmentId")

	if h.store == nil {
		c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"})
		return
	}

	id, err := uuid.Parse(assessmentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"})
		return
	}

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

	c.JSON(http.StatusOK, assessment.Overview)
}

// GetByRegulation returns obligations grouped by regulation
// GET /sdk/v1/ucca/obligations/:assessmentId/by-regulation
func (h *ObligationsHandlers) GetByRegulation(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	assessmentID := c.Param("assessmentId")

	if h.store == nil {
		c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"})
		return
	}

	id, err := uuid.Parse(assessmentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"})
		return
	}

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

	grouped := h.registry.GroupByRegulation(assessment.Overview.Obligations)

	c.JSON(http.StatusOK, ucca.ObligationsByRegulationResponse{
		Regulations: grouped,
	})
}

// GetByDeadline returns obligations grouped by deadline timeframe
// GET /sdk/v1/ucca/obligations/:assessmentId/by-deadline
func (h *ObligationsHandlers) GetByDeadline(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	assessmentID := c.Param("assessmentId")

	if h.store == nil {
		c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"})
		return
	}

	id, err := uuid.Parse(assessmentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"})
		return
	}

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

	grouped := h.registry.GroupByDeadline(assessment.Overview.Obligations)

	c.JSON(http.StatusOK, grouped)
}

// GetByResponsible returns obligations grouped by responsible role
// GET /sdk/v1/ucca/obligations/:assessmentId/by-responsible
func (h *ObligationsHandlers) GetByResponsible(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	assessmentID := c.Param("assessmentId")

	if h.store == nil {
		c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"})
		return
	}

	id, err := uuid.Parse(assessmentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"})
		return
	}

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

	grouped := h.registry.GroupByResponsible(assessment.Overview.Obligations)

	c.JSON(http.StatusOK, ucca.ObligationsByResponsibleResponse{
		ByRole: grouped,
	})
}

// ExportMemo exports the obligations overview as a C-Level memo
// POST /sdk/v1/ucca/obligations/export/memo
func (h *ObligationsHandlers) ExportMemo(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)

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

	if h.store == nil {
		c.JSON(http.StatusNotImplemented, gin.H{"error": "Persistence not configured"})
		return
	}

	id, err := uuid.Parse(req.AssessmentID)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid assessment ID"})
		return
	}

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

	// Create exporter
	exporter := ucca.NewPDFExporter(req.Language)

	// Generate export based on format
	var response *ucca.ExportMemoResponse
	switch req.Format {
	case "pdf":
		response, err = exporter.ExportManagementMemo(assessment.Overview)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate PDF", "details": err.Error()})
			return
		}
	case "markdown", "":
		response, err = exporter.ExportMarkdown(assessment.Overview)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate Markdown", "details": err.Error()})
			return
		}
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid format. Use 'markdown' or 'pdf'"})
		return
	}

	c.JSON(http.StatusOK, response)
}

// ExportMemoFromOverview exports an overview directly (without persistence)
// POST /sdk/v1/ucca/obligations/export/direct
func (h *ObligationsHandlers) ExportMemoFromOverview(c *gin.Context) {
	var req struct {
		Overview *ucca.ManagementObligationsOverview `json:"overview"`
		Format   string                               `json:"format"` // "markdown" or "pdf"
		Language string                               `json:"language,omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	if req.Overview == nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Overview is required"})
		return
	}

	exporter := ucca.NewPDFExporter(req.Language)

	var response *ucca.ExportMemoResponse
	var err error
	switch req.Format {
	case "pdf":
		response, err = exporter.ExportManagementMemo(req.Overview)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate PDF", "details": err.Error()})
			return
		}
	case "markdown", "":
		response, err = exporter.ExportMarkdown(req.Overview)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate Markdown", "details": err.Error()})
			return
		}
	default:
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid format. Use 'markdown' or 'pdf'"})
		return
	}

	c.JSON(http.StatusOK, response)
}

// ListRegulations returns all available regulation modules
// GET /sdk/v1/ucca/obligations/regulations
func (h *ObligationsHandlers) ListRegulations(c *gin.Context) {
	modules := h.registry.ListModules()

	c.JSON(http.StatusOK, ucca.AvailableRegulationsResponse{
		Regulations: modules,
	})
}

// GetDecisionTree returns the decision tree for a specific regulation
// GET /sdk/v1/ucca/obligations/regulations/:regulationId/decision-tree
func (h *ObligationsHandlers) GetDecisionTree(c *gin.Context) {
	regulationID := c.Param("regulationId")

	tree, err := h.registry.GetDecisionTree(regulationID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, tree)
}

// QuickCheck performs a quick obligations check without persistence
// POST /sdk/v1/ucca/obligations/quick-check
func (h *ObligationsHandlers) QuickCheck(c *gin.Context) {
	var req struct {
		// Organization basics
		EmployeeCount     int     `json:"employee_count"`
		AnnualRevenue     float64 `json:"annual_revenue"`
		BalanceSheetTotal float64 `json:"balance_sheet_total,omitempty"`
		Country           string  `json:"country"`

		// Sector
		PrimarySector   string   `json:"primary_sector"`
		SpecialServices []string `json:"special_services,omitempty"`
		IsKRITIS        bool     `json:"is_kritis,omitempty"`

		// Quick flags
		ProcessesPersonalData bool `json:"processes_personal_data,omitempty"`
		UsesAI                bool `json:"uses_ai,omitempty"`
		IsFinancialInstitution bool `json:"is_financial_institution,omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
		return
	}

	// Build UnifiedFacts from quick check request
	facts := &ucca.UnifiedFacts{
		Organization: ucca.OrganizationFacts{
			EmployeeCount:     req.EmployeeCount,
			AnnualRevenue:     req.AnnualRevenue,
			BalanceSheetTotal: req.BalanceSheetTotal,
			Country:           req.Country,
			EUMember:          isEUCountry(req.Country),
		},
		Sector: ucca.SectorFacts{
			PrimarySector:          req.PrimarySector,
			SpecialServices:        req.SpecialServices,
			IsKRITIS:               req.IsKRITIS,
			KRITISThresholdMet:     req.IsKRITIS,
			IsFinancialInstitution: req.IsFinancialInstitution,
		},
		DataProtection: ucca.DataProtectionFacts{
			ProcessesPersonalData: req.ProcessesPersonalData,
		},
		AIUsage: ucca.AIUsageFacts{
			UsesAI: req.UsesAI,
		},
		Financial: ucca.FinancialFacts{
			IsRegulated: req.IsFinancialInstitution,
		},
	}

	// Quick evaluation
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		tenantID = uuid.New() // Generate temporary ID for quick check
	}

	overview := h.registry.EvaluateAll(tenantID, facts, "")

	// Return simplified result
	c.JSON(http.StatusOK, gin.H{
		"applicable_regulations": overview.ApplicableRegulations,
		"total_obligations":      len(overview.Obligations),
		"critical_obligations":   overview.ExecutiveSummary.CriticalObligations,
		"sanctions_summary":      overview.SanctionsSummary,
		"executive_summary":      overview.ExecutiveSummary,
	})
}

// ============================================================================
// Helper Functions
// ============================================================================

func generateMemoMarkdown(overview *ucca.ManagementObligationsOverview) string {
	content := "# Pflichten-Übersicht für die Geschäftsführung\n\n"
	content += "**Datum:** " + overview.AssessmentDate.Format("02.01.2006") + "\n"
	if overview.OrganizationName != "" {
		content += "**Organisation:** " + overview.OrganizationName + "\n"
	}
	content += "\n---\n\n"

	// Executive Summary
	content += "## Executive Summary\n\n"
	content += "| Kennzahl | Wert |\n"
	content += "|----------|------|\n"
	content += "| Anwendbare Regulierungen | " + itoa(overview.ExecutiveSummary.TotalRegulations) + " |\n"
	content += "| Gesamtzahl Pflichten | " + itoa(overview.ExecutiveSummary.TotalObligations) + " |\n"
	content += "| Kritische Pflichten | " + itoa(overview.ExecutiveSummary.CriticalObligations) + " |\n"
	content += "| Überfällige Pflichten | " + itoa(overview.ExecutiveSummary.OverdueObligations) + " |\n"
	content += "| Anstehende Fristen (30 Tage) | " + itoa(overview.ExecutiveSummary.UpcomingDeadlines) + " |\n"
	content += "\n"

	// Key Risks
	if len(overview.ExecutiveSummary.KeyRisks) > 0 {
		content += "### Hauptrisiken\n\n"
		for _, risk := range overview.ExecutiveSummary.KeyRisks {
			content += "- ⚠️ " + risk + "\n"
		}
		content += "\n"
	}

	// Recommended Actions
	if len(overview.ExecutiveSummary.RecommendedActions) > 0 {
		content += "### Empfohlene Maßnahmen\n\n"
		for i, action := range overview.ExecutiveSummary.RecommendedActions {
			content += itoa(i+1) + ". " + action + "\n"
		}
		content += "\n"
	}

	// Applicable Regulations
	content += "## Anwendbare Regulierungen\n\n"
	for _, reg := range overview.ApplicableRegulations {
		content += "### " + reg.Name + "\n\n"
		content += "- **Klassifizierung:** " + reg.Classification + "\n"
		content += "- **Begründung:** " + reg.Reason + "\n"
		content += "- **Anzahl Pflichten:** " + itoa(reg.ObligationCount) + "\n"
		content += "\n"
	}

	// Sanctions Summary
	content += "## Sanktionsrisiken\n\n"
	content += overview.SanctionsSummary.Summary + "\n\n"
	if overview.SanctionsSummary.MaxFinancialRisk != "" {
		content += "- **Maximales Bußgeld:** " + overview.SanctionsSummary.MaxFinancialRisk + "\n"
	}
	if overview.SanctionsSummary.PersonalLiabilityRisk {
		content += "- **Persönliche Haftung:** Ja ⚠️\n"
	}
	content += "\n"

	// Critical Obligations
	content += "## Kritische Pflichten\n\n"
	for _, obl := range overview.Obligations {
		if obl.Priority == ucca.PriorityCritical {
			content += "### " + obl.ID + ": " + obl.Title + "\n\n"
			content += obl.Description + "\n\n"
			content += "- **Verantwortlich:** " + string(obl.Responsible) + "\n"
			if obl.Deadline != nil {
				if obl.Deadline.Date != nil {
					content += "- **Frist:** " + obl.Deadline.Date.Format("02.01.2006") + "\n"
				} else if obl.Deadline.Duration != "" {
					content += "- **Frist:** " + obl.Deadline.Duration + "\n"
				}
			}
			if obl.Sanctions != nil && obl.Sanctions.MaxFine != "" {
				content += "- **Sanktion:** " + obl.Sanctions.MaxFine + "\n"
			}
			content += "\n"
		}
	}

	// Incident Deadlines
	if len(overview.IncidentDeadlines) > 0 {
		content += "## Meldepflichten bei Sicherheitsvorfällen\n\n"
		content += "| Phase | Frist | Empfänger |\n"
		content += "|-------|-------|-----------|\n"
		for _, deadline := range overview.IncidentDeadlines {
			content += "| " + deadline.Phase + " | " + deadline.Deadline + " | " + deadline.Recipient + " |\n"
		}
		content += "\n"
	}

	content += "---\n\n"
	content += "*Dieses Dokument wurde automatisch generiert und ersetzt keine Rechtsberatung.*\n"

	return content
}

func isEUCountry(country string) bool {
	euCountries := map[string]bool{
		"DE": true, "AT": true, "BE": true, "BG": true, "HR": true, "CY": true,
		"CZ": true, "DK": true, "EE": true, "FI": true, "FR": true, "GR": true,
		"HU": true, "IE": true, "IT": true, "LV": true, "LT": true, "LU": true,
		"MT": true, "NL": true, "PL": true, "PT": true, "RO": true, "SK": true,
		"SI": true, "ES": true, "SE": true,
	}
	return euCountries[country]
}

func itoa(i int) string {
	return strconv.Itoa(i)
}
