"""
Source-Type-Klassifikation fuer Regulierungen und Frameworks.

Dreistufiges Modell der normativen Verbindlichkeit:

  Stufe 1 — GESETZ (law):
    Rechtlich bindend. Bussgeld bei Verstoss.
    Beispiele: DSGVO, NIS2, AI Act, CRA

  Stufe 2 — LEITLINIE (guideline):
    Offizielle Auslegungshilfe von Aufsichtsbehoerden.
    Beweislastumkehr: Wer abweicht, muss begruenden warum.
    Beispiele: EDPB-Leitlinien, BSI-Standards, WP29-Dokumente

  Stufe 3 — FRAMEWORK (framework):
    Freiwillige Best Practices, nicht rechtsverbindlich.
    Aber: Koennen als "Stand der Technik" herangezogen werden.
    Beispiele: ENISA, NIST, OWASP, OECD, CISA

Mapping: source_regulation (aus control_parent_links) -> source_type
"""

# --- Typ-Definitionen ---
SOURCE_TYPE_LAW = "law"           # Gesetz/Verordnung/Richtlinie — normative_strength bleibt
SOURCE_TYPE_GUIDELINE = "guideline"  # Leitlinie/Standard — max "should"
SOURCE_TYPE_FRAMEWORK = "framework"  # Framework/Best Practice — max "may"

# Max erlaubte normative_strength pro source_type
# DB-Constraint erlaubt: must, should, may (NICHT "can")
NORMATIVE_STRENGTH_CAP: dict[str, str] = {
    SOURCE_TYPE_LAW: "must",       # keine Begrenzung
    SOURCE_TYPE_GUIDELINE: "should",  # max "should"
    SOURCE_TYPE_FRAMEWORK: "may",     # max "may" (= "kann")
}

# Reihenfolge fuer Vergleiche (hoeher = staerker)
STRENGTH_ORDER: dict[str, int] = {
    "may": 1,        # KANN (DB-Wert)
    "can": 1,        # Alias — wird in cap_normative_strength zu "may" normalisiert
    "should": 2,
    "must": 3,
}


def cap_normative_strength(original: str, source_type: str) -> str:
    """
    Begrenzt die normative_strength basierend auf dem source_type.

    Beispiel:
        cap_normative_strength("must", "framework") -> "may"
        cap_normative_strength("should", "law") -> "should"
        cap_normative_strength("must", "guideline") -> "should"
    """
    cap = NORMATIVE_STRENGTH_CAP.get(source_type, "must")
    cap_level = STRENGTH_ORDER.get(cap, 3)
    original_level = STRENGTH_ORDER.get(original, 3)
    if original_level > cap_level:
        return cap
    return original


def get_highest_source_type(source_types: list[str]) -> str:
    """
    Bestimmt den hoechsten source_type aus einer Liste.
    Ein Gesetz uebertrumpft alles.

    Beispiel:
        get_highest_source_type(["framework", "law"]) -> "law"
        get_highest_source_type(["framework", "guideline"]) -> "guideline"
    """
    type_order = {SOURCE_TYPE_FRAMEWORK: 1, SOURCE_TYPE_GUIDELINE: 2, SOURCE_TYPE_LAW: 3}
    if not source_types:
        return SOURCE_TYPE_FRAMEWORK
    return max(source_types, key=lambda t: type_order.get(t, 0))


# ============================================================================
# Klassifikation: source_regulation -> source_type
#
# Diese Map wird fuer den Backfill und zukuenftige Pipeline-Runs verwendet.
# Neue Regulierungen hier eintragen!
# ============================================================================

SOURCE_REGULATION_CLASSIFICATION: dict[str, str] = {
    # --- EU-Verordnungen (unmittelbar bindend) ---
    "DSGVO (EU) 2016/679": SOURCE_TYPE_LAW,
    "KI-Verordnung (EU) 2024/1689": SOURCE_TYPE_LAW,
    "Cyber Resilience Act (CRA)": SOURCE_TYPE_LAW,
    "NIS2-Richtlinie (EU) 2022/2555": SOURCE_TYPE_LAW,
    "Data Act": SOURCE_TYPE_LAW,
    "Data Governance Act (DGA)": SOURCE_TYPE_LAW,
    "Markets in Crypto-Assets (MiCA)": SOURCE_TYPE_LAW,
    "Maschinenverordnung (EU) 2023/1230": SOURCE_TYPE_LAW,
    "Batterieverordnung (EU) 2023/1542": SOURCE_TYPE_LAW,
    "AML-Verordnung": SOURCE_TYPE_LAW,

    # --- EU-Richtlinien (nach nationaler Umsetzung bindend) ---
    # Fuer Compliance-Zwecke wie Gesetze behandeln

    # --- Nationale Gesetze ---
    "Bundesdatenschutzgesetz (BDSG)": SOURCE_TYPE_LAW,
    "Telekommunikationsgesetz": SOURCE_TYPE_LAW,
    "Telekommunikationsgesetz Oesterreich": SOURCE_TYPE_LAW,
    "Gewerbeordnung (GewO)": SOURCE_TYPE_LAW,
    "Handelsgesetzbuch (HGB)": SOURCE_TYPE_LAW,
    "Abgabenordnung (AO)": SOURCE_TYPE_LAW,
    "IFRS-Übernahmeverordnung": SOURCE_TYPE_LAW,
    "Österreichisches Datenschutzgesetz (DSG)": SOURCE_TYPE_LAW,
    "LOPDGDD - Ley Orgánica de Protección de Datos (Spanien)": SOURCE_TYPE_LAW,
    "Loi Informatique et Libertés (Frankreich)": SOURCE_TYPE_LAW,
    "Információs önrendelkezési jog törvény (Ungarn)": SOURCE_TYPE_LAW,
    "EU Blue Guide 2022": SOURCE_TYPE_LAW,

    # --- EDPB/WP29 Leitlinien (offizielle Auslegungshilfe) ---
    "EDPB Leitlinien 01/2019 (Zertifizierung)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 01/2020 (Datentransfers)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 01/2020 (Vernetzte Fahrzeuge)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 01/2022 (BCR)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 01/2024 (Berechtigtes Interesse)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 04/2019 (Data Protection by Design)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 05/2020 - Einwilligung": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 07/2020 (Datentransfers)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 08/2020 (Social Media)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 09/2022 (Data Breach)": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien 09/2022 - Meldung von Datenschutzverletzungen": SOURCE_TYPE_GUIDELINE,
    "EDPB Empfehlungen 01/2020 - Ergaenzende Massnahmen fuer Datentransfers": SOURCE_TYPE_GUIDELINE,
    "EDPB Leitlinien - Berechtigtes Interesse (Art. 6(1)(f))": SOURCE_TYPE_GUIDELINE,
    "WP244 Leitlinien (Profiling)": SOURCE_TYPE_GUIDELINE,
    "WP251 Leitlinien (Profiling)": SOURCE_TYPE_GUIDELINE,
    "WP260 Leitlinien (Transparenz)": SOURCE_TYPE_GUIDELINE,

    # --- BSI Standards (behoerdliche technische Richtlinien) ---
    "BSI-TR-03161-1": SOURCE_TYPE_GUIDELINE,
    "BSI-TR-03161-2": SOURCE_TYPE_GUIDELINE,
    "BSI-TR-03161-3": SOURCE_TYPE_GUIDELINE,

    # --- ENISA (EU-Agentur, aber Empfehlungen nicht rechtsverbindlich) ---
    "ENISA Cybersecurity State 2024": SOURCE_TYPE_FRAMEWORK,
    "ENISA ICS/SCADA Dependencies": SOURCE_TYPE_FRAMEWORK,
    "ENISA Supply Chain Good Practices": SOURCE_TYPE_FRAMEWORK,
    "ENISA Threat Landscape Supply Chain": SOURCE_TYPE_FRAMEWORK,

    # --- NIST (US-Standards, international als Best Practice) ---
    "NIST AI Risk Management Framework": SOURCE_TYPE_FRAMEWORK,
    "NIST Cybersecurity Framework 2.0": SOURCE_TYPE_FRAMEWORK,
    "NIST SP 800-207 (Zero Trust)": SOURCE_TYPE_FRAMEWORK,
    "NIST SP 800-218 (SSDF)": SOURCE_TYPE_FRAMEWORK,
    "NIST SP 800-53 Rev. 5": SOURCE_TYPE_FRAMEWORK,
    "NIST SP 800-63-3": SOURCE_TYPE_FRAMEWORK,

    # --- OWASP (Community-Standards) ---
    "OWASP API Security Top 10 (2023)": SOURCE_TYPE_FRAMEWORK,
    "OWASP ASVS 4.0": SOURCE_TYPE_FRAMEWORK,
    "OWASP MASVS 2.0": SOURCE_TYPE_FRAMEWORK,
    "OWASP SAMM 2.0": SOURCE_TYPE_FRAMEWORK,
    "OWASP Top 10 (2021)": SOURCE_TYPE_FRAMEWORK,

    # --- Sonstige Frameworks ---
    "OECD KI-Empfehlung": SOURCE_TYPE_FRAMEWORK,
    "CISA Secure by Design": SOURCE_TYPE_FRAMEWORK,
}


def classify_source_regulation(source_regulation: str) -> str:
    """
    Klassifiziert eine source_regulation als law, guideline oder framework.

    Delegates to DB-backed RegulationRegistry (with 5min cache).
    Falls back to SOURCE_REGULATION_CLASSIFICATION dict + heuristic
    if DB is unavailable.
    """
    if not source_regulation:
        return SOURCE_TYPE_FRAMEWORK

    # Try DB-backed registry first
    try:
        from services.regulation_registry import classify_source_regulation as _db_classify
        result = _db_classify(source_regulation)
        if result:
            return result
    except Exception:
        pass

    # Fallback: local dict
    if source_regulation in SOURCE_REGULATION_CLASSIFICATION:
        return SOURCE_REGULATION_CLASSIFICATION[source_regulation]

    # Heuristik fuer unbekannte Quellen
    lower = source_regulation.lower()

    law_indicators = [
        "verordnung", "richtlinie", "gesetz", "directive", "regulation",
        "(eu)", "(eg)", "act", "ley", "loi", "törvény", "código",
    ]
    if any(ind in lower for ind in law_indicators):
        return SOURCE_TYPE_LAW

    guideline_indicators = [
        "edpb", "leitlinie", "guideline", "wp2", "bsi", "empfehlung",
    ]
    if any(ind in lower for ind in guideline_indicators):
        return SOURCE_TYPE_GUIDELINE

    framework_indicators = [
        "enisa", "nist", "owasp", "oecd", "cisa", "framework", "iso",
    ]
    if any(ind in lower for ind in framework_indicators):
        return SOURCE_TYPE_FRAMEWORK

    return SOURCE_TYPE_FRAMEWORK
