"""Core types for the Orxaq causal reasoning engine.

All types use stdlib only (ADR-007). Regulatory annotations
support SR 11-7 compliance (ADR-008).
"""

from __future__ import annotations

import hashlib
import json
from dataclasses import dataclass
from enum import Enum


class CausalRole(Enum):
    """Role of a variable in a causal graph."""

    TREATMENT = "treatment"
    OUTCOME = "outcome"
    CONFOUNDER = "confounder"
    MEDIATOR = "mediator"
    COLLIDER = "collider"
    INSTRUMENT = "instrument"
    MODERATOR = "moderator"
    EXOGENOUS = "exogenous"


class VariableType(Enum):
    """Temporal nature of a variable."""

    STATIC = "static"
    DYNAMIC = "dynamic"
    MACRO = "macro"
    DERIVED = "derived"


class SensitivityLevel(Enum):
    """Data classification per SR 11-7."""

    PUBLIC = "public"
    INTERNAL = "internal"
    CONFIDENTIAL = "confidential"
    RESTRICTED = "restricted"


@dataclass(frozen=True)
class Entity:
    """A node in the World DAG representing a causal variable.

    Immutable by design — changes create new entities with audit trail.
    """

    entity_id: str
    name: str
    description: str = ""
    causal_role: CausalRole = CausalRole.EXOGENOUS
    variable_type: VariableType = VariableType.STATIC
    sensitivity: SensitivityLevel = SensitivityLevel.INTERNAL
    domain: str = ""
    units: str = ""
    bounds: tuple[float | None, float | None] = (None, None)
    regulatory_tags: tuple[str, ...] = ()
    metadata: tuple[tuple[str, str], ...] = ()

    @property
    def fingerprint(self) -> str:
        """SHA-256 fingerprint of the entity's identity-defining fields."""
        data = json.dumps(
            {
                "entity_id": self.entity_id,
                "name": self.name,
                "causal_role": self.causal_role.value,
                "variable_type": self.variable_type.value,
                "sensitivity": self.sensitivity.value,
                "domain": self.domain,
            },
            sort_keys=True,
        )
        return hashlib.sha256(data.encode()).hexdigest()


@dataclass(frozen=True)
class CausalEdge:
    """A directed edge in the World DAG representing a causal mechanism."""

    source: str
    target: str
    mechanism: str = ""
    confidence: float = 0.5
    soliton_score: float = 0.5
    provenance: str = ""
    is_immutable: bool = False
    edge_type: str = "causal"
    temporal_lag: float = 0.0

    @property
    def edge_id(self) -> str:
        """Human-readable edge identifier."""
        return f"{self.source}\u2192{self.target}"


@dataclass(frozen=True)
class DimensionDef:
    """Definition of an architectural dimension (Zachman completeness)."""

    name: str
    description: str = ""
    domain: str = ""
    regulatory_tags: tuple[str, ...] = ()
    status: str = "seam-spec"


class CycleError(Exception):
    """Raised when adding an edge would create a cycle in the World DAG."""
