package handlers

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/breakpilot/ai-compliance-sdk/internal/llm"
	"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"
)

// UCCAHandlers handles UCCA-related API endpoints
type UCCAHandlers struct {
	store            *ucca.Store
	escalationStore  *ucca.EscalationStore
	policyEngine     *ucca.PolicyEngine
	legacyRuleEngine *ucca.RuleEngine // Keep for backwards compatibility
	providerRegistry *llm.ProviderRegistry
	legalRAGClient   *ucca.LegalRAGClient
	escalationTrigger *ucca.EscalationTrigger
}

// NewUCCAHandlers creates new UCCA handlers
func NewUCCAHandlers(store *ucca.Store, escalationStore *ucca.EscalationStore, providerRegistry *llm.ProviderRegistry) *UCCAHandlers {
	// Try to create YAML-based policy engine first
	policyEngine, err := ucca.NewPolicyEngine()
	if err != nil {
		// Log warning but don't fail - fall back to legacy engine
		fmt.Printf("Warning: Could not load YAML policy engine: %v. Falling back to legacy rules.\n", err)
	}

	return &UCCAHandlers{
		store:            store,
		escalationStore:  escalationStore,
		policyEngine:     policyEngine, // May be nil if YAML loading failed
		legacyRuleEngine: ucca.NewRuleEngine(),
		providerRegistry: providerRegistry,
		legalRAGClient:   ucca.NewLegalRAGClient(),
		escalationTrigger: ucca.DefaultEscalationTrigger(),
	}
}

// ============================================================================
// POST /sdk/v1/ucca/assess - Evaluate a use case
// ============================================================================

// Assess evaluates a use case intake and creates an assessment
func (h *UCCAHandlers) Assess(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 intake ucca.UseCaseIntake
	if err := c.ShouldBindJSON(&intake); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Run evaluation - prefer YAML-based policy engine if available
	var result *ucca.AssessmentResult
	var policyVersion string
	if h.policyEngine != nil {
		result = h.policyEngine.Evaluate(&intake)
		policyVersion = h.policyEngine.GetPolicyVersion()
	} else {
		result = h.legacyRuleEngine.Evaluate(&intake)
		policyVersion = "1.0.0-legacy"
	}

	// Calculate hash of use case text
	hash := sha256.Sum256([]byte(intake.UseCaseText))
	hashStr := hex.EncodeToString(hash[:])

	// Create assessment record
	assessment := &ucca.Assessment{
		TenantID:                tenantID,
		Title:                   intake.Title,
		PolicyVersion:           policyVersion,
		Status:                  "completed",
		Intake:                  intake,
		UseCaseTextStored:       intake.StoreRawText,
		UseCaseTextHash:         hashStr,
		Feasibility:             result.Feasibility,
		RiskLevel:               result.RiskLevel,
		Complexity:              result.Complexity,
		RiskScore:               result.RiskScore,
		TriggeredRules:          result.TriggeredRules,
		RequiredControls:        result.RequiredControls,
		RecommendedArchitecture: result.RecommendedArchitecture,
		ForbiddenPatterns:       result.ForbiddenPatterns,
		ExampleMatches:          result.ExampleMatches,
		DSFARecommended:         result.DSFARecommended,
		Art22Risk:               result.Art22Risk,
		TrainingAllowed:         result.TrainingAllowed,
		Domain:                  intake.Domain,
		CreatedBy:               userID,
	}

	// Clear use case text if not opted in to store
	if !intake.StoreRawText {
		assessment.Intake.UseCaseText = ""
	}

	// Generate title if not provided
	if assessment.Title == "" {
		assessment.Title = fmt.Sprintf("Assessment vom %s", time.Now().Format("02.01.2006 15:04"))
	}

	// Save to database
	if err := h.store.CreateAssessment(c.Request.Context(), assessment); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// Automatically create escalation based on assessment result
	var escalation *ucca.Escalation
	if h.escalationStore != nil && h.escalationTrigger != nil {
		level, reason := h.escalationTrigger.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
		}

		escalation = &ucca.Escalation{
			TenantID:         tenantID,
			AssessmentID:     assessment.ID,
			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.escalationStore.CreateEscalation(c.Request.Context(), escalation); err != nil {
			// Log error but don't fail the assessment creation
			fmt.Printf("Warning: Could not create escalation: %v\n", err)
			escalation = nil
		} else {
			// Add history entry
			h.escalationStore.AddEscalationHistory(c.Request.Context(), &ucca.EscalationHistory{
				EscalationID: escalation.ID,
				Action:       "auto_created",
				NewStatus:    string(escalation.Status),
				NewLevel:     string(escalation.EscalationLevel),
				ActorID:      userID,
				Notes:        "Automatisch erstellt bei Assessment",
			})

			// For E1/E2/E3, try to auto-assign
			if level != ucca.EscalationLevelE0 {
				role := ucca.GetRoleForLevel(level)
				reviewer, err := h.escalationStore.GetNextAvailableReviewer(c.Request.Context(), tenantID, role)
				if err == nil && reviewer != nil {
					h.escalationStore.AssignEscalation(c.Request.Context(), escalation.ID, reviewer.UserID, role)
					h.escalationStore.IncrementReviewerCount(c.Request.Context(), reviewer.UserID)
					h.escalationStore.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, ucca.AssessResponse{
		Assessment: *assessment,
		Result:     *result,
		Escalation: escalation,
	})
}

// ============================================================================
// GET /sdk/v1/ucca/assessments - List all assessments
// ============================================================================

// ListAssessments returns all assessments for a tenant
func (h *UCCAHandlers) ListAssessments(c *gin.Context) {
	tenantID := rbac.GetTenantID(c)
	if tenantID == uuid.Nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "tenant ID required"})
		return
	}

	filters := &ucca.AssessmentFilters{
		Feasibility: c.Query("feasibility"),
		Domain:      c.Query("domain"),
		RiskLevel:   c.Query("risk_level"),
	}

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

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

// ============================================================================
// GET /sdk/v1/ucca/assessments/:id - Get single assessment
// ============================================================================

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

	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
	}

	c.JSON(http.StatusOK, assessment)
}

// ============================================================================
// DELETE /sdk/v1/ucca/assessments/:id - Delete assessment
// ============================================================================

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

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

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

// ============================================================================
// GET /sdk/v1/ucca/patterns - Get pattern catalog
// ============================================================================

// ListPatterns returns all available architecture patterns
func (h *UCCAHandlers) ListPatterns(c *gin.Context) {
	var response []gin.H

	// Prefer YAML-based patterns if available
	if h.policyEngine != nil {
		yamlPatterns := h.policyEngine.GetAllPatterns()
		response = make([]gin.H, 0, len(yamlPatterns))
		for _, p := range yamlPatterns {
			response = append(response, gin.H{
				"id":             p.ID,
				"title":          p.Title,
				"description":    p.Description,
				"benefit":        p.Benefit,
				"effort":         p.Effort,
				"risk_reduction": p.RiskReduction,
			})
		}
	} else {
		// Fall back to legacy patterns
		patterns := ucca.GetAllPatterns()
		response = make([]gin.H, len(patterns))
		for i, p := range patterns {
			response[i] = gin.H{
				"id":             p.ID,
				"title":          p.Title,
				"title_de":       p.TitleDE,
				"description":    p.Description,
				"description_de": p.DescriptionDE,
				"benefits":       p.Benefits,
				"requirements":   p.Requirements,
			}
		}
	}

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

// ============================================================================
// GET /sdk/v1/ucca/controls - Get control catalog
// ============================================================================

// ListControls returns all available compliance controls
func (h *UCCAHandlers) ListControls(c *gin.Context) {
	var response []gin.H

	// Prefer YAML-based controls if available
	if h.policyEngine != nil {
		yamlControls := h.policyEngine.GetAllControls()
		response = make([]gin.H, 0, len(yamlControls))
		for _, ctrl := range yamlControls {
			response = append(response, gin.H{
				"id":          ctrl.ID,
				"title":       ctrl.Title,
				"description": ctrl.Description,
				"gdpr_ref":    ctrl.GDPRRef,
				"effort":      ctrl.Effort,
			})
		}
	} else {
		// Fall back to legacy controls
		for id, ctrl := range ucca.ControlLibrary {
			response = append(response, gin.H{
				"id":          id,
				"title":       ctrl.Title,
				"description": ctrl.Description,
				"severity":    ctrl.Severity,
				"category":    ctrl.Category,
				"gdpr_ref":    ctrl.GDPRRef,
			})
		}
	}

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

// ============================================================================
// GET /sdk/v1/ucca/problem-solutions - Get problem-solution mappings
// ============================================================================

// ListProblemSolutions returns all problem-solution mappings
func (h *UCCAHandlers) ListProblemSolutions(c *gin.Context) {
	if h.policyEngine == nil {
		c.JSON(http.StatusOK, gin.H{
			"problem_solutions": []gin.H{},
			"message":           "Problem-solutions only available with YAML policy engine",
		})
		return
	}

	problemSolutions := h.policyEngine.GetProblemSolutions()
	response := make([]gin.H, len(problemSolutions))
	for i, ps := range problemSolutions {
		solutions := make([]gin.H, len(ps.Solutions))
		for j, sol := range ps.Solutions {
			solutions[j] = gin.H{
				"id":              sol.ID,
				"title":           sol.Title,
				"pattern":         sol.Pattern,
				"control":         sol.Control,
				"removes_problem": sol.RemovesProblem,
				"team_question":   sol.TeamQuestion,
			}
		}

		triggers := make([]gin.H, len(ps.Triggers))
		for j, t := range ps.Triggers {
			triggers[j] = gin.H{
				"rule":            t.Rule,
				"without_control": t.WithoutControl,
			}
		}

		response[i] = gin.H{
			"problem_id": ps.ProblemID,
			"title":      ps.Title,
			"triggers":   triggers,
			"solutions":  solutions,
		}
	}

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

// ============================================================================
// GET /sdk/v1/ucca/examples - Get example catalog
// ============================================================================

// ListExamples returns all available didactic examples
func (h *UCCAHandlers) ListExamples(c *gin.Context) {
	examples := ucca.GetAllExamples()

	// Convert to API response format
	response := make([]gin.H, len(examples))
	for i, ex := range examples {
		response[i] = gin.H{
			"id":           ex.ID,
			"title":        ex.Title,
			"title_de":     ex.TitleDE,
			"description":  ex.Description,
			"description_de": ex.DescriptionDE,
			"domain":       ex.Domain,
			"outcome":      ex.Outcome,
			"outcome_de":   ex.OutcomeDE,
			"lessons":      ex.Lessons,
			"lessons_de":   ex.LessonsDE,
		}
	}

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

// ============================================================================
// GET /sdk/v1/ucca/rules - Get all rules (transparency)
// ============================================================================

// ListRules returns all rules for transparency
func (h *UCCAHandlers) ListRules(c *gin.Context) {
	var response []gin.H
	var policyVersion string

	// Prefer YAML-based rules if available
	if h.policyEngine != nil {
		yamlRules := h.policyEngine.GetAllRules()
		policyVersion = h.policyEngine.GetPolicyVersion()
		response = make([]gin.H, len(yamlRules))
		for i, r := range yamlRules {
			response[i] = gin.H{
				"code":        r.ID,
				"category":    r.Category,
				"title":       r.Title,
				"description": r.Description,
				"severity":    r.Severity,
				"gdpr_ref":    r.GDPRRef,
				"rationale":   r.Rationale,
				"controls":    r.Effect.ControlsAdd,
				"patterns":    r.Effect.SuggestedPatterns,
				"risk_add":    r.Effect.RiskAdd,
			}
		}
	} else {
		// Fall back to legacy rules
		rules := h.legacyRuleEngine.GetRules()
		policyVersion = "1.0.0-legacy"
		response = make([]gin.H, len(rules))
		for i, r := range rules {
			response[i] = gin.H{
				"code":          r.Code,
				"category":      r.Category,
				"title":         r.Title,
				"title_de":      r.TitleDE,
				"description":   r.Description,
				"description_de": r.DescriptionDE,
				"severity":      r.Severity,
				"score_delta":   r.ScoreDelta,
				"gdpr_ref":      r.GDPRRef,
				"controls":      r.Controls,
				"patterns":      r.Patterns,
			}
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"rules":          response,
		"total":          len(response),
		"policy_version": policyVersion,
		"categories": []string{
			"A. Datenklassifikation",
			"B. Zweck & Rechtsgrundlage",
			"C. Automatisierung",
			"D. Training & Modell",
			"E. Hosting",
			"F. Domain-spezifisch",
			"G. Aggregation",
		},
	})
}

// ============================================================================
// POST /sdk/v1/ucca/assessments/:id/explain - Generate LLM explanation
// ============================================================================

// 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 {
		// Default to German
		req.Language = "de"
	}
	if req.Language == "" {
		req.Language = "de"
	}

	// Get assessment
	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 {
			// Log error but continue without legal context
			fmt.Printf("Warning: Could not get legal context: %v\n", err)
		} else {
			legalContextStr = h.legalRAGClient.FormatLegalContextForPrompt(legalContext)
		}
	}

	// Build prompt for LLM with legal context
	prompt := buildExplanationPrompt(assessment, req.Language, legalContextStr)

	// Call LLM
	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

	// Save explanation to database
	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 _, c := range assessment.RequiredControls {
			buf.WriteString(fmt.Sprintf("- %s: %s\n", c.Title, c.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")
	}

	// Include legal context from RAG if available
	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()
}

// ============================================================================
// GET /sdk/v1/ucca/export/:id - Export assessment
// ============================================================================

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

	// JSON export
	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(fmt.Sprintf("| 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 _, c := range a.RequiredControls {
			buf.WriteString(fmt.Sprintf("### %s\n", c.Title))
			buf.WriteString(fmt.Sprintf("%s\n\n", c.Description))
			if c.GDPRRef != "" {
				buf.WriteString(fmt.Sprintf("*Referenz: %s*\n\n", c.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()
}

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

// GetStats returns UCCA statistics for a tenant
func (h *UCCAHandlers) GetStats(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.GetStats(c.Request.Context(), tenantID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, stats)
}

// ============================================================================
// POST /sdk/v1/ucca/wizard/ask - Legal Assistant for Wizard
// ============================================================================

// WizardAskRequest represents a question to the Legal Assistant
type WizardAskRequest struct {
	Question    string `json:"question" binding:"required"`
	StepNumber  int    `json:"step_number"`
	FieldID     string `json:"field_id,omitempty"`     // Optional: Specific field context
	CurrentData map[string]interface{} `json:"current_data,omitempty"` // Current wizard answers
}

// WizardAskResponse represents the Legal Assistant response
type WizardAskResponse struct {
	Answer        string              `json:"answer"`
	Sources       []LegalSource       `json:"sources,omitempty"`
	RelatedFields []string            `json:"related_fields,omitempty"`
	GeneratedAt   time.Time           `json:"generated_at"`
	Model         string              `json:"model"`
}

// LegalSource represents a legal reference used in the answer
type LegalSource struct {
	Regulation string `json:"regulation"`
	Article    string `json:"article,omitempty"`
	Text       string `json:"text,omitempty"`
}

// AskWizardQuestion handles legal questions from the wizard
func (h *UCCAHandlers) AskWizardQuestion(c *gin.Context) {
	var req WizardAskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Build context-aware query for Legal RAG
	ragQuery := buildWizardRAGQuery(req)

	// Search legal corpus for relevant context
	var legalResults []ucca.LegalSearchResult
	var sources []LegalSource
	if h.legalRAGClient != nil {
		results, err := h.legalRAGClient.Search(c.Request.Context(), ragQuery, nil, 5)
		if err != nil {
			// Log but continue without RAG context
			fmt.Printf("Warning: Legal RAG search failed: %v\n", err)
		} else {
			legalResults = results
			// Convert to sources
			sources = make([]LegalSource, len(results))
			for i, r := range results {
				sources[i] = LegalSource{
					Regulation: r.RegulationName,
					Article:    r.Article,
					Text:       truncateText(r.Text, 200),
				}
			}
		}
	}

	// Build prompt for LLM
	prompt := buildWizardAssistantPrompt(req, legalResults)

	// Build system prompt with step context
	systemPrompt := buildWizardSystemPrompt(req.StepNumber)

	// Call LLM
	chatReq := &llm.ChatRequest{
		Messages: []llm.Message{
			{Role: "system", Content: systemPrompt},
			{Role: "user", Content: prompt},
		},
		MaxTokens:   1024,
		Temperature: 0.3, // Low temperature for precise legal answers
	}
	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
	}

	// Identify related wizard fields based on question
	relatedFields := identifyRelatedFields(req.Question)

	c.JSON(http.StatusOK, WizardAskResponse{
		Answer:        response.Message.Content,
		Sources:       sources,
		RelatedFields: relatedFields,
		GeneratedAt:   time.Now().UTC(),
		Model:         response.Model,
	})
}

// buildWizardRAGQuery creates an optimized query for Legal RAG search
func buildWizardRAGQuery(req WizardAskRequest) string {
	// Start with the user's question
	query := req.Question

	// Add context based on step number
	stepContext := map[int]string{
		1: "KI-Anwendung Use Case",
		2: "personenbezogene Daten Datenkategorien DSGVO Art. 4 Art. 9",
		3: "Verarbeitungszweck Profiling Scoring automatisierte Entscheidung Art. 22",
		4: "Hosting Cloud On-Premises Auftragsverarbeitung",
		5: "Standardvertragsklauseln SCC Drittlandtransfer TIA Transfer Impact Assessment Art. 44 Art. 46",
		6: "KI-Modell Training RAG Finetuning",
		7: "Auftragsverarbeitungsvertrag AVV DSFA Verarbeitungsverzeichnis Art. 28 Art. 30 Art. 35",
		8: "Automatisierung Human-in-the-Loop Art. 22 AI Act",
	}

	if context, ok := stepContext[req.StepNumber]; ok {
		query = query + " " + context
	}

	return query
}

// buildWizardSystemPrompt creates the system prompt for the Legal Assistant
func buildWizardSystemPrompt(stepNumber int) string {
	basePrompt := `Du bist ein freundlicher Rechtsassistent, der Nutzern hilft,
datenschutzrechtliche Begriffe und Anforderungen zu verstehen.

DEINE AUFGABE:
- Erkläre rechtliche Begriffe in einfacher, verständlicher Sprache
- Beantworte Fragen zum aktuellen Wizard-Schritt
- Hilf dem Nutzer, die richtigen Antworten im Wizard zu geben
- Verweise auf relevante Rechtsquellen (DSGVO-Artikel, etc.)

WICHTIGE REGELN:
- Antworte IMMER auf Deutsch
- Verwende einfache Sprache, keine Juristensprache
- Gib konkrete Beispiele wenn möglich
- Bei Unsicherheit empfehle die Rücksprache mit einem Datenschutzbeauftragten
- Du darfst KEINE Rechtsberatung geben, nur erklären

ANTWORT-FORMAT:
- Kurz und prägnant (max. 3-4 Sätze für einfache Fragen)
- Strukturiert mit Aufzählungen bei komplexen Themen
- Immer mit Quellenangabe am Ende (z.B. "Siehe: DSGVO Art. 9")`

	// Add step-specific context
	stepContexts := map[int]string{
		1: "\n\nKONTEXT: Der Nutzer befindet sich im ersten Schritt und gibt grundlegende Informationen zum KI-Vorhaben ein.",
		2: "\n\nKONTEXT: Der Nutzer gibt an, welche Datenarten verarbeitet werden. Erkläre die Unterschiede zwischen personenbezogenen Daten, Art. 9 Daten (besondere Kategorien), biometrischen Daten, etc.",
		3: "\n\nKONTEXT: Der Nutzer gibt den Verarbeitungszweck an. Erkläre Begriffe wie Profiling, Scoring, systematische Überwachung, automatisierte Entscheidungen mit rechtlicher Wirkung.",
		4: "\n\nKONTEXT: Der Nutzer gibt Hosting-Informationen an. Erkläre Cloud vs. On-Premises, wann Drittlandtransfer vorliegt, Unterschiede zwischen EU/EWR und Drittländern.",
		5: "\n\nKONTEXT: Der Nutzer beantwortet Fragen zu SCC und TIA. Erkläre Standardvertragsklauseln (SCC), Transfer Impact Assessment (TIA), das Data Privacy Framework (DPF), und wann welche Instrumente erforderlich sind.",
		6: "\n\nKONTEXT: Der Nutzer gibt KI-Modell-Informationen an. Erkläre RAG vs. Training/Finetuning, warum Training mit personenbezogenen Daten problematisch ist, und welche Opt-Out-Klauseln wichtig sind.",
		7: "\n\nKONTEXT: Der Nutzer beantwortet Fragen zu Verträgen. Erkläre den Auftragsverarbeitungsvertrag (AVV), die Datenschutz-Folgenabschätzung (DSFA), das Verarbeitungsverzeichnis (VVT), und wann diese erforderlich sind.",
		8: "\n\nKONTEXT: Der Nutzer gibt den Automatisierungsgrad an. Erkläre Human-in-the-Loop, Art. 22 DSGVO (automatisierte Einzelentscheidungen), und die Anforderungen des AI Acts.",
	}

	if context, ok := stepContexts[stepNumber]; ok {
		basePrompt += context
	}

	return basePrompt
}

// buildWizardAssistantPrompt creates the user prompt with legal context
func buildWizardAssistantPrompt(req WizardAskRequest, legalResults []ucca.LegalSearchResult) string {
	var buf bytes.Buffer

	buf.WriteString(fmt.Sprintf("FRAGE DES NUTZERS:\n%s\n\n", req.Question))

	// Add legal context if available
	if len(legalResults) > 0 {
		buf.WriteString("RELEVANTE RECHTSGRUNDLAGEN (aus unserer Bibliothek):\n\n")
		for i, result := range legalResults {
			buf.WriteString(fmt.Sprintf("%d. %s", i+1, result.RegulationName))
			if result.Article != "" {
				buf.WriteString(fmt.Sprintf(" - Art. %s", result.Article))
				if result.Paragraph != "" {
					buf.WriteString(fmt.Sprintf(" Abs. %s", result.Paragraph))
				}
			}
			buf.WriteString("\n")
			buf.WriteString(fmt.Sprintf("   %s\n\n", truncateText(result.Text, 300)))
		}
	}

	// Add field context if provided
	if req.FieldID != "" {
		buf.WriteString(fmt.Sprintf("AKTUELLES FELD: %s\n\n", req.FieldID))
	}

	buf.WriteString("Bitte beantworte die Frage kurz und verständlich. Verwende die angegebenen Rechtsgrundlagen als Referenz.")

	return buf.String()
}

// identifyRelatedFields identifies wizard fields related to the question
func identifyRelatedFields(question string) []string {
	question = strings.ToLower(question)
	var related []string

	// Map keywords to wizard field IDs
	keywordMapping := map[string][]string{
		"personenbezogen":     {"data_types.personal_data"},
		"art. 9":              {"data_types.article_9_data"},
		"sensibel":            {"data_types.article_9_data"},
		"gesundheit":          {"data_types.article_9_data"},
		"minderjährig":        {"data_types.minor_data"},
		"kinder":              {"data_types.minor_data"},
		"biometrisch":         {"data_types.biometric_data"},
		"gesicht":             {"data_types.biometric_data"},
		"kennzeichen":         {"data_types.license_plates"},
		"standort":            {"data_types.location_data"},
		"gps":                 {"data_types.location_data"},
		"profiling":           {"purpose.profiling"},
		"scoring":             {"purpose.evaluation_scoring"},
		"überwachung":         {"processing.systematic_monitoring"},
		"automatisch":         {"outputs.decision_with_legal_effect", "automation"},
		"entscheidung":        {"outputs.decision_with_legal_effect"},
		"cloud":               {"hosting.type", "hosting.region"},
		"on-premises":         {"hosting.type"},
		"lokal":               {"hosting.type"},
		"scc":                 {"contracts.scc.present", "contracts.scc.version"},
		"standardvertrags":    {"contracts.scc.present"},
		"drittland":           {"hosting.region", "provider.location"},
		"usa":                 {"hosting.region", "provider.location", "provider.dpf_certified"},
		"transfer":            {"hosting.region", "contracts.tia.present"},
		"tia":                 {"contracts.tia.present", "contracts.tia.result"},
		"dpf":                 {"provider.dpf_certified"},
		"data privacy":        {"provider.dpf_certified"},
		"avv":                 {"contracts.avv.present"},
		"auftragsverarbeitung": {"contracts.avv.present"},
		"dsfa":                {"governance.dsfa_completed"},
		"folgenabschätzung":   {"governance.dsfa_completed"},
		"verarbeitungsverzeichnis": {"governance.vvt_entry"},
		"training":            {"model_usage.training", "provider.uses_data_for_training"},
		"finetuning":          {"model_usage.training"},
		"rag":                 {"model_usage.rag"},
		"human":               {"processing.human_oversight"},
		"aufsicht":            {"processing.human_oversight"},
	}

	seen := make(map[string]bool)
	for keyword, fields := range keywordMapping {
		if strings.Contains(question, keyword) {
			for _, field := range fields {
				if !seen[field] {
					related = append(related, field)
					seen[field] = true
				}
			}
		}
	}

	return related
}

// ============================================================================
// GET /sdk/v1/ucca/wizard/schema - Get Wizard Schema
// ============================================================================

// GetWizardSchema returns the wizard schema for the frontend
func (h *UCCAHandlers) GetWizardSchema(c *gin.Context) {
	// For now, return a static schema info
	// In future, this could be loaded from the YAML file
	c.JSON(http.StatusOK, gin.H{
		"version":     "1.1",
		"total_steps": 8,
		"default_mode": "simple",
		"legal_assistant": gin.H{
			"enabled":     true,
			"endpoint":    "/sdk/v1/ucca/wizard/ask",
			"max_tokens":  1024,
			"example_questions": []string{
				"Was sind personenbezogene Daten?",
				"Was ist der Unterschied zwischen AVV und SCC?",
				"Brauche ich ein TIA?",
				"Was bedeutet Profiling?",
				"Was ist Art. 9 DSGVO?",
				"Wann brauche ich eine DSFA?",
				"Was ist das Data Privacy Framework?",
			},
		},
		"steps": []gin.H{
			{"number": 1, "title": "Grundlegende Informationen", "icon": "info"},
			{"number": 2, "title": "Welche Daten werden verarbeitet?", "icon": "database"},
			{"number": 3, "title": "Wofür wird die KI eingesetzt?", "icon": "target"},
			{"number": 4, "title": "Wo läuft die KI?", "icon": "server"},
			{"number": 5, "title": "Internationaler Datentransfer", "icon": "globe"},
			{"number": 6, "title": "KI-Modell und Training", "icon": "brain"},
			{"number": 7, "title": "Verträge & Compliance", "icon": "file-contract"},
			{"number": 8, "title": "Automatisierung & Kontrolle", "icon": "user-check"},
		},
	})
}

// ============================================================================
// Helper functions
// ============================================================================

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