package ucca

// ============================================================================
// DSGVO Module
// ============================================================================
//
// This module implements the GDPR (DSGVO - Datenschutz-Grundverordnung) obligations.
//
// Split into:
//   - dsgvo_module.go      — struct, constants, classification, derive methods, decision tree
//   - dsgvo_yaml.go        — YAML loading and conversion helpers
//   - dsgvo_obligations.go — hardcoded fallback obligations/controls/deadlines
//
// ============================================================================

// DSGVOModule implements the RegulationModule interface for DSGVO
type DSGVOModule struct {
	obligations       []Obligation
	controls          []ObligationControl
	incidentDeadlines []IncidentDeadline
	decisionTree      *DecisionTree
	loaded            bool
}

var (
	// DSGVOSpecialCategories contains Article 9 special categories of personal data
	DSGVOSpecialCategories = map[string]bool{
		"racial_ethnic_origin":   true,
		"political_opinions":     true,
		"religious_beliefs":      true,
		"trade_union_membership": true,
		"genetic_data":           true,
		"biometric_data":         true,
		"health_data":            true,
		"sexual_orientation":     true,
	}

	// DSGVOHighRiskProcessing contains high risk processing activities (Art. 35)
	DSGVOHighRiskProcessing = map[string]bool{
		"systematic_monitoring":  true,
		"automated_decisions":    true,
		"large_scale_special":    true,
		"public_area_monitoring": true,
		"profiling":              true,
		"vulnerable_persons":     true,
	}
)

// NewDSGVOModule creates a new DSGVO module, loading obligations from YAML
func NewDSGVOModule() (*DSGVOModule, error) {
	m := &DSGVOModule{
		obligations:       []Obligation{},
		controls:          []ObligationControl{},
		incidentDeadlines: []IncidentDeadline{},
	}

	if err := m.loadFromYAML(); err != nil {
		m.loadHardcodedObligations()
	}

	m.buildDecisionTree()
	m.loaded = true

	return m, nil
}

// ID returns the module identifier
func (m *DSGVOModule) ID() string { return "dsgvo" }

// Name returns the human-readable name
func (m *DSGVOModule) Name() string { return "DSGVO (Datenschutz-Grundverordnung)" }

// Description returns a brief description
func (m *DSGVOModule) Description() string {
	return "EU-Datenschutz-Grundverordnung (Verordnung (EU) 2016/679) - Schutz personenbezogener Daten"
}

// IsApplicable checks if DSGVO applies to the organization
func (m *DSGVOModule) IsApplicable(facts *UnifiedFacts) bool {
	if !facts.DataProtection.ProcessesPersonalData {
		return false
	}
	if facts.Organization.EUMember || facts.DataProtection.OffersToEU || facts.DataProtection.MonitorsEUIndividuals {
		return true
	}
	return facts.DataProtection.ProcessesPersonalData
}

// GetClassification returns the DSGVO classification as string
func (m *DSGVOModule) GetClassification(facts *UnifiedFacts) string {
	if !m.IsApplicable(facts) {
		return "nicht_anwendbar"
	}
	if m.hasHighRiskProcessing(facts) {
		if facts.DataProtection.IsController {
			return "verantwortlicher_hohes_risiko"
		}
		return "auftragsverarbeiter_hohes_risiko"
	}
	if facts.DataProtection.IsController {
		return "verantwortlicher"
	}
	return "auftragsverarbeiter"
}

func (m *DSGVOModule) hasHighRiskProcessing(facts *UnifiedFacts) bool {
	for _, cat := range facts.DataProtection.SpecialCategories {
		if DSGVOSpecialCategories[cat] {
			return true
		}
	}
	for _, activity := range facts.DataProtection.HighRiskActivities {
		if DSGVOHighRiskProcessing[activity] {
			return true
		}
	}
	if facts.DataProtection.DataSubjectCount > 10000 {
		return true
	}
	if facts.DataProtection.SystematicMonitoring {
		return true
	}
	if facts.DataProtection.AutomatedDecisions && facts.DataProtection.LegalEffects {
		return true
	}
	return false
}

func (m *DSGVOModule) requiresDPO(facts *UnifiedFacts) bool {
	if facts.Organization.IsPublicAuthority {
		return true
	}
	if facts.DataProtection.SystematicMonitoring && facts.DataProtection.DataSubjectCount > 10000 {
		return true
	}
	if len(facts.DataProtection.SpecialCategories) > 0 && facts.DataProtection.DataSubjectCount > 10000 {
		return true
	}
	if facts.Organization.Country == "DE" && facts.Organization.EmployeeCount >= 20 {
		return true
	}
	return false
}

// DeriveObligations derives all applicable DSGVO obligations
func (m *DSGVOModule) DeriveObligations(facts *UnifiedFacts) []Obligation {
	if !m.IsApplicable(facts) {
		return []Obligation{}
	}

	var result []Obligation
	isHighRisk := m.hasHighRiskProcessing(facts)
	needsDPO := m.requiresDPO(facts)
	isController := facts.DataProtection.IsController
	usesProcessors := facts.DataProtection.UsesExternalProcessor

	for _, obl := range m.obligations {
		if m.obligationApplies(obl, isController, isHighRisk, needsDPO, usesProcessors, facts) {
			customized := obl
			customized.RegulationID = m.ID()
			result = append(result, customized)
		}
	}

	return result
}

func (m *DSGVOModule) obligationApplies(obl Obligation, isController, isHighRisk, needsDPO, usesProcessors bool, facts *UnifiedFacts) bool {
	switch obl.AppliesWhen {
	case "always":
		return true
	case "controller":
		return isController
	case "processor":
		return !isController
	case "high_risk":
		return isHighRisk
	case "needs_dpo":
		return needsDPO
	case "uses_processors":
		return usesProcessors
	case "controller_or_processor":
		return true
	case "special_categories":
		return len(facts.DataProtection.SpecialCategories) > 0
	case "cross_border":
		return facts.DataProtection.CrossBorderProcessing
	case "":
		return true
	default:
		return true
	}
}

// DeriveControls derives all applicable DSGVO controls
func (m *DSGVOModule) DeriveControls(facts *UnifiedFacts) []ObligationControl {
	if !m.IsApplicable(facts) {
		return []ObligationControl{}
	}

	var result []ObligationControl
	for _, ctrl := range m.controls {
		ctrl.RegulationID = m.ID()
		result = append(result, ctrl)
	}

	return result
}

// GetDecisionTree returns the DSGVO applicability decision tree
func (m *DSGVOModule) GetDecisionTree() *DecisionTree { return m.decisionTree }

// GetIncidentDeadlines returns DSGVO breach notification deadlines
func (m *DSGVOModule) GetIncidentDeadlines(facts *UnifiedFacts) []IncidentDeadline {
	if !m.IsApplicable(facts) {
		return []IncidentDeadline{}
	}
	return m.incidentDeadlines
}

func (m *DSGVOModule) buildDecisionTree() {
	m.decisionTree = &DecisionTree{
		ID:   "dsgvo_applicability",
		Name: "DSGVO Anwendbarkeits-Entscheidungsbaum",
		RootNode: &DecisionNode{
			ID:       "root",
			Question: "Verarbeitet Ihre Organisation personenbezogene Daten?",
			YesNode: &DecisionNode{
				ID:       "eu_check",
				Question: "Ist Ihre Organisation in der EU/EWR ansässig?",
				YesNode: &DecisionNode{
					ID:          "eu_established",
					Result:      "DSGVO anwendbar",
					Explanation: "Die DSGVO gilt für alle in der EU ansässigen Organisationen, die personenbezogene Daten verarbeiten.",
				},
				NoNode: &DecisionNode{
					ID:       "offering_check",
					Question: "Bieten Sie Waren oder Dienstleistungen an Personen in der EU an?",
					YesNode: &DecisionNode{
						ID:          "offering_to_eu",
						Result:      "DSGVO anwendbar",
						Explanation: "Die DSGVO gilt für Organisationen außerhalb der EU, die Waren/Dienstleistungen an EU-Bürger anbieten.",
					},
					NoNode: &DecisionNode{
						ID:       "monitoring_check",
						Question: "Beobachten Sie das Verhalten von Personen in der EU?",
						YesNode: &DecisionNode{
							ID:          "monitoring_eu",
							Result:      "DSGVO anwendbar",
							Explanation: "Die DSGVO gilt für Organisationen, die das Verhalten von Personen in der EU beobachten (z.B. Tracking, Profiling).",
						},
						NoNode: &DecisionNode{
							ID:          "not_applicable",
							Result:      "DSGVO nicht anwendbar",
							Explanation: "Die DSGVO ist nicht anwendbar, da keine der Anknüpfungskriterien erfüllt ist.",
						},
					},
				},
			},
			NoNode: &DecisionNode{
				ID:          "no_personal_data",
				Result:      "DSGVO nicht anwendbar",
				Explanation: "Die DSGVO gilt nur für die Verarbeitung personenbezogener Daten.",
			},
		},
	}
}
