"""
compliance_registry.py — Single source of truth for all compliance tag constants.

Never write compliance strings anywhere else in the codebase.
Import named constants and use refs_to_ids() to build compliance_tags lists.

Usage in attack modules:
    from sichgate.compliance_registry import (
        BUNDLE_BIAS_FAIRNESS, ISO_42001_6_1, refs_to_ids
    )
    compliance_tags = refs_to_ids(BUNDLE_BIAS_FAIRNESS + [ISO_42001_6_1])
"""

from dataclasses import dataclass, asdict
from typing import List, Optional, Dict
from enum import Enum


class Framework(str, Enum):
    """Supported compliance frameworks."""
    EU_AI_ACT   = "EU AI Act"
    GDPR        = "GDPR"
    NIST_AI_RMF = "NIST AI RMF"
    OWASP_LLM   = "OWASP LLM Top 10"
    ISO_42001   = "ISO/IEC 42001"
    HIPAA       = "HIPAA"
    CYBER_AI    = "NIST Cyber AI Profile"  # NIST IR 8596, Dec 2025 preliminary draft


@dataclass(frozen=True)
class ComplianceRef:
    """
    A single compliance reference linking to a specific regulatory requirement.

    id:          Machine-readable hyphenated ID used in JSON output.
                 Example: "EU-AI-ACT-ART-9"
    framework:   Human-readable framework name. Example: "EU AI Act"
    reference:   Specific article, section, or control.
    description: Plain-English description of the requirement.
    url:         Canonical reference URL.
    """
    id: str
    framework: str
    reference: str
    description: str
    url: str

    def to_dict(self) -> dict:
        return asdict(self)


# ── EU AI Act ─────────────────────────────────────────────────────────────────

EU_AI_ACT_ART_6 = ComplianceRef(
    id          = "EU-AI-ACT-ART-6",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 6 — Classification Rules for High-Risk AI Systems",
    description = (
        "An AI system is high-risk where it falls within the categories listed in "
        "Annex III. Bias and fairness testing is required for systems affecting "
        "fundamental rights."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ART_9 = ComplianceRef(
    id          = "EU-AI-ACT-ART-9",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 9 — Risk Management System",
    description = (
        "Providers of high-risk AI systems must establish, implement, document and "
        "maintain a risk management system covering the full lifecycle. Adversarial "
        "test results are direct evidence for this requirement."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ART_10 = ComplianceRef(
    id          = "EU-AI-ACT-ART-10",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 10 — Data and Data Governance",
    description = (
        "Training, validation and test datasets must be relevant, representative, "
        "free of errors and complete. Bias findings are direct evidence of "
        "Art. 10 non-compliance."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ART_13 = ComplianceRef(
    id          = "EU-AI-ACT-ART-13",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 13 — Transparency and Provision of Information to Deployers",
    description = (
        "High-risk AI systems must be designed to enable deployers to interpret outputs. "
        "Failures include inability to explain system behaviour and system prompt "
        "extraction vulnerabilities."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ART_14 = ComplianceRef(
    id          = "EU-AI-ACT-ART-14",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 14 — Human Oversight",
    description = (
        "High-risk AI systems must allow effective human oversight. Sycophancy and "
        "competing-objectives failures undermine the human's ability to correct or "
        "override the system."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ART_15 = ComplianceRef(
    id          = "EU-AI-ACT-ART-15",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Article 15 — Accuracy, Robustness and Cybersecurity",
    description = (
        "High-risk AI systems must be resilient against attempts by unauthorised third "
        "parties to alter their use, outputs or performance. SichGate's entire attack "
        "suite is direct evidence for this article."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)

EU_AI_ACT_ANNEX_III = ComplianceRef(
    id          = "EU-AI-ACT-ANNEX-III",
    framework   = Framework.EU_AI_ACT.value,
    reference   = "Annex III — High-Risk AI Systems",
    description = (
        "Biometric identification, categorisation, and emotion recognition systems "
        "are classified as high-risk. Biometric and voice AI customers must demonstrate "
        "conformity assessment under this annex."
    ),
    url         = "https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32024R1689",
)


# ── GDPR ──────────────────────────────────────────────────────────────────────

GDPR_ART_5 = ComplianceRef(
    id          = "GDPR-ART-5",
    framework   = Framework.GDPR.value,
    reference   = "Article 5 — Principles Relating to Processing of Personal Data",
    description = (
        "Personal data shall be processed lawfully, fairly and in a transparent manner; "
        "collected for specified purposes; adequate, relevant and limited. Data "
        "extraction attacks reveal violations of data minimisation principles."
    ),
    url         = "https://gdpr-info.eu/art-5-gdpr/",
)

GDPR_ART_5_1_D = ComplianceRef(
    id          = "GDPR-ART-5-1-D",
    framework   = Framework.GDPR.value,
    reference   = "Article 5(1)(d) — Accuracy Principle",
    description = (
        "Personal data shall be accurate and, where necessary, kept up to date. "
        "Hallucination findings directly evidence inaccurate outputs that may "
        "affect data subjects."
    ),
    url         = "https://gdpr-info.eu/art-5-gdpr/",
)

GDPR_ART_17 = ComplianceRef(
    id          = "GDPR-ART-17",
    framework   = Framework.GDPR.value,
    reference   = "Article 17 — Right to Erasure ('Right to be Forgotten')",
    description = (
        "Data subjects have the right to erasure of their personal data. Membership "
        "inference attacks can detect if 'forgotten' data persists in model weights."
    ),
    url         = "https://gdpr-info.eu/art-17-gdpr/",
)

GDPR_ART_22 = ComplianceRef(
    id          = "GDPR-ART-22",
    framework   = Framework.GDPR.value,
    reference   = "Article 22 — Automated Individual Decision-Making",
    description = (
        "Individuals have the right not to be subject to solely automated decisions "
        "producing significant effects. Bias findings are direct evidence of Art. 22 "
        "non-compliance when differential scoring affects real decisions."
    ),
    url         = "https://gdpr-info.eu/art-22-gdpr/",
)

GDPR_ART_25 = ComplianceRef(
    id          = "GDPR-ART-25",
    framework   = Framework.GDPR.value,
    reference   = "Article 25 — Data Protection by Design and Default",
    description = (
        "Controllers must implement privacy-preserving design. Privacy-preserving "
        "design must resist extraction and inference attacks."
    ),
    url         = "https://gdpr-info.eu/art-25-gdpr/",
)

GDPR_ART_32 = ComplianceRef(
    id          = "GDPR-ART-32",
    framework   = Framework.GDPR.value,
    reference   = "Article 32 — Security of Processing",
    description = (
        "Controllers and processors must implement appropriate technical and "
        "organisational measures to ensure security including confidentiality, "
        "integrity and availability. All security attacks test adequacy of measures."
    ),
    url         = "https://gdpr-info.eu/art-32-gdpr/",
)

GDPR_ART_35 = ComplianceRef(
    id          = "GDPR-ART-35",
    framework   = Framework.GDPR.value,
    reference   = "Article 35 — Data Protection Impact Assessment",
    description = (
        "Where processing is likely to result in high risk, a DPIA is required. "
        "SichGate reports serve as technical input for DPIA requirements."
    ),
    url         = "https://gdpr-info.eu/art-35-gdpr/",
)


# ── HIPAA ─────────────────────────────────────────────────────────────────────

HIPAA_164_308 = ComplianceRef(
    id          = "HIPAA-164-308",
    framework   = Framework.HIPAA.value,
    reference   = "§164.308 — Administrative Safeguards",
    description = (
        "Risk analysis and risk management for PHI. AI red teaming results constitute "
        "the risk analysis documentation required under the HIPAA Security Rule "
        "administrative safeguards."
    ),
    url         = "https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/",
)

HIPAA_164_312 = ComplianceRef(
    id          = "HIPAA-164-312",
    framework   = Framework.HIPAA.value,
    reference   = "§164.312 — Technical Safeguards",
    description = (
        "Access controls and encryption for ePHI. A model that can be prompted to "
        "reveal patient information or bypass access controls fails this requirement."
    ),
    url         = "https://www.hhs.gov/hipaa/for-professionals/security/laws-regulations/",
)


# ── NIST AI RMF v2.0 (Feb 2024) ───────────────────────────────────────────────

NIST_AI_RMF_GOVERN = ComplianceRef(
    id          = "NIST-AI-RMF-GOVERN",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "GOVERN — Governance Function",
    description = (
        "A culture of AI risk management is cultivated and present. Organisational "
        "context is established for ongoing AI risk governance."
    ),
    url         = "https://www.nist.gov/itl/ai-risk-management-framework",
)

NIST_AI_RMF_MAP = ComplianceRef(
    id          = "NIST-AI-RMF-MAP",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MAP — Map Function",
    description = (
        "Context is recognised and risks related to context are identified. Attack "
        "surface mapping identifies risks in specific deployment contexts."
    ),
    url         = "https://www.nist.gov/itl/ai-risk-management-framework",
)

NIST_AI_RMF_MEASURE = ComplianceRef(
    id          = "NIST-AI-RMF-MEASURE",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MEASURE — Measure Function",
    description = (
        "Appropriate methods and metrics are identified and applied. SichGate provides "
        "standardised metrics for measuring AI security."
    ),
    url         = "https://www.nist.gov/itl/ai-risk-management-framework",
)

NIST_AI_RMF_MANAGE = ComplianceRef(
    id          = "NIST-AI-RMF-MANAGE",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MANAGE — Manage Function",
    description = (
        "Risks are prioritised and acted upon. Response plans are developed and "
        "implemented. Remediation guidance enables risk management actions."
    ),
    url         = "https://www.nist.gov/itl/ai-risk-management-framework",
)

NIST_GOVERN_1_1 = ComplianceRef(
    id          = "NIST-AI-RMF-GV-1.1",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "GOVERN 1.1 — Transparency",
    description = (
        "Policies, processes and procedures for AI transparency are established. "
        "System prompt extraction and hallucination probes test transparency failures."
    ),
    url         = "https://airc.nist.gov/RMF/1",
)

NIST_GOVERN_1_7 = ComplianceRef(
    id          = "NIST-AI-RMF-GV-1.7",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "GOVERN 1.7 — Human Oversight",
    description = (
        "Processes are in place to ensure effective human oversight of AI systems. "
        "Sycophancy, consistency, and competing-objectives probes test whether the "
        "model undermines human oversight capability."
    ),
    url         = "https://airc.nist.gov/RMF/1",
)

NIST_MEASURE_2_3 = ComplianceRef(
    id          = "NIST-AI-RMF-MS-2.3",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MEASURE 2.3 — Accuracy and Performance",
    description = (
        "AI system accuracy, reliability and performance are evaluated. Hallucination "
        "probes directly test accuracy and factual reliability."
    ),
    url         = "https://airc.nist.gov/RMF/2",
)

NIST_MEASURE_2_5 = ComplianceRef(
    id          = "NIST-AI-RMF-MS-2.5",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MEASURE 2.5 — Fairness and Bias",
    description = (
        "AI system bias is evaluated and documented including across demographic "
        "groups, use cases and deployment contexts. Bias and fairness attack results "
        "are the primary evidence for this control."
    ),
    url         = "https://airc.nist.gov/RMF/2",
)

NIST_MEASURE_2_6 = ComplianceRef(
    id          = "NIST-AI-RMF-MS-2.6",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MEASURE 2.6 — Safety",
    description = (
        "AI system safety properties are evaluated and documented. Safe messaging "
        "compliance probes test whether the model avoids producing content that "
        "could cause physical or psychological harm."
    ),
    url         = "https://airc.nist.gov/RMF/2",
)

NIST_MEASURE_2_10 = ComplianceRef(
    id          = "NIST-AI-RMF-MS-2.10",
    framework   = Framework.NIST_AI_RMF.value,
    reference   = "MEASURE 2.10 — Privacy",
    description = (
        "Privacy risks from the AI system are identified and evaluated. Membership "
        "inference, training data extraction, and PII leakage attacks directly "
        "evidence privacy risk."
    ),
    url         = "https://airc.nist.gov/RMF/2",
)


# ── NIST Cyber AI Profile (NIST IR 8596, December 2025 preliminary draft) ─────
# Note: In comment period as of Feb 2026. Final version expected mid-2026.
# Begin aligning now — update control IDs when final version publishes.

CYBER_AI_SECURE_AT_01 = ComplianceRef(
    id          = "CYBER-AI-PROFILE-AT-01",
    framework   = Framework.CYBER_AI.value,
    reference   = "Secure.AT-01 — Adversarial Testing",
    description = (
        "AI systems shall be subject to adversarial testing to identify vulnerabilities "
        "before and during deployment. SichGate's full attack suite directly evidences "
        "this control. Note: NIST IR 8596 is in preliminary draft; final version "
        "expected mid-2026."
    ),
    url         = "https://csrc.nist.gov/pubs/ir/8596/ipd",
)

CYBER_AI_SECURE_AT_02 = ComplianceRef(
    id          = "CYBER-AI-PROFILE-AT-02",
    framework   = Framework.CYBER_AI.value,
    reference   = "Secure.AT-02 — Red Team Exercises",
    description = (
        "Structured red team exercises shall be conducted against AI systems. "
        "SichGate's structured attack categories constitute the red team exercise "
        "record. Note: NIST IR 8596 preliminary draft."
    ),
    url         = "https://csrc.nist.gov/pubs/ir/8596/ipd",
)

CYBER_AI_GOVERN_OC_02 = ComplianceRef(
    id          = "CYBER-AI-PROFILE-OC-02",
    framework   = Framework.CYBER_AI.value,
    reference   = "Govern.OC-02 — AI Lifecycle Security",
    description = (
        "Security considerations shall be integrated throughout the AI lifecycle. "
        "Scheduled SichGate monitoring evidences continuous security assessment "
        "throughout the lifecycle. Note: NIST IR 8596 preliminary draft."
    ),
    url         = "https://csrc.nist.gov/pubs/ir/8596/ipd",
)


# ── ISO/IEC 42001 ─────────────────────────────────────────────────────────────

ISO_42001_6_1 = ComplianceRef(
    id          = "ISO-42001-6.1",
    framework   = Framework.ISO_42001.value,
    reference   = "Clause 6.1 — Actions to Address Risks and Opportunities",
    description = (
        "The organisation shall determine risks and opportunities that need to be "
        "addressed. Every SichGate finding contributes to the clause 6.1 risk "
        "assessment documentation required for ISO 42001 certification."
    ),
    url         = "https://www.iso.org/standard/81230.html",
)

ISO_42001_8_4 = ComplianceRef(
    id          = "ISO-42001-8.4",
    framework   = Framework.ISO_42001.value,
    reference   = "Clause 8.4 — AI System Impact Assessment",
    description = (
        "The organisation shall conduct and document an AI system impact assessment "
        "before deployment. Bias and fairness findings directly inform the impact "
        "assessment for affected demographic groups."
    ),
    url         = "https://www.iso.org/standard/81230.html",
)

ISO_42001_9_1 = ComplianceRef(
    id          = "ISO-42001-9.1",
    framework   = Framework.ISO_42001.value,
    reference   = "Clause 9.1 — Monitoring, Measurement, Analysis and Evaluation",
    description = (
        "The organisation shall determine what needs to be monitored and measured. "
        "SichGate provides continuous measurement capabilities for AI security."
    ),
    url         = "https://www.iso.org/standard/81230.html",
)

ISO_42001_A_6 = ComplianceRef(
    id          = "ISO-42001-A.6",
    framework   = Framework.ISO_42001.value,
    reference   = "Annex A, Clause A.6 — Data for AI Systems",
    description = (
        "Controls for data used in AI systems including provenance, quality and "
        "privacy. Membership inference and training data extraction attacks test "
        "whether data governance controls are effective."
    ),
    url         = "https://www.iso.org/standard/81230.html",
)


# ── OWASP LLM Top 10 (2025 edition) ──────────────────────────────────────────

OWASP_LLM_01 = ComplianceRef(
    id          = "OWASP-LLM-01",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM01:2025 — Prompt Injection",
    description = (
        "Prompt injection via direct or indirect manipulation of model inputs leads "
        "to unauthorised access, data breaches and compromised decision-making. "
        "Includes both direct injection and indirect injection via data channels."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_02 = ComplianceRef(
    id          = "OWASP-LLM-02",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM02:2025 — Insecure Output Handling",
    description = (
        "Improper validation of LLM outputs can result in XSS, CSRF, SSRF, privilege "
        "escalation or remote code execution in downstream systems."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_03 = ComplianceRef(
    id          = "OWASP-LLM-03",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM03:2025 — Training Data Poisoning",
    description = (
        "Tampered training data can impair LLMs, introducing biases, backdoors or "
        "harmful behaviours. Bias and alignment testing detects poisoning effects."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_04 = ComplianceRef(
    id          = "OWASP-LLM-04",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM04:2025 — Model Denial of Service",
    description = (
        "Attackers cause resource-heavy operations on LLMs, leading to service "
        "degradation or high costs."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_05 = ComplianceRef(
    id          = "OWASP-LLM-05",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM05:2025 — Supply Chain Vulnerabilities",
    description = (
        "LLM supply chain can be compromised, affecting training data, models or "
        "deployment platforms."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_06 = ComplianceRef(
    id          = "OWASP-LLM-06",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM06:2025 — Sensitive Information Disclosure",
    description = (
        "Model discloses sensitive or confidential information including training data, "
        "system prompts, PII or PHI. Data extraction and system prompt extraction "
        "attacks directly test this vulnerability."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_07 = ComplianceRef(
    id          = "OWASP-LLM-07",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM07:2025 — Insecure Plugin Design",
    description = (
        "LLM plugins can have insecure inputs and insufficient access control. "
        "Injection attacks test plugin security boundaries."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_08 = ComplianceRef(
    id          = "OWASP-LLM-08",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM08:2025 — Excessive Agency",
    description = (
        "Granting LLMs excessive functionality or autonomy enables unintended or "
        "harmful actions. Alignment attacks test safety constraint enforcement."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_09 = ComplianceRef(
    id          = "OWASP-LLM-09",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM09:2025 — Misinformation",
    description = (
        "Model generates false or misleading outputs presented with false confidence. "
        "Hallucination probes directly test factual accuracy and appropriate "
        "uncertainty expression."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)

OWASP_LLM_10 = ComplianceRef(
    id          = "OWASP-LLM-10",
    framework   = Framework.OWASP_LLM.value,
    reference   = "LLM10:2025 — Model Theft",
    description = (
        "Unauthorised access to proprietary LLMs risks economic loss, competitive "
        "advantage and access to sensitive information. Model extraction attacks "
        "test theft resistance."
    ),
    url         = "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
)


# ── Convenience bundles — use these in attack modules ────────────────────────
# Each bundle maps to the primary regulatory obligation for that attack category.
# Extend with additional refs as needed for specific customer contexts.

BUNDLE_PROMPT_INJECTION     = [OWASP_LLM_01, EU_AI_ACT_ART_15, EU_AI_ACT_ANNEX_III]
BUNDLE_PII_PHI_LEAKAGE      = [GDPR_ART_32, HIPAA_164_312, OWASP_LLM_06, NIST_MEASURE_2_10]
BUNDLE_BIAS_FAIRNESS        = [EU_AI_ACT_ART_10, GDPR_ART_22, NIST_MEASURE_2_5, ISO_42001_8_4]
BUNDLE_HUMAN_OVERSIGHT      = [EU_AI_ACT_ART_14, NIST_GOVERN_1_7]
BUNDLE_TRAINING_DATA        = [GDPR_ART_17, GDPR_ART_32, NIST_MEASURE_2_10]
BUNDLE_SYSTEM_TRANSPARENCY  = [EU_AI_ACT_ART_13, OWASP_LLM_06, NIST_GOVERN_1_1]
BUNDLE_SAFE_MESSAGING       = [NIST_MEASURE_2_6, EU_AI_ACT_ANNEX_III]
BUNDLE_ROBUSTNESS           = [EU_AI_ACT_ART_15, NIST_MEASURE_2_3]
BUNDLE_MEMBERSHIP_INFERENCE = [GDPR_ART_22, GDPR_ART_17, HIPAA_164_308, NIST_MEASURE_2_10]
BUNDLE_ALIGNMENT            = [
    EU_AI_ACT_ART_14, EU_AI_ACT_ART_15, EU_AI_ACT_ANNEX_III,
    NIST_GOVERN_1_7, ISO_42001_6_1,
]

# Phase 2.3 — new attack category bundles
BUNDLE_INFINITE_CONTEXT = [
    EU_AI_ACT_ART_15, EU_AI_ACT_ART_9,
    OWASP_LLM_01, CYBER_AI_SECURE_AT_01, CYBER_AI_SECURE_AT_02,
    ISO_42001_6_1,
]
BUNDLE_MULTITURN_TRAINING = [
    EU_AI_ACT_ART_10, EU_AI_ACT_ART_9,
    OWASP_LLM_03, NIST_AI_RMF_MEASURE, ISO_42001_A_6,
]
BUNDLE_REASONING_CHAIN = [
    EU_AI_ACT_ART_14, EU_AI_ACT_ART_15,
    OWASP_LLM_01, OWASP_LLM_08,
    NIST_GOVERN_1_7, ISO_42001_6_1,
]


# ── Helpers ───────────────────────────────────────────────────────────────────

def refs_to_ids(refs: List[ComplianceRef]) -> List[str]:
    """
    Convert a list of ComplianceRef objects to a flat list of ID strings.

    Use this in every attack module to build compliance_tags. The output is
    a proper JSON list — never a pipe-delimited string.

    Example:
        compliance_tags = refs_to_ids(BUNDLE_BIAS_FAIRNESS + [ISO_42001_6_1])
        # ["EU-AI-ACT-ART-10", "GDPR-ART-22", "NIST-AI-RMF-MS-2.5",
        #  "ISO-42001-8.4", "ISO-42001-6.1"]
    """
    return [r.id for r in refs]


# ── Complete registry ─────────────────────────────────────────────────────────

_ALL_REFS: List[ComplianceRef] = [
    # EU AI Act
    EU_AI_ACT_ART_6, EU_AI_ACT_ART_9, EU_AI_ACT_ART_10, EU_AI_ACT_ART_13,
    EU_AI_ACT_ART_14, EU_AI_ACT_ART_15, EU_AI_ACT_ANNEX_III,
    # GDPR
    GDPR_ART_5, GDPR_ART_5_1_D, GDPR_ART_17, GDPR_ART_22, GDPR_ART_25,
    GDPR_ART_32, GDPR_ART_35,
    # HIPAA
    HIPAA_164_308, HIPAA_164_312,
    # NIST AI RMF — functions
    NIST_AI_RMF_GOVERN, NIST_AI_RMF_MAP, NIST_AI_RMF_MEASURE, NIST_AI_RMF_MANAGE,
    # NIST AI RMF — specific controls
    NIST_GOVERN_1_1, NIST_GOVERN_1_7,
    NIST_MEASURE_2_3, NIST_MEASURE_2_5, NIST_MEASURE_2_6, NIST_MEASURE_2_10,
    # NIST Cyber AI Profile (IR 8596, Dec 2025 preliminary draft)
    CYBER_AI_SECURE_AT_01, CYBER_AI_SECURE_AT_02, CYBER_AI_GOVERN_OC_02,
    # ISO/IEC 42001
    ISO_42001_6_1, ISO_42001_8_4, ISO_42001_9_1, ISO_42001_A_6,
    # OWASP LLM Top 10 (2025)
    OWASP_LLM_01, OWASP_LLM_02, OWASP_LLM_03, OWASP_LLM_04, OWASP_LLM_05,
    OWASP_LLM_06, OWASP_LLM_07, OWASP_LLM_08, OWASP_LLM_09, OWASP_LLM_10,
]

_REFS_BY_ID: Dict[str, ComplianceRef] = {ref.id: ref for ref in _ALL_REFS}


# ── Public API ────────────────────────────────────────────────────────────────

def list_all_refs() -> List[ComplianceRef]:
    """Return all compliance references in the registry."""
    return _ALL_REFS.copy()


def get_ref(ref_id: str) -> Optional[ComplianceRef]:
    """Get a specific compliance reference by ID."""
    return _REFS_BY_ID.get(ref_id)


def ids_to_refs(ref_ids: List[str]) -> List[ComplianceRef]:
    """Convert a list of reference IDs to ComplianceRef objects."""
    return [_REFS_BY_ID[rid] for rid in ref_ids if rid in _REFS_BY_ID]


def refs_by_framework(framework: str) -> List[ComplianceRef]:
    """Get all references for a specific framework."""
    return [ref for ref in _ALL_REFS if ref.framework == framework]


def frameworks_covered() -> List[str]:
    """Return sorted list of all frameworks covered by the registry."""
    return sorted(set(ref.framework for ref in _ALL_REFS))


def search_refs(query: str) -> List[ComplianceRef]:
    """Search references by keyword in reference or description."""
    q = query.lower()
    return [
        ref for ref in _ALL_REFS
        if q in ref.reference.lower() or q in ref.description.lower()
    ]


# ── Attack type → compliance mapping ─────────────────────────────────────────

ATTACK_TYPE_TO_REFS: Dict[str, List[str]] = {
    "prompt_injection":               refs_to_ids(BUNDLE_PROMPT_INJECTION),
    "instruction_hijacking":          refs_to_ids(BUNDLE_PROMPT_INJECTION),
    "payload_splitting":              refs_to_ids(BUNDLE_PROMPT_INJECTION),
    "virtualization":                 refs_to_ids(BUNDLE_PROMPT_INJECTION),
    "json_xml_smuggling":             refs_to_ids(BUNDLE_PROMPT_INJECTION),
    "jailbreak":                      refs_to_ids([OWASP_LLM_01, OWASP_LLM_08,
                                                   EU_AI_ACT_ART_9, EU_AI_ACT_ART_15]),
    "data_extraction":                refs_to_ids([OWASP_LLM_06, GDPR_ART_5,
                                                   GDPR_ART_32, EU_AI_ACT_ART_10]),
    "membership_inference":           refs_to_ids(BUNDLE_MEMBERSHIP_INFERENCE),
    "model_extraction":               refs_to_ids([OWASP_LLM_10, OWASP_LLM_05,
                                                   EU_AI_ACT_ART_15]),
    "hallucination_probe":            refs_to_ids([OWASP_LLM_09, EU_AI_ACT_ART_13,
                                                   NIST_MEASURE_2_3, ISO_42001_6_1]),
    "safe_messaging":                 refs_to_ids(BUNDLE_SAFE_MESSAGING + [ISO_42001_6_1]),
    "bias_fairness":                  refs_to_ids(BUNDLE_BIAS_FAIRNESS + [ISO_42001_6_1]),
    "alignment_sycophancy":           refs_to_ids(BUNDLE_ALIGNMENT),
    "alignment_consistency":          refs_to_ids(BUNDLE_ALIGNMENT),
    "alignment_crescendo":            refs_to_ids(BUNDLE_ALIGNMENT),
    "alignment_competing_objectives": refs_to_ids(BUNDLE_ALIGNMENT),
    "evasion":                        refs_to_ids(BUNDLE_ROBUSTNESS),
    # Phase 2.3
    "infinite_context_cwi":           refs_to_ids(BUNDLE_INFINITE_CONTEXT),
    "infinite_context_etp":           refs_to_ids(BUNDLE_INFINITE_CONTEXT),
    "infinite_context_cod":           refs_to_ids(BUNDLE_INFINITE_CONTEXT),
    "multiturn_rci":                  refs_to_ids(BUNDLE_MULTITURN_TRAINING),
    "multiturn_tdpe":                 refs_to_ids(BUNDLE_MULTITURN_TRAINING),
    "multiturn_ccm":                  refs_to_ids(BUNDLE_MULTITURN_TRAINING),
    "reasoning_coth":                 refs_to_ids(BUNDLE_REASONING_CHAIN),
    "reasoning_scp":                  refs_to_ids(BUNDLE_REASONING_CHAIN),
    "reasoning_le":                   refs_to_ids(BUNDLE_REASONING_CHAIN),
    "reasoning_ca":                   refs_to_ids(BUNDLE_REASONING_CHAIN),
}


def refs_for_attack_type(attack_type: str) -> List[ComplianceRef]:
    """Get compliance references relevant to a specific attack type."""
    ref_ids = ATTACK_TYPE_TO_REFS.get(attack_type.lower(), [])
    return ids_to_refs(ref_ids)
