package handlers

import (
	"bytes"
	"fmt"
	"net/http"
	"time"

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

// Explain generates an LLM explanation for an assessment
func (h *UCCAHandlers) Explain(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

	var req ucca.ExplainRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		req.Language = "de"
	}
	if req.Language == "" {
		req.Language = "de"
	}

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

	// Get legal context from RAG
	var legalContext *ucca.LegalContext
	var legalContextStr string
	if h.legalRAGClient != nil {
		legalContext, err = h.legalRAGClient.GetLegalContextForAssessment(c.Request.Context(), assessment)
		if err != nil {
			fmt.Printf("Warning: Could not get legal context: %v\n", err)
		} else {
			legalContextStr = h.legalRAGClient.FormatLegalContextForPrompt(legalContext)
		}
	}

	prompt := buildExplanationPrompt(assessment, req.Language, legalContextStr)

	chatReq := &llm.ChatRequest{
		Messages: []llm.Message{
			{Role: "system", Content: "Du bist ein Datenschutz-Experte, der DSGVO-Compliance-Bewertungen erklärt. Antworte klar, präzise und auf Deutsch. Beziehe dich auf die angegebenen Rechtsgrundlagen."},
			{Role: "user", Content: prompt},
		},
		MaxTokens:   2000,
		Temperature: 0.3,
	}
	response, err := h.providerRegistry.Chat(c.Request.Context(), chatReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "LLM call failed: " + err.Error()})
		return
	}

	explanation := response.Message.Content
	model := response.Model

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

	c.JSON(http.StatusOK, ucca.ExplainResponse{
		ExplanationText: explanation,
		GeneratedAt:     time.Now().UTC(),
		Model:           model,
		LegalContext:    legalContext,
	})
}

// buildExplanationPrompt creates the prompt for the LLM explanation
func buildExplanationPrompt(assessment *ucca.Assessment, language string, legalContext string) string {
	var buf bytes.Buffer

	buf.WriteString("Erkläre die folgende DSGVO-Compliance-Bewertung für einen KI-Use-Case in verständlicher Sprache:\n\n")

	buf.WriteString(fmt.Sprintf("**Ergebnis:** %s\n", assessment.Feasibility))
	buf.WriteString(fmt.Sprintf("**Risikostufe:** %s\n", assessment.RiskLevel))
	buf.WriteString(fmt.Sprintf("**Risiko-Score:** %d/100\n", assessment.RiskScore))
	buf.WriteString(fmt.Sprintf("**Komplexität:** %s\n\n", assessment.Complexity))

	if len(assessment.TriggeredRules) > 0 {
		buf.WriteString("**Ausgelöste Regeln:**\n")
		for _, r := range assessment.TriggeredRules {
			buf.WriteString(fmt.Sprintf("- %s (%s): %s\n", r.Code, r.Severity, r.Title))
		}
		buf.WriteString("\n")
	}

	if len(assessment.RequiredControls) > 0 {
		buf.WriteString("**Erforderliche Maßnahmen:**\n")
		for _, ctrl := range assessment.RequiredControls {
			buf.WriteString(fmt.Sprintf("- %s: %s\n", ctrl.Title, ctrl.Description))
		}
		buf.WriteString("\n")
	}

	if assessment.DSFARecommended {
		buf.WriteString("**Hinweis:** Eine Datenschutz-Folgenabschätzung (DSFA) wird empfohlen.\n\n")
	}

	if assessment.Art22Risk {
		buf.WriteString("**Warnung:** Es besteht ein Risiko unter Art. 22 DSGVO (automatisierte Einzelentscheidungen).\n\n")
	}

	if legalContext != "" {
		buf.WriteString(legalContext)
	}

	buf.WriteString("\nBitte erkläre:\n")
	buf.WriteString("1. Warum dieses Ergebnis zustande kam (mit Bezug auf die angegebenen Rechtsgrundlagen)\n")
	buf.WriteString("2. Welche konkreten Schritte unternommen werden sollten\n")
	buf.WriteString("3. Welche Alternativen es gibt, falls der Use Case abgelehnt wurde\n")
	buf.WriteString("4. Welche spezifischen Artikel aus DSGVO/AI Act beachtet werden müssen\n")

	return buf.String()
}

// Export exports an assessment as JSON or Markdown
func (h *UCCAHandlers) Export(c *gin.Context) {
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid ID"})
		return
	}

	format := c.DefaultQuery("format", "json")

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

	if format == "md" {
		markdown := generateMarkdownExport(assessment)
		c.Header("Content-Type", "text/markdown; charset=utf-8")
		c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=ucca_assessment_%s.md", id.String()[:8]))
		c.Data(http.StatusOK, "text/markdown; charset=utf-8", []byte(markdown))
		return
	}

	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=ucca_assessment_%s.json", id.String()[:8]))
	c.JSON(http.StatusOK, gin.H{
		"exported_at": time.Now().UTC().Format(time.RFC3339),
		"assessment":  assessment,
	})
}

// generateMarkdownExport creates a Markdown export of the assessment
func generateMarkdownExport(a *ucca.Assessment) string {
	var buf bytes.Buffer

	buf.WriteString("# UCCA Use-Case Assessment\n\n")
	buf.WriteString(fmt.Sprintf("**ID:** %s\n", a.ID.String()))
	buf.WriteString(fmt.Sprintf("**Erstellt:** %s\n", a.CreatedAt.Format("02.01.2006 15:04")))
	buf.WriteString(fmt.Sprintf("**Domain:** %s\n\n", a.Domain))

	buf.WriteString("## Ergebnis\n\n")
	buf.WriteString("| Kriterium | Wert |\n")
	buf.WriteString("|-----------|------|\n")
	buf.WriteString(fmt.Sprintf("| Machbarkeit | **%s** |\n", a.Feasibility))
	buf.WriteString(fmt.Sprintf("| Risikostufe | %s |\n", a.RiskLevel))
	buf.WriteString(fmt.Sprintf("| Risiko-Score | %d/100 |\n", a.RiskScore))
	buf.WriteString(fmt.Sprintf("| Komplexität | %s |\n", a.Complexity))
	buf.WriteString(fmt.Sprintf("| DSFA empfohlen | %t |\n", a.DSFARecommended))
	buf.WriteString(fmt.Sprintf("| Art. 22 Risiko | %t |\n", a.Art22Risk))
	buf.WriteString(fmt.Sprintf("| Training erlaubt | %s |\n\n", a.TrainingAllowed))

	if len(a.TriggeredRules) > 0 {
		buf.WriteString("## Ausgelöste Regeln\n\n")
		buf.WriteString("| Code | Titel | Schwere | Score |\n")
		buf.WriteString("|------|-------|---------|-------|\n")
		for _, r := range a.TriggeredRules {
			buf.WriteString(fmt.Sprintf("| %s | %s | %s | +%d |\n", r.Code, r.Title, r.Severity, r.ScoreDelta))
		}
		buf.WriteString("\n")
	}

	if len(a.RequiredControls) > 0 {
		buf.WriteString("## Erforderliche Kontrollen\n\n")
		for _, ctrl := range a.RequiredControls {
			buf.WriteString(fmt.Sprintf("### %s\n", ctrl.Title))
			buf.WriteString(fmt.Sprintf("%s\n\n", ctrl.Description))
			if ctrl.GDPRRef != "" {
				buf.WriteString(fmt.Sprintf("*Referenz: %s*\n\n", ctrl.GDPRRef))
			}
		}
	}

	if len(a.RecommendedArchitecture) > 0 {
		buf.WriteString("## Empfohlene Architektur-Patterns\n\n")
		for _, p := range a.RecommendedArchitecture {
			buf.WriteString(fmt.Sprintf("### %s\n", p.Title))
			buf.WriteString(fmt.Sprintf("%s\n\n", p.Description))
		}
	}

	if len(a.ForbiddenPatterns) > 0 {
		buf.WriteString("## Verbotene Patterns\n\n")
		for _, p := range a.ForbiddenPatterns {
			buf.WriteString(fmt.Sprintf("### %s\n", p.Title))
			buf.WriteString(fmt.Sprintf("**Grund:** %s\n\n", p.Reason))
		}
	}

	if a.ExplanationText != nil && *a.ExplanationText != "" {
		buf.WriteString("## KI-Erklärung\n\n")
		buf.WriteString(*a.ExplanationText)
		buf.WriteString("\n\n")
	}

	buf.WriteString("---\n")
	buf.WriteString(fmt.Sprintf("*Generiert mit UCCA Policy Version %s*\n", a.PolicyVersion))

	return buf.String()
}

// truncateText truncates a string to maxLen characters
func truncateText(text string, maxLen int) string {
	if len(text) <= maxLen {
		return text
	}
	return text[:maxLen] + "..."
}
