package ucca

import (
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"gopkg.in/yaml.v3"
)

// ============================================================================
// YAML-based Policy Engine
// ============================================================================
//
// This engine evaluates use-case intakes against YAML-defined rules.
// Key design principles:
//   - Deterministic: No LLM involvement in rule evaluation
//   - Transparent: Rules are auditable YAML
//   - Composable: Each field carries its own legal metadata
//   - Solution-oriented: Problems include suggested solutions
//
// ============================================================================

// DefaultPolicyPath is the default location for the policy file
var DefaultPolicyPath = "policies/ucca_policy_v1.yaml"

// PolicyConfig represents the full YAML policy structure
type PolicyConfig struct {
	Policy           PolicyMetadata            `yaml:"policy"`
	Thresholds       Thresholds                `yaml:"thresholds"`
	Patterns         map[string]PatternDef     `yaml:"patterns"`
	Controls         map[string]ControlDef     `yaml:"controls"`
	Rules            []RuleDef                 `yaml:"rules"`
	ProblemSolutions []ProblemSolutionDef      `yaml:"problem_solutions"`
	EscalationTriggers []EscalationTriggerDef  `yaml:"escalation_triggers"`
}

// PolicyMetadata contains policy header info
type PolicyMetadata struct {
	Name               string   `yaml:"name"`
	Version            string   `yaml:"version"`
	Jurisdiction       string   `yaml:"jurisdiction"`
	Basis              []string `yaml:"basis"`
	DefaultFeasibility string   `yaml:"default_feasibility"`
	DefaultRiskScore   int      `yaml:"default_risk_score"`
}

// Thresholds for risk scoring and escalation
type Thresholds struct {
	Risk       RiskThresholds `yaml:"risk"`
	Escalation []string       `yaml:"escalation"`
}

// RiskThresholds defines risk level boundaries
type RiskThresholds struct {
	Minimal      int `yaml:"minimal"`
	Low          int `yaml:"low"`
	Medium       int `yaml:"medium"`
	High         int `yaml:"high"`
	Unacceptable int `yaml:"unacceptable"`
}

// PatternDef represents an architecture pattern from YAML
type PatternDef struct {
	ID            string `yaml:"id"`
	Title         string `yaml:"title"`
	Description   string `yaml:"description"`
	Benefit       string `yaml:"benefit"`
	Effort        string `yaml:"effort"`
	RiskReduction int    `yaml:"risk_reduction"`
}

// ControlDef represents a required control from YAML
type ControlDef struct {
	ID          string `yaml:"id"`
	Title       string `yaml:"title"`
	Description string `yaml:"description"`
	GDPRRef     string `yaml:"gdpr_ref"`
	Effort      string `yaml:"effort"`
}

// RuleDef represents a single rule from YAML
type RuleDef struct {
	ID          string       `yaml:"id"`
	Category    string       `yaml:"category"`
	Title       string       `yaml:"title"`
	Description string       `yaml:"description"`
	Condition   ConditionDef `yaml:"condition"`
	Effect      EffectDef    `yaml:"effect"`
	Severity    string       `yaml:"severity"`
	GDPRRef     string       `yaml:"gdpr_ref"`
	Rationale   string       `yaml:"rationale"`
}

// ConditionDef represents a rule condition (supports field checks and compositions)
type ConditionDef struct {
	// Simple field check
	Field    string      `yaml:"field,omitempty"`
	Operator string      `yaml:"operator,omitempty"`
	Value    interface{} `yaml:"value,omitempty"`

	// Composite conditions
	AllOf []ConditionDef `yaml:"all_of,omitempty"`
	AnyOf []ConditionDef `yaml:"any_of,omitempty"`

	// Aggregate conditions (evaluated after all rules)
	Aggregate string `yaml:"aggregate,omitempty"`
}

// EffectDef represents the effect when a rule triggers
type EffectDef struct {
	RiskAdd           int      `yaml:"risk_add,omitempty"`
	Feasibility       string   `yaml:"feasibility,omitempty"`
	ControlsAdd       []string `yaml:"controls_add,omitempty"`
	SuggestedPatterns []string `yaml:"suggested_patterns,omitempty"`
	Escalation        bool     `yaml:"escalation,omitempty"`
	Art22Risk         bool     `yaml:"art22_risk,omitempty"`
	TrainingAllowed   bool     `yaml:"training_allowed,omitempty"`
	LegalBasis        string   `yaml:"legal_basis,omitempty"`
}

// ProblemSolutionDef maps problems to solutions
type ProblemSolutionDef struct {
	ProblemID string              `yaml:"problem_id"`
	Title     string              `yaml:"title"`
	Triggers  []ProblemTriggerDef `yaml:"triggers"`
	Solutions []SolutionDef       `yaml:"solutions"`
}

// ProblemTriggerDef defines when a problem is triggered
type ProblemTriggerDef struct {
	Rule           string `yaml:"rule"`
	WithoutControl string `yaml:"without_control,omitempty"`
}

// SolutionDef represents a potential solution
type SolutionDef struct {
	ID             string `yaml:"id"`
	Title          string `yaml:"title"`
	Pattern        string `yaml:"pattern,omitempty"`
	Control        string `yaml:"control,omitempty"`
	RemovesProblem bool   `yaml:"removes_problem"`
	TeamQuestion   string `yaml:"team_question"`
}

// EscalationTriggerDef defines when to escalate to DSB
type EscalationTriggerDef struct {
	Condition string `yaml:"condition"`
	Reason    string `yaml:"reason"`
}

// ============================================================================
// Policy Engine Implementation
// ============================================================================

// PolicyEngine evaluates intakes against YAML-defined rules
type PolicyEngine struct {
	config *PolicyConfig
}

// NewPolicyEngine creates a new policy engine, loading from the default path
// It searches for the policy file in common locations
func NewPolicyEngine() (*PolicyEngine, error) {
	// Try multiple locations to find the policy file
	searchPaths := []string{
		DefaultPolicyPath,
		filepath.Join(".", "policies", "ucca_policy_v1.yaml"),
		filepath.Join("..", "policies", "ucca_policy_v1.yaml"),
		filepath.Join("..", "..", "policies", "ucca_policy_v1.yaml"),
		"/app/policies/ucca_policy_v1.yaml", // Docker container path
	}

	var data []byte
	var err error
	for _, path := range searchPaths {
		data, err = os.ReadFile(path)
		if err == nil {
			break
		}
	}

	if err != nil {
		return nil, fmt.Errorf("failed to load policy from any known location: %w", err)
	}

	var config PolicyConfig
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse policy YAML: %w", err)
	}

	return &PolicyEngine{config: &config}, nil
}

// NewPolicyEngineFromPath loads policy from a specific file path
func NewPolicyEngineFromPath(path string) (*PolicyEngine, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read policy file: %w", err)
	}

	var config PolicyConfig
	if err := yaml.Unmarshal(data, &config); err != nil {
		return nil, fmt.Errorf("failed to parse policy YAML: %w", err)
	}

	return &PolicyEngine{config: &config}, nil
}

// GetPolicyVersion returns the policy version
func (e *PolicyEngine) GetPolicyVersion() string {
	return e.config.Policy.Version
}

// Evaluate runs all YAML rules against the intake
func (e *PolicyEngine) Evaluate(intake *UseCaseIntake) *AssessmentResult {
	result := &AssessmentResult{
		Feasibility:             FeasibilityYES,
		RiskLevel:               RiskLevelMINIMAL,
		Complexity:              ComplexityLOW,
		RiskScore:               0,
		TriggeredRules:          []TriggeredRule{},
		RequiredControls:        []RequiredControl{},
		RecommendedArchitecture: []PatternRecommendation{},
		ForbiddenPatterns:       []ForbiddenPattern{},
		ExampleMatches:          []ExampleMatch{},
		DSFARecommended:         false,
		Art22Risk:               false,
		TrainingAllowed:         TrainingYES,
	}

	// Track state for aggregation
	hasBlock := false
	hasWarn := false
	controlSet := make(map[string]bool)
	patternPriority := make(map[string]int)
	triggeredRuleIDs := make(map[string]bool)
	needsEscalation := false

	// Evaluate each non-aggregate rule
	priority := 1
	for _, rule := range e.config.Rules {
		// Skip aggregate rules (evaluated later)
		if rule.Condition.Aggregate != "" {
			continue
		}

		if e.evaluateCondition(&rule.Condition, intake) {
			triggeredRuleIDs[rule.ID] = true

			// Create triggered rule record
			triggered := TriggeredRule{
				Code:        rule.ID,
				Category:    rule.Category,
				Title:       rule.Title,
				Description: rule.Description,
				Severity:    parseSeverity(rule.Severity),
				ScoreDelta:  rule.Effect.RiskAdd,
				GDPRRef:     rule.GDPRRef,
				Rationale:   rule.Rationale,
			}
			result.TriggeredRules = append(result.TriggeredRules, triggered)

			// Apply effects
			result.RiskScore += rule.Effect.RiskAdd

			// Track severity
			switch parseSeverity(rule.Severity) {
			case SeverityBLOCK:
				hasBlock = true
			case SeverityWARN:
				hasWarn = true
			}

			// Override feasibility if specified
			if rule.Effect.Feasibility != "" {
				switch rule.Effect.Feasibility {
				case "NO":
					result.Feasibility = FeasibilityNO
				case "CONDITIONAL":
					if result.Feasibility != FeasibilityNO {
						result.Feasibility = FeasibilityCONDITIONAL
					}
				case "YES":
					// Only set YES if not already NO or CONDITIONAL
					if result.Feasibility != FeasibilityNO && result.Feasibility != FeasibilityCONDITIONAL {
						result.Feasibility = FeasibilityYES
					}
				}
			}

			// Collect controls
			for _, ctrlID := range rule.Effect.ControlsAdd {
				if !controlSet[ctrlID] {
					controlSet[ctrlID] = true
					if ctrl, ok := e.config.Controls[ctrlID]; ok {
						result.RequiredControls = append(result.RequiredControls, RequiredControl{
							ID:          ctrl.ID,
							Title:       ctrl.Title,
							Description: ctrl.Description,
							Severity:    parseSeverity(rule.Severity),
							Category:    categorizeControl(ctrl.ID),
							GDPRRef:     ctrl.GDPRRef,
						})
					}
				}
			}

			// Collect patterns
			for _, patternID := range rule.Effect.SuggestedPatterns {
				if _, exists := patternPriority[patternID]; !exists {
					patternPriority[patternID] = priority
					priority++
				}
			}

			// Track special flags
			if rule.Effect.Escalation {
				needsEscalation = true
			}
			if rule.Effect.Art22Risk {
				result.Art22Risk = true
			}
		}
	}

	// Apply aggregation rules
	if hasBlock {
		result.Feasibility = FeasibilityNO
	} else if hasWarn && result.Feasibility != FeasibilityNO {
		result.Feasibility = FeasibilityCONDITIONAL
	}

	// Determine risk level from thresholds
	result.RiskLevel = e.calculateRiskLevel(result.RiskScore)

	// Determine complexity
	result.Complexity = e.calculateComplexity(result)

	// Check if DSFA is recommended
	result.DSFARecommended = e.shouldRecommendDSFA(intake, result)

	// Determine training allowed status
	result.TrainingAllowed = e.determineTrainingAllowed(intake)

	// Add recommended patterns (sorted by priority)
	result.RecommendedArchitecture = e.buildPatternRecommendations(patternPriority)

	// Match didactic examples
	result.ExampleMatches = MatchExamples(intake)

	// Generate summaries
	result.Summary = e.generateSummary(result, intake)
	result.Recommendation = e.generateRecommendation(result, intake)
	if result.Feasibility == FeasibilityNO {
		result.AlternativeApproach = e.generateAlternative(result, intake, triggeredRuleIDs)
	}

	// Note: needsEscalation could be used to flag the assessment for DSB review
	_ = needsEscalation

	return result
}

// evaluateCondition recursively evaluates a condition against the intake
func (e *PolicyEngine) evaluateCondition(cond *ConditionDef, intake *UseCaseIntake) bool {
	// Handle composite all_of
	if len(cond.AllOf) > 0 {
		for _, subCond := range cond.AllOf {
			if !e.evaluateCondition(&subCond, intake) {
				return false
			}
		}
		return true
	}

	// Handle composite any_of
	if len(cond.AnyOf) > 0 {
		for _, subCond := range cond.AnyOf {
			if e.evaluateCondition(&subCond, intake) {
				return true
			}
		}
		return false
	}

	// Handle simple field condition
	if cond.Field != "" {
		return e.evaluateFieldCondition(cond.Field, cond.Operator, cond.Value, intake)
	}

	return false
}

// evaluateFieldCondition evaluates a single field comparison
func (e *PolicyEngine) evaluateFieldCondition(field, operator string, value interface{}, intake *UseCaseIntake) bool {
	// Get the field value from intake
	fieldValue := e.getFieldValue(field, intake)
	if fieldValue == nil {
		return false
	}

	switch operator {
	case "equals":
		return e.compareEquals(fieldValue, value)
	case "not_equals":
		return !e.compareEquals(fieldValue, value)
	case "in":
		return e.compareIn(fieldValue, value)
	case "contains":
		return e.compareContains(fieldValue, value)
	default:
		return false
	}
}

// getFieldValue extracts a field value from the intake using dot notation
func (e *PolicyEngine) getFieldValue(field string, intake *UseCaseIntake) interface{} {
	parts := strings.Split(field, ".")
	if len(parts) == 0 {
		return nil
	}

	switch parts[0] {
	case "data_types":
		if len(parts) < 2 {
			return nil
		}
		return e.getDataTypeValue(parts[1], intake)
	case "purpose":
		if len(parts) < 2 {
			return nil
		}
		return e.getPurposeValue(parts[1], intake)
	case "automation":
		return string(intake.Automation)
	case "outputs":
		if len(parts) < 2 {
			return nil
		}
		return e.getOutputsValue(parts[1], intake)
	case "hosting":
		if len(parts) < 2 {
			return nil
		}
		return e.getHostingValue(parts[1], intake)
	case "model_usage":
		if len(parts) < 2 {
			return nil
		}
		return e.getModelUsageValue(parts[1], intake)
	case "domain":
		return string(intake.Domain)
	case "retention":
		if len(parts) < 2 {
			return nil
		}
		return e.getRetentionValue(parts[1], intake)
	}

	return nil
}

func (e *PolicyEngine) getDataTypeValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "personal_data":
		return intake.DataTypes.PersonalData
	case "article_9_data":
		return intake.DataTypes.Article9Data
	case "minor_data":
		return intake.DataTypes.MinorData
	case "license_plates":
		return intake.DataTypes.LicensePlates
	case "images":
		return intake.DataTypes.Images
	case "audio":
		return intake.DataTypes.Audio
	case "location_data":
		return intake.DataTypes.LocationData
	case "biometric_data":
		return intake.DataTypes.BiometricData
	case "financial_data":
		return intake.DataTypes.FinancialData
	case "employee_data":
		return intake.DataTypes.EmployeeData
	case "customer_data":
		return intake.DataTypes.CustomerData
	case "public_data":
		return intake.DataTypes.PublicData
	}
	return nil
}

func (e *PolicyEngine) getPurposeValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "customer_support":
		return intake.Purpose.CustomerSupport
	case "marketing":
		return intake.Purpose.Marketing
	case "analytics":
		return intake.Purpose.Analytics
	case "automation":
		return intake.Purpose.Automation
	case "evaluation_scoring":
		return intake.Purpose.EvaluationScoring
	case "decision_making":
		return intake.Purpose.DecisionMaking
	case "profiling":
		return intake.Purpose.Profiling
	case "research":
		return intake.Purpose.Research
	case "internal_tools":
		return intake.Purpose.InternalTools
	case "public_service":
		return intake.Purpose.PublicService
	}
	return nil
}

func (e *PolicyEngine) getOutputsValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "recommendations_to_users":
		return intake.Outputs.RecommendationsToUsers
	case "rankings_or_scores":
		return intake.Outputs.RankingsOrScores
	case "legal_effects":
		return intake.Outputs.LegalEffects
	case "access_decisions":
		return intake.Outputs.AccessDecisions
	case "content_generation":
		return intake.Outputs.ContentGeneration
	case "data_export":
		return intake.Outputs.DataExport
	}
	return nil
}

func (e *PolicyEngine) getHostingValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "provider":
		return intake.Hosting.Provider
	case "region":
		return intake.Hosting.Region
	case "data_residency":
		return intake.Hosting.DataResidency
	}
	return nil
}

func (e *PolicyEngine) getModelUsageValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "rag":
		return intake.ModelUsage.RAG
	case "finetune":
		return intake.ModelUsage.Finetune
	case "training":
		return intake.ModelUsage.Training
	case "inference":
		return intake.ModelUsage.Inference
	}
	return nil
}

func (e *PolicyEngine) getRetentionValue(field string, intake *UseCaseIntake) interface{} {
	switch field {
	case "store_prompts":
		return intake.Retention.StorePrompts
	case "store_responses":
		return intake.Retention.StoreResponses
	case "retention_days":
		return intake.Retention.RetentionDays
	case "anonymize_after_use":
		return intake.Retention.AnonymizeAfterUse
	}
	return nil
}

// compareEquals compares two values for equality
func (e *PolicyEngine) compareEquals(fieldValue, expected interface{}) bool {
	// Handle bool comparison
	if bv, ok := fieldValue.(bool); ok {
		if eb, ok := expected.(bool); ok {
			return bv == eb
		}
	}

	// Handle string comparison
	if sv, ok := fieldValue.(string); ok {
		if es, ok := expected.(string); ok {
			return sv == es
		}
	}

	// Handle int comparison
	if iv, ok := fieldValue.(int); ok {
		switch ev := expected.(type) {
		case int:
			return iv == ev
		case float64:
			return iv == int(ev)
		}
	}

	return false
}

// compareIn checks if fieldValue is in a list of expected values
func (e *PolicyEngine) compareIn(fieldValue, expected interface{}) bool {
	list, ok := expected.([]interface{})
	if !ok {
		return false
	}

	sv, ok := fieldValue.(string)
	if !ok {
		return false
	}

	for _, item := range list {
		if is, ok := item.(string); ok && is == sv {
			return true
		}
	}
	return false
}

// compareContains checks if a string contains a substring
func (e *PolicyEngine) compareContains(fieldValue, expected interface{}) bool {
	sv, ok := fieldValue.(string)
	if !ok {
		return false
	}
	es, ok := expected.(string)
	if !ok {
		return false
	}
	return strings.Contains(strings.ToLower(sv), strings.ToLower(es))
}

// calculateRiskLevel determines risk level from score
func (e *PolicyEngine) calculateRiskLevel(score int) RiskLevel {
	t := e.config.Thresholds.Risk
	if score >= t.Unacceptable {
		return RiskLevelUNACCEPTABLE
	}
	if score >= t.High {
		return RiskLevelHIGH
	}
	if score >= t.Medium {
		return RiskLevelMEDIUM
	}
	if score >= t.Low {
		return RiskLevelLOW
	}
	return RiskLevelMINIMAL
}

// calculateComplexity determines implementation complexity
func (e *PolicyEngine) calculateComplexity(result *AssessmentResult) Complexity {
	controlCount := len(result.RequiredControls)
	if controlCount >= 5 || result.RiskScore >= 50 {
		return ComplexityHIGH
	}
	if controlCount >= 3 || result.RiskScore >= 25 {
		return ComplexityMEDIUM
	}
	return ComplexityLOW
}

// shouldRecommendDSFA checks if a DSFA is recommended
func (e *PolicyEngine) shouldRecommendDSFA(intake *UseCaseIntake, result *AssessmentResult) bool {
	if result.RiskLevel == RiskLevelHIGH || result.RiskLevel == RiskLevelUNACCEPTABLE {
		return true
	}
	if intake.DataTypes.Article9Data || intake.DataTypes.BiometricData {
		return true
	}
	if intake.Purpose.Profiling && intake.DataTypes.PersonalData {
		return true
	}
	// Check if C_DSFA control is required
	for _, ctrl := range result.RequiredControls {
		if ctrl.ID == "C_DSFA" {
			return true
		}
	}
	return false
}

// determineTrainingAllowed checks training permission
func (e *PolicyEngine) determineTrainingAllowed(intake *UseCaseIntake) TrainingAllowed {
	if intake.ModelUsage.Training && intake.DataTypes.PersonalData {
		return TrainingNO
	}
	if intake.ModelUsage.Finetune && intake.DataTypes.PersonalData {
		return TrainingCONDITIONAL
	}
	if intake.DataTypes.MinorData && (intake.ModelUsage.Training || intake.ModelUsage.Finetune) {
		return TrainingNO
	}
	return TrainingYES
}

// buildPatternRecommendations creates sorted pattern recommendations
func (e *PolicyEngine) buildPatternRecommendations(patternPriority map[string]int) []PatternRecommendation {
	type priorityPair struct {
		id       string
		priority int
	}

	pairs := make([]priorityPair, 0, len(patternPriority))
	for id, p := range patternPriority {
		pairs = append(pairs, priorityPair{id, p})
	}
	sort.Slice(pairs, func(i, j int) bool {
		return pairs[i].priority < pairs[j].priority
	})

	recommendations := make([]PatternRecommendation, 0, len(pairs))
	for _, p := range pairs {
		if pattern, ok := e.config.Patterns[p.id]; ok {
			recommendations = append(recommendations, PatternRecommendation{
				PatternID:   pattern.ID,
				Title:       pattern.Title,
				Description: pattern.Description,
				Rationale:   pattern.Benefit,
				Priority:    p.priority,
			})
		}
	}
	return recommendations
}

// generateSummary creates a human-readable summary
func (e *PolicyEngine) generateSummary(result *AssessmentResult, intake *UseCaseIntake) string {
	var parts []string

	switch result.Feasibility {
	case FeasibilityYES:
		parts = append(parts, "Der Use Case ist aus DSGVO-Sicht grundsätzlich umsetzbar.")
	case FeasibilityCONDITIONAL:
		parts = append(parts, "Der Use Case ist unter Auflagen umsetzbar.")
	case FeasibilityNO:
		parts = append(parts, "Der Use Case ist in der aktuellen Form nicht DSGVO-konform umsetzbar.")
	}

	blockCount := 0
	warnCount := 0
	for _, r := range result.TriggeredRules {
		if r.Severity == SeverityBLOCK {
			blockCount++
		} else if r.Severity == SeverityWARN {
			warnCount++
		}
	}

	if blockCount > 0 {
		parts = append(parts, fmt.Sprintf("%d kritische Regelverletzung(en) identifiziert.", blockCount))
	}
	if warnCount > 0 {
		parts = append(parts, fmt.Sprintf("%d Warnungen erfordern Aufmerksamkeit.", warnCount))
	}

	if result.DSFARecommended {
		parts = append(parts, "Eine Datenschutz-Folgenabschätzung (DSFA) wird empfohlen.")
	}

	return strings.Join(parts, " ")
}

// generateRecommendation creates actionable recommendations
func (e *PolicyEngine) generateRecommendation(result *AssessmentResult, intake *UseCaseIntake) string {
	if result.Feasibility == FeasibilityYES {
		return "Fahren Sie mit der Implementierung fort. Beachten Sie die empfohlenen Architektur-Patterns für optimale DSGVO-Konformität."
	}

	if result.Feasibility == FeasibilityCONDITIONAL {
		if len(result.RequiredControls) > 0 {
			return fmt.Sprintf("Implementieren Sie die %d erforderlichen Kontrollen vor dem Go-Live. Dokumentieren Sie alle Maßnahmen für den Nachweis der Rechenschaftspflicht (Art. 5 DSGVO).", len(result.RequiredControls))
		}
		return "Prüfen Sie die ausgelösten Warnungen und implementieren Sie entsprechende Schutzmaßnahmen."
	}

	return "Der Use Case erfordert grundlegende Änderungen. Prüfen Sie die Lösungsvorschläge."
}

// generateAlternative creates alternative approach suggestions
func (e *PolicyEngine) generateAlternative(result *AssessmentResult, intake *UseCaseIntake, triggeredRules map[string]bool) string {
	var suggestions []string

	// Find applicable problem-solutions
	for _, ps := range e.config.ProblemSolutions {
		for _, trigger := range ps.Triggers {
			if triggeredRules[trigger.Rule] {
				// Check if control is missing (if specified)
				if trigger.WithoutControl != "" {
					hasControl := false
					for _, ctrl := range result.RequiredControls {
						if ctrl.ID == trigger.WithoutControl {
							hasControl = true
							break
						}
					}
					if hasControl {
						continue
					}
				}
				// Add first solution as suggestion
				if len(ps.Solutions) > 0 {
					sol := ps.Solutions[0]
					suggestions = append(suggestions, fmt.Sprintf("%s: %s", sol.Title, sol.TeamQuestion))
				}
			}
		}
	}

	// Fallback suggestions based on intake
	if len(suggestions) == 0 {
		if intake.ModelUsage.Training && intake.DataTypes.PersonalData {
			suggestions = append(suggestions, "Nutzen Sie nur RAG statt Training mit personenbezogenen Daten")
		}
		if intake.Automation == AutomationFullyAutomated && intake.Outputs.LegalEffects {
			suggestions = append(suggestions, "Implementieren Sie Human-in-the-Loop für Entscheidungen mit rechtlichen Auswirkungen")
		}
		if intake.DataTypes.MinorData && intake.Purpose.EvaluationScoring {
			suggestions = append(suggestions, "Verzichten Sie auf automatisches Scoring von Minderjährigen")
		}
	}

	if len(suggestions) == 0 {
		return "Überarbeiten Sie den Use Case unter Berücksichtigung der ausgelösten Regeln."
	}

	return strings.Join(suggestions, " | ")
}

// GetAllRules returns all rules in the policy
func (e *PolicyEngine) GetAllRules() []RuleDef {
	return e.config.Rules
}

// GetAllPatterns returns all patterns in the policy
func (e *PolicyEngine) GetAllPatterns() map[string]PatternDef {
	return e.config.Patterns
}

// GetAllControls returns all controls in the policy
func (e *PolicyEngine) GetAllControls() map[string]ControlDef {
	return e.config.Controls
}

// GetProblemSolutions returns problem-solution mappings
func (e *PolicyEngine) GetProblemSolutions() []ProblemSolutionDef {
	return e.config.ProblemSolutions
}

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

func parseSeverity(s string) Severity {
	switch strings.ToUpper(s) {
	case "BLOCK":
		return SeverityBLOCK
	case "WARN":
		return SeverityWARN
	default:
		return SeverityINFO
	}
}

func categorizeControl(id string) string {
	// Map control IDs to categories
	technical := map[string]bool{
		"C_ENCRYPTION": true, "C_ACCESS_LOGGING": true,
	}
	if technical[id] {
		return "technical"
	}
	return "organizational"
}
