"""Strict, privacy-safe contracts for ARR processing deliveries."""

from __future__ import annotations

import re
from dataclasses import dataclass
from datetime import date
from pathlib import PurePosixPath
from typing import Any, Dict, Mapping, Optional


DELIVERY_SCHEMA_VERSION = "1.0"
# v4 is the active fixed-processor contract.  v3 remains parseable only for
# historical/direct-MCP compatibility and must never acquire review behavior.
LEGACY_RESULT_SCHEMA_VERSION = "3.0"
RESULT_SCHEMA_VERSION = "4.0"
SUPPORTED_RESULT_SCHEMA_VERSIONS = frozenset(
    {LEGACY_RESULT_SCHEMA_VERSION, RESULT_SCHEMA_VERSION}
)
XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
SHA256_RE = re.compile(r"^[0-9a-f]{64}$")
OPAQUE_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$")
PROCESSOR_VERSION_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._+-]{0,63}$")

TOP_LEVEL_FIELDS = {
    "delivery_schema_version",
    "delivery_id",
    "job_id",
    "attempt_no",
    "status",
    "processor_version",
    "rule_set_sha256",
    "result_schema_version",
    "business_date",
    "artifacts",
}
ARTIFACT_FIELDS = {
    "object_key",
    "original_filename",
    "sha256",
    "byte_size",
    "mime_type",
}
ARTIFACT_ROLES = {
    "source_xml",
    "daily_report",
    "result_json",
    "structured_result_json",
    "exception_report",
    "manual_override_json",
}
LEGACY_ARTIFACT_ROLES = ARTIFACT_ROLES - {"manual_override_json"}
ROLE_CONTRACTS = {
    "source_xml": ("opera_xml", ".xml", "application/xml"),
    "booking_source": ("booking_excel", ".xlsx", XLSX_MIME),
    "daily_report": ("daily_xlsx", ".xlsx", XLSX_MIME),
    "monthly_report": ("monthly_xlsx", ".xlsx", XLSX_MIME),
    "company_report": ("company_ten_day_xlsx", ".xlsx", XLSX_MIME),
    "result_json": ("result_json", ".json", "application/json"),
    "structured_result_json": (
        "structured_result_json",
        ".json",
        "application/json",
    ),
    "exception_report": ("exception_xlsx", ".xlsx", XLSX_MIME),
    "manual_override_json": (
        "manual_override_json",
        ".json",
        "application/json",
    ),
}
ARTIFACT_SIZE_LIMITS = {
    "source_xml": 100 * 1024 * 1024,
    "booking_source": 25 * 1024 * 1024,
    "daily_report": 100 * 1024 * 1024,
    "monthly_report": 100 * 1024 * 1024,
    "company_report": 100 * 1024 * 1024,
    "result_json": 5 * 1024 * 1024,
    "structured_result_json": 50 * 1024 * 1024,
    "exception_report": 20 * 1024 * 1024,
    "manual_override_json": 5 * 1024 * 1024,
}


def artifact_roles_for_schema(result_schema_version: str) -> set[str]:
    if result_schema_version == LEGACY_RESULT_SCHEMA_VERSION:
        return set(LEGACY_ARTIFACT_ROLES)
    if result_schema_version == RESULT_SCHEMA_VERSION:
        return set(ARTIFACT_ROLES)
    _fail("DELIVERY_INVALID", "result schema version is unsupported")


class IngestionError(RuntimeError):
    """A stable, non-sensitive validation or persistence error."""

    def __init__(
        self,
        code: str,
        safe_message: str,
        *,
        retryable: bool = False,
    ):
        super().__init__(safe_message)
        self.code = code
        self.safe_message = safe_message
        self.retryable = retryable


def _fail(code: str, safe_message: str) -> None:
    raise IngestionError(code, safe_message)


def _strict_mapping(value: Any, expected: set[str], label: str) -> Mapping[str, Any]:
    if not isinstance(value, Mapping) or set(value) != expected:
        _fail("DELIVERY_INVALID", f"{label} field set is invalid")
    return value


def _valid_object_key(value: Any) -> bool:
    if not isinstance(value, str) or not value or len(value) > 1024:
        return False
    if (
        value.startswith("/")
        or value.endswith("/")
        or "\\" in value
        or "?" in value
        or "#" in value
        or "//" in value
        or any(ord(char) < 32 or ord(char) == 127 for char in value)
    ):
        return False
    path = PurePosixPath(value)
    return not path.is_absolute() and ".." not in path.parts and "." not in path.parts


def _valid_basename(value: Any) -> bool:
    return (
        isinstance(value, str)
        and 0 < len(value) <= 255
        and PurePosixPath(value).name == value
        and value not in {".", ".."}
        and "/" not in value
        and "\\" not in value
        and not any(ord(char) < 32 or ord(char) == 127 for char in value)
    )


@dataclass(frozen=True)
class ArtifactRef:
    role: str
    file_kind: str
    object_key: str
    original_filename: str
    sha256: str
    byte_size: int
    mime_type: str

    @classmethod
    def from_dict(cls, role: str, payload: Any) -> "ArtifactRef":
        if role not in ROLE_CONTRACTS:
            _fail("DELIVERY_INVALID", "artifact role is invalid")
        values = _strict_mapping(payload, ARTIFACT_FIELDS, f"{role} artifact")
        file_kind, extension, expected_mime = ROLE_CONTRACTS[role]
        object_key = values.get("object_key")
        original_filename = values.get("original_filename")
        sha256 = values.get("sha256")
        byte_size = values.get("byte_size")
        mime_type = values.get("mime_type")
        if (
            not _valid_object_key(object_key)
            or not _valid_basename(original_filename)
            or not str(original_filename).lower().endswith(extension)
            or not isinstance(sha256, str)
            or not SHA256_RE.fullmatch(sha256)
            or not isinstance(byte_size, int)
            or isinstance(byte_size, bool)
            or byte_size < 0
            or mime_type != expected_mime
        ):
            _fail("ARTIFACT_REFERENCE_INVALID", f"{role} metadata is invalid")
        return cls(
            role=role,
            file_kind=file_kind,
            object_key=str(object_key),
            original_filename=str(original_filename),
            sha256=sha256,
            byte_size=byte_size,
            mime_type=str(mime_type),
        )

    def to_dict(self) -> Dict[str, Any]:
        return {
            "object_key": self.object_key,
            "original_filename": self.original_filename,
            "sha256": self.sha256,
            "byte_size": self.byte_size,
            "mime_type": self.mime_type,
        }


@dataclass(frozen=True)
class DeliveryEnvelope:
    delivery_id: str
    job_id: str
    attempt_no: int
    status: str
    processor_version: str
    rule_set_sha256: str
    result_schema_version: str
    business_date: Optional[date]
    artifacts: Mapping[str, Optional[ArtifactRef]]

    @classmethod
    def from_dict(cls, payload: Any) -> "DeliveryEnvelope":
        values = _strict_mapping(payload, TOP_LEVEL_FIELDS, "delivery")
        if values.get("delivery_schema_version") != DELIVERY_SCHEMA_VERSION:
            _fail("DELIVERY_INVALID", "delivery schema version is unsupported")
        delivery_id = values.get("delivery_id")
        job_id = values.get("job_id")
        attempt_no = values.get("attempt_no")
        status = values.get("status")
        processor_version = values.get("processor_version")
        rule_set_sha256 = values.get("rule_set_sha256")
        result_schema_version = values.get("result_schema_version")
        if not isinstance(delivery_id, str) or not OPAQUE_ID_RE.fullmatch(delivery_id):
            _fail("DELIVERY_INVALID", "delivery identifier is invalid")
        if not isinstance(job_id, str) or not OPAQUE_ID_RE.fullmatch(job_id):
            _fail("DELIVERY_INVALID", "job identifier is invalid")
        if not isinstance(attempt_no, int) or isinstance(attempt_no, bool) or attempt_no < 1:
            _fail("DELIVERY_INVALID", "attempt number is invalid")
        if (
            not isinstance(processor_version, str)
            or not PROCESSOR_VERSION_RE.fullmatch(processor_version)
        ):
            _fail("DELIVERY_INVALID", "processor version is invalid")
        if not isinstance(rule_set_sha256, str) or not SHA256_RE.fullmatch(rule_set_sha256):
            _fail("DELIVERY_INVALID", "rule set identity is invalid")
        if result_schema_version not in SUPPORTED_RESULT_SCHEMA_VERSIONS:
            _fail("DELIVERY_INVALID", "result schema version is unsupported")
        allowed_statuses = {"success", "failed"}
        if result_schema_version == RESULT_SCHEMA_VERSION:
            allowed_statuses.add("review_required")
        if status not in allowed_statuses:
            _fail("DELIVERY_INVALID", "delivery status is invalid")

        raw_business_date = values.get("business_date")
        parsed_date: Optional[date]
        if raw_business_date is None:
            parsed_date = None
        elif isinstance(raw_business_date, str):
            try:
                parsed_date = date.fromisoformat(raw_business_date)
            except ValueError:
                _fail("DELIVERY_INVALID", "business date is invalid")
        else:
            _fail("DELIVERY_INVALID", "business date is invalid")

        artifact_roles = artifact_roles_for_schema(str(result_schema_version))
        raw_artifacts = _strict_mapping(values.get("artifacts"), artifact_roles, "artifact")
        artifacts: Dict[str, Optional[ArtifactRef]] = {}
        for role in sorted(artifact_roles):
            raw_artifact = raw_artifacts.get(role)
            artifacts[role] = (
                None if raw_artifact is None else ArtifactRef.from_dict(role, raw_artifact)
            )
        always_required = ("source_xml", "result_json", "structured_result_json")
        if any(artifacts[role] is None for role in always_required):
            _fail("DELIVERY_INVALID", "required delivery artifact is missing")
        manual_override = artifacts.get("manual_override_json")
        if status == "success":
            if (
                parsed_date is None
                or artifacts["daily_report"] is None
                or artifacts["exception_report"] is not None
            ):
                _fail("DELIVERY_INVALID", "success delivery artifact shape is invalid")
        elif status == "review_required":
            if (
                parsed_date is None
                or artifacts["daily_report"] is not None
                or artifacts["exception_report"] is not None
                or manual_override is not None
            ):
                _fail("DELIVERY_INVALID", "review delivery artifact shape is invalid")
        elif artifacts["daily_report"] is not None or artifacts["exception_report"] is None:
            _fail("DELIVERY_INVALID", "failed delivery artifact shape is invalid")
        elif manual_override is not None:
            _fail("DELIVERY_INVALID", "failed delivery artifact shape is invalid")
        return cls(
            delivery_id=delivery_id,
            job_id=job_id,
            attempt_no=attempt_no,
            status=status,
            processor_version=processor_version,
            rule_set_sha256=rule_set_sha256,
            result_schema_version=result_schema_version,
            business_date=parsed_date,
            artifacts=artifacts,
        )

    def to_dict(self) -> Dict[str, Any]:
        return {
            "delivery_schema_version": DELIVERY_SCHEMA_VERSION,
            "delivery_id": self.delivery_id,
            "job_id": self.job_id,
            "attempt_no": self.attempt_no,
            "status": self.status,
            "processor_version": self.processor_version,
            "rule_set_sha256": self.rule_set_sha256,
            "result_schema_version": self.result_schema_version,
            "business_date": self.business_date.isoformat() if self.business_date else None,
            "artifacts": {
                role: reference.to_dict() if reference is not None else None
                for role, reference in self.artifacts.items()
            },
        }
