"""
Enhanced Engine Configuration v2.0
===================================
Configuration dataclass for the fuzzy matching engine with safe defaults
that preserve current behavior while enabling new optimizations.
"""

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


@dataclass
class EngineConfig:
    """
    Enhanced configuration for the fuzzy matching engine.
    All defaults preserve backward compatibility.
    """

    # Scoring
    score_aggregator: Literal["weighted_mean", "weighted_present_mean"] = (
        "weighted_mean"
    )
    score_margin_cutoff: Optional[int] = None  # e.g., threshold - 5 (points)

    # Blocking & fallback
    apply_blocking: bool = True
    min_blocking_coverage: float = 0.10
    strict_blocking_failures: bool = True  # CRITICAL: Default True for backward compat
    auto_soft_widen: bool = True
    soft_widen_trigger_pct: float = 0.30
    soft_widen_trigger_min: int = 100
    soft_widen_min_no_match_blocks: int = 10
    soft_widen_max_blocks: int = 5_000
    fallback_unblocked_topk: int = 50
    candidate_pair_budget: int = 5_000_000
    fallback_budget_per_source: int = 200
    blocking_domain_use_base: bool = False  # eTLD+1 gate

    # Cleansing
    domain_cleanse_mode: Literal["legacy", "strict"] = "legacy"
    domain_fields_allowlist: List[str] = field(
        default_factory=lambda: [
            "Website",
            "Email",
            "Domain",
            "Domain__c",
            "CleanDomain__c",
        ]
    )

    # Logging / telemetry
    unicode_safe_logging: bool = True
    stats_level: Literal["basic", "verbose"] = "verbose"
    random_seed: int = 42

    # Shadow mode
    shadow_mode_enabled: bool = False
    shadow_mode_sample_pct: float = 0.05  # 5% default

    def validate(self) -> None:
        """Validate configuration - raises AssertionError if invalid"""
        assert (
            0 <= self.min_blocking_coverage <= 1
        ), f"min_blocking_coverage must be [0,1], got {self.min_blocking_coverage}"
        assert (
            0 <= self.soft_widen_trigger_pct <= 1
        ), f"soft_widen_trigger_pct must be [0,1], got {self.soft_widen_trigger_pct}"
        assert (
            0 <= self.shadow_mode_sample_pct <= 1
        ), f"shadow_mode_sample_pct must be [0,1], got {self.shadow_mode_sample_pct}"
