"""Core coverage policy models."""

from collections.abc import Callable
from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field

from ..enums import Role


class Validity(BaseModel):
    """Validity constraints for evidence"""

    within_tax_year: bool = False
    available_by: str | None = None
    date_tolerance_days: int = 30


class StatusClassifier(BaseModel):
    """Rules for classifying evidence status"""

    min_ocr: float = 0.82
    min_extract: float = 0.85
    date_in_year: bool = True
    date_in_year_or_tolerance: bool = True
    conflict_rules: list[str] = Field(default_factory=list)


class StatusClassifierConfig(BaseModel):
    """Complete status classifier configuration"""

    present_verified: StatusClassifier
    present_unverified: StatusClassifier
    conflicting: StatusClassifier
    missing: StatusClassifier = Field(default_factory=lambda: StatusClassifier())


class EvidenceItem(BaseModel):
    """Evidence requirement definition"""

    id: str
    role: Role
    condition: str | None = None
    boxes: list[str] = Field(default_factory=list)
    acceptable_alternatives: list[str] = Field(default_factory=list)
    validity: Validity = Field(default_factory=Validity)
    reasons: dict[str, str] = Field(default_factory=dict)


class CrossCheck(BaseModel):
    """Cross-validation rule"""

    name: str
    logic: str


class SchedulePolicy(BaseModel):
    """Policy for a specific tax schedule"""

    guidance_hint: str | None = None
    evidence: list[EvidenceItem] = Field(default_factory=list)
    cross_checks: list[CrossCheck] = Field(default_factory=list)
    selection_rule: dict[str, str] = Field(default_factory=dict)
    notes: dict[str, Any] = Field(default_factory=dict)


class Trigger(BaseModel):
    """Schedule trigger condition"""

    any_of: list[str] = Field(default_factory=list)
    all_of: list[str] = Field(default_factory=list)


class GuidanceRef(BaseModel):
    """Reference to guidance document"""

    doc_id: str
    kind: str


class QuestionTemplates(BaseModel):
    """Templates for generating clarifying questions"""

    default: dict[str, str] = Field(default_factory=dict)
    reasons: dict[str, str] = Field(default_factory=dict)


class ConflictRules(BaseModel):
    """Rules for handling conflicting evidence"""

    precedence: list[str] = Field(default_factory=list)
    escalation: dict[str, Any] = Field(default_factory=dict)


class TaxYearBoundary(BaseModel):
    """Tax year date boundaries"""

    start: str
    end: str


class Defaults(BaseModel):
    """Default configuration values"""

    confidence_thresholds: dict[str, float] = Field(default_factory=dict)
    date_tolerance_days: int = 30
    require_lineage_bbox: bool = True
    allow_bank_substantiation: bool = True


class Privacy(BaseModel):
    """Privacy and PII handling configuration"""

    vector_pii_free: bool = True
    redact_patterns: list[str] = Field(default_factory=list)


class CoveragePolicy(BaseModel):
    """Complete coverage policy definition"""

    version: str
    jurisdiction: str
    tax_year: str
    tax_year_boundary: TaxYearBoundary
    defaults: Defaults
    document_kinds: list[str] = Field(default_factory=list)
    guidance_refs: dict[str, GuidanceRef] = Field(default_factory=dict)
    triggers: dict[str, Trigger] = Field(default_factory=dict)
    schedules: dict[str, SchedulePolicy] = Field(default_factory=dict)
    status_classifier: StatusClassifierConfig
    conflict_resolution: ConflictRules
    question_templates: QuestionTemplates
    privacy: Privacy


class CompiledCoveragePolicy(BaseModel):
    """Coverage policy with compiled predicates"""

    policy: CoveragePolicy
    compiled_predicates: dict[str, Callable[[str, str], bool]] = Field(
        default_factory=dict
    )
    compiled_at: datetime
    hash: str
    source_files: list[str] = Field(default_factory=list)
