"""Regulatory Change Intelligence (RCI) — domain objects.

RCI is a read-/reasoning layer ON TOP of the product-first pipeline. It answers
"what changes relative to my existing Regulatory Map?" — NOT "what does the new
law say in general". A RegulatoryChange is simulated/provided INPUT (no ingestion,
no newsletter/mailbox, no RAG); the delta is computed against a stored
ComplianceBaseline (snapshot of the map).

`delta_type` is a THIRD vocabulary — distinct from `ClaimCoverage` (Welt 1, what
the customer claims) and `ComplianceStatus` (Welt 2, verified evidence). The three
must never be conflated. These are application/reasoning types, NOT
compliance-meta-model classes (architecture freeze v1.0 untouched).
"""

from __future__ import annotations

from enum import Enum
from typing import Dict, List, Optional

from pydantic import BaseModel, Field

from compliance.profile.canonical import CanonicalProductRegulatoryProfile
from compliance.reasoning.enums import AuthorityLevel, Confidence
from compliance.regulatory_map.schemas import RegulatoryMap


class DeltaType(str, Enum):
    NEW = "new"  # obligation now applies that was not in the baseline
    CHANGED = "changed"  # existing obligation substantively modified
    REMOVED = "removed"  # obligation no longer applies (repeal)
    ALREADY_COVERED = "already_covered"  # existing obligation, evidence likely suffices
    NEEDS_REVIEW = "needs_review"  # a human must check
    NOT_APPLICABLE = "not_applicable"  # change does not touch this product's map


class ChangeType(str, Enum):
    NEW_REGULATION = "new_regulation"
    AMENDMENT = "amendment"
    REPEAL = "repeal"
    GUIDANCE_UPDATE = "guidance_update"


# ── stored snapshot ──────────────────────────────────────────────────────
class ComplianceBaseline(BaseModel):
    baseline_id: str
    product_profile_snapshot: CanonicalProductRegulatoryProfile
    regulatory_map_snapshot: RegulatoryMap
    applicable_obligations: List[str] = Field(default_factory=list)  # registry-linked obligation_ids
    # required evidence per obligation (derived) — to compute missing_evidence
    obligation_evidence_required: Dict[str, List[str]] = Field(default_factory=dict)
    # evidence the customer ALREADY has, per obligation (provided)
    evidence_refs: Dict[str, List[str]] = Field(default_factory=dict)
    created_at: Optional[str] = None


# ── simulated/provided change (INPUT — never ingested) ───────────────────
class RegulatoryChange(BaseModel):
    change_id: str
    source: str = "simulated"
    affected_regulations: List[str] = Field(default_factory=list)
    affected_obligations: List[str] = Field(default_factory=list)
    change_type: ChangeType
    effective_date: Optional[str] = None
    authority_level: AuthorityLevel = AuthorityLevel.LEGAL_TEXT
    summary: str = ""


# ── per-obligation delta ─────────────────────────────────────────────────
class ObligationDelta(BaseModel):
    obligation_id: str
    delta_type: DeltaType
    reason: str
    affected_evidence: List[str] = Field(default_factory=list)  # evidence already present for it
    missing_evidence: List[str] = Field(default_factory=list)  # required but not yet present
    confidence: Confidence


# ── management-level summary ──────────────────────────────────────────────
class ChangeImpactSummary(BaseModel):
    what_changed: str = ""
    what_matters_for_this_product: List[str] = Field(default_factory=list)  # need action
    already_covered: List[str] = Field(default_factory=list)
    needs_review: List[str] = Field(default_factory=list)
    not_relevant: List[str] = Field(default_factory=list)
    unsupported_domains: List[str] = Field(default_factory=list)


class ChangeAssessment(BaseModel):
    change_id: str
    affects_product: bool
    deltas: List[ObligationDelta] = Field(default_factory=list)
    summary: ChangeImpactSummary
