from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from rights_filter.domain.records import DataClass


@dataclass(frozen=True)
class DataClassPolicy:
    access_roles: set[str]
    retention: str
    deletion: str
    correction: str


class GovernancePolicyRegistry:
    def __init__(self, policies: dict[DataClass, DataClassPolicy]) -> None:
        self._policies = policies

    @classmethod
    def default(cls) -> "GovernancePolicyRegistry":
        return cls(
            {
                DataClass.ORIGINAL_IMAGE: DataClassPolicy(
                    {"operator", "admin"},
                    "application retention policy",
                    "delete or detach according to submission lifecycle",
                    "correct through source submission workflow",
                ),
                DataClass.INTERNAL_DERIVATIVE: DataClassPolicy(
                    {"system", "admin"},
                    "short-lived analysis retention",
                    "delete after analysis or retention expiry",
                    "regenerate from corrected original",
                ),
                DataClass.EXTERNAL_DERIVATIVE: DataClassPolicy(
                    {"system", "admin"},
                    "short-lived external-call retention",
                    "delete after provider request completes",
                    "regenerate only after compliance-approved rerun",
                ),
                DataClass.IMAGE_FINGERPRINT: DataClassPolicy(
                    {"operator", "admin", "system"},
                    "evidence retention policy",
                    "delete or deactivate with source correction",
                    "deactivate stale automatic references",
                ),
                DataClass.WEB_EVIDENCE: DataClassPolicy(
                    {"operator", "admin"},
                    "evidence retention policy",
                    "delete with analysis evidence policy",
                    "supersede with new analysis run",
                ),
                DataClass.SEARCH_EVIDENCE: DataClassPolicy(
                    {"operator", "admin"},
                    "search evidence retention policy",
                    "delete with analysis evidence policy",
                    "supersede with new search-enriched analysis",
                ),
                DataClass.LLM_SUMMARY: DataClassPolicy(
                    {"operator", "admin"},
                    "operator-only summary retention policy",
                    "delete with analysis evidence policy",
                    "regenerate from corrected source evidence",
                ),
                DataClass.PROVIDER_METADATA: DataClassPolicy(
                    {"admin"},
                    "provider audit retention policy",
                    "delete with provider audit policy",
                    "correct through provider evidence review",
                ),
                DataClass.OPERATOR_NOTE: DataClassPolicy(
                    {"operator", "admin"},
                    "decision audit retention policy",
                    "delete with decision audit policy",
                    "append correction rather than overwriting audit trail",
                ),
            }
        )

    def policy_for(self, data_class: DataClass) -> DataClassPolicy:
        return self._policies[data_class]


def assert_no_biometric_template(payload: dict[str, Any]) -> None:
    forbidden_keys = {"embedding", "face_embedding", "biometric_template"}
    if forbidden_keys.intersection(payload):
        raise ValueError("biometric template storage is not allowed")


def assert_operator_evidence_payload_allowed(
    data_class: DataClass, payload: dict[str, Any]
) -> None:
    assert_no_biometric_template(payload)

    if data_class == DataClass.SEARCH_EVIDENCE:
        forbidden_image_keys = {
            "original_image",
            "internal_derivative",
            "external_derivative",
            "image_payload",
            "image_content",
            "derivative",
            "content",
        }
        if forbidden_image_keys.intersection(payload):
            raise ValueError("image payload cannot be stored for search evidence")

    if data_class == DataClass.LLM_SUMMARY:
        source_urls = payload.get("source_urls") or []
        source_evidence_ids = payload.get("source_evidence_ids") or []
        if not source_urls and not source_evidence_ids:
            raise ValueError("LLM summary must reference source evidence")
