"""
Proof Profiles: Contracts over proof kinds

Defines named proof profiles that specify:
- Required proof kinds (must be present or receipt fails)
- Optional proof kinds (may be present)
- Minimum dignity score
- Tri-temporal enforcement
- Extra witness requirements

Profiles are resolved at emit time and embedded in the receipt
so audits never depend on external config.

---
feature:
  id: feature.proof_profiles
  name: Proof Profiles
  kind: module
  summary: Named proof contracts for different trust levels
  owners: ["@agent-c"]
  stage: production
  tags: [receipts, chain-of-trust, profiles]
  depends_on: [feature.proof_config]
---
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Dict, List, Optional

from loom.proof_config import AttestationLevel
from receipts.models_v1 import ProfileSnapshotV1, ProofKind


__all__ = [
    "ProofProfile",
    "PROOF_PROFILES",
    "resolve_profile",
    "get_profile_snapshot",
]


@dataclass(frozen=True)
class ProofProfile:
    """
    A named proof contract.

    Specifies what proofs are required/optional and what constraints apply.
    """
    profile_id: str
    attestation_level: AttestationLevel
    required_proofs: List[str]
    optional_proofs: List[str] = field(default_factory=list)
    min_dignity: float = 0.0
    enforce_tri_temporal: bool = True
    extra_witness_required: Optional[str] = None
    strict_mode: bool = False  # If True, missing proofs = refusal, not degraded

    def to_snapshot(self) -> ProfileSnapshotV1:
        """Convert to a frozen ProfileSnapshotV1 for embedding in receipts."""
        return ProfileSnapshotV1(
            proof_profile_id=self.profile_id,
            attestation_level=self.attestation_level.value,
            required_proofs=list(self.required_proofs),
            optional_proofs=list(self.optional_proofs),
            min_dignity=self.min_dignity,
            enforce_tri_temporal=self.enforce_tri_temporal,
            extra_witness_required=self.extra_witness_required,
        )


# -----------------------------------------------------------------------------
# Standard Proof Profiles
# -----------------------------------------------------------------------------

PROOF_PROFILES: Dict[str, ProofProfile] = {
    # L0: Development - no crypto guarantees
    "local-dev": ProofProfile(
        profile_id="local-dev",
        attestation_level=AttestationLevel.L0_DEV,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
        ],
        optional_proofs=[
            ProofKind.LOCAL_SIGNATURE.value,
        ],
        min_dignity=0.0,
        enforce_tri_temporal=False,
        strict_mode=False,
    ),

    # L1: Signed - local signature only
    "standard-local": ProofProfile(
        profile_id="standard-local",
        attestation_level=AttestationLevel.L1_SIGNED,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
            ProofKind.LOCAL_SIGNATURE.value,
        ],
        optional_proofs=[],
        min_dignity=0.10,
        enforce_tri_temporal=True,
        strict_mode=False,
    ),

    # L2: Timestamped - signature + TSA
    "standard-enterprise": ProofProfile(
        profile_id="standard-enterprise",
        attestation_level=AttestationLevel.L2_TIMESTAMPED,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
            ProofKind.LOCAL_SIGNATURE.value,
            ProofKind.TSA_RFC3161.value,
        ],
        optional_proofs=[
            ProofKind.TRANSPARENCY_LOG.value,
        ],
        min_dignity=0.10,
        enforce_tri_temporal=True,
        strict_mode=False,  # Allow degraded if TSA down
    ),

    # L3: Anchored - signature + TSA + Merkle batch
    "regulated": ProofProfile(
        profile_id="regulated",
        attestation_level=AttestationLevel.L3_ANCHORED,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
            ProofKind.LOCAL_SIGNATURE.value,
            ProofKind.TSA_RFC3161.value,
        ],
        optional_proofs=[
            ProofKind.TRANSPARENCY_LOG.value,
        ],
        min_dignity=0.15,
        enforce_tri_temporal=True,
        strict_mode=False,  # Allow degraded with explicit marking
    ),

    # L5: Court-Grade - full chain with Rekor
    "court-grade": ProofProfile(
        profile_id="court-grade",
        attestation_level=AttestationLevel.L5_COURT_GRADE,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
            ProofKind.LOCAL_SIGNATURE.value,
            ProofKind.TSA_RFC3161.value,
            ProofKind.TRANSPARENCY_LOG.value,
        ],
        optional_proofs=[
            ProofKind.ENCLAVE_ATTESTATION.value,
        ],
        min_dignity=0.15,
        enforce_tri_temporal=True,
        strict_mode=True,  # No degraded mode - fail if any proof missing
    ),

    # L5: Clinical-Grade - court-grade + human witness
    "clinical-grade": ProofProfile(
        profile_id="clinical-grade",
        attestation_level=AttestationLevel.L5_COURT_GRADE,
        required_proofs=[
            ProofKind.CONTENT_DIGEST.value,
            ProofKind.LOCAL_SIGNATURE.value,
            ProofKind.TSA_RFC3161.value,
            ProofKind.TRANSPARENCY_LOG.value,
        ],
        optional_proofs=[
            ProofKind.ENCLAVE_ATTESTATION.value,
            ProofKind.WITNESS_SIGNATURE.value,
        ],
        min_dignity=0.20,
        enforce_tri_temporal=True,
        extra_witness_required="human_clinician",
        strict_mode=True,  # No degraded mode
    ),
}


# -----------------------------------------------------------------------------
# Domain -> Profile Mapping
# -----------------------------------------------------------------------------

DOMAIN_PROFILE_MAP: Dict[str, Dict[str, str]] = {
    "clinical": {
        "default": "clinical-grade",
        "low_risk": "regulated",
    },
    "finance": {
        "default": "court-grade",
        "low_value": "regulated",
    },
    "ops": {
        "default": "standard-enterprise",
        "low_risk": "standard-local",
    },
    "sandbox": {
        "default": "local-dev",
    },
    "governance": {
        "default": "regulated",
    },
    "markets": {
        "default": "regulated",
    },
    "mlb": {
        "default": "standard-enterprise",
    },
}


def resolve_profile(
    domain: str,
    risk_level: str = "default",
    tenant_id: Optional[str] = None,
    profile_override: Optional[str] = None,
) -> ProofProfile:
    """
    Resolve the appropriate proof profile for a domain/risk combination.

    Args:
        domain: Domain namespace (clinical, finance, ops, etc.)
        risk_level: Risk level within domain (default, low_risk, low_value, etc.)
        tenant_id: Optional tenant for tenant-specific overrides (future)
        profile_override: Explicit profile name override

    Returns:
        ProofProfile to use for this receipt
    """
    # Explicit override takes precedence
    if profile_override and profile_override in PROOF_PROFILES:
        return PROOF_PROFILES[profile_override]

    # Look up domain mapping
    domain_map = DOMAIN_PROFILE_MAP.get(domain.lower(), {})
    profile_id = domain_map.get(risk_level, domain_map.get("default", "standard-local"))

    if profile_id not in PROOF_PROFILES:
        # Fallback to standard-local if unknown
        profile_id = "standard-local"

    return PROOF_PROFILES[profile_id]


def get_profile_snapshot(
    domain: str,
    risk_level: str = "default",
    tenant_id: Optional[str] = None,
    profile_override: Optional[str] = None,
) -> ProfileSnapshotV1:
    """
    Get a frozen ProfileSnapshotV1 for embedding in a receipt.

    This is a convenience wrapper around resolve_profile().
    """
    profile = resolve_profile(domain, risk_level, tenant_id, profile_override)
    return profile.to_snapshot()
