"""Configuration for claim-validator library."""

from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

# Default PA rule-based validators
DEFAULT_PA_RULE_VALIDATORS: list[str] = [
    "claim_validator.prior_auth.validators.rule_based.cross_field.PACrossFieldValidator",
    "claim_validator.prior_auth.validators.rule_based.date_of_birth.PADateOfBirthValidator",
    "claim_validator.prior_auth.validators.rule_based.diagnosis.PADiagnosisValidator",
    "claim_validator.prior_auth.validators.rule_based.member_id.PAMemberIDValidator",
    "claim_validator.prior_auth.validators.rule_based.npi.PANPIValidator",
    "claim_validator.prior_auth.validators.rule_based.procedure.PAProcedureValidator",
    "claim_validator.prior_auth.validators.rule_based.service_date.PAServiceDateValidator",
]

# Default 8 rule-based validators (dotted paths)
DEFAULT_RULE_VALIDATORS: list[str] = [
    "claim_validator.validators.rule_based.completeness.CompletenessValidator",
    "claim_validator.validators.rule_based.npi.NPIValidator",
    "claim_validator.validators.rule_based.subscriber_id.SubscriberIDValidator",
    "claim_validator.validators.rule_based.demographics.DemographicsValidator",
    "claim_validator.validators.rule_based.coding.CodingValidator",
    "claim_validator.validators.rule_based.monetary.MonetaryValidator",
    "claim_validator.validators.rule_based.duplicate.DuplicateValidator",
    "claim_validator.validators.rule_based.timely_filing.TimelyFilingValidator",
    "claim_validator.validators.rule_based.place_of_service.PlaceOfServiceValidator",
    "claim_validator.validators.rule_based.taxonomy.TaxonomyValidator",
    "claim_validator.validators.rule_based.modifier_compatibility.ModifierCompatibilityValidator",
]


# Default eligibility AI validators
DEFAULT_ELIG_AI_VALIDATORS: list[str] = [
    "claim_validator.eligibility.validators.ai.interpreter.EligibilityInterpreterAI",
]

# Default PA AI validators
DEFAULT_PA_AI_VALIDATORS: list[str] = [
    "claim_validator.prior_auth.validators.ai.interpreter.PriorAuthInterpreterAI",
]


# Default eligibility rule-based validators
DEFAULT_ELIG_RULE_VALIDATORS: list[str] = [
    "claim_validator.eligibility.validators.rule_based.date.EligibilityDateValidator",
    "claim_validator.eligibility.validators.rule_based.demographics.EligibilityDemographicsValidator",
    "claim_validator.eligibility.validators.rule_based.member_id.MemberIDValidator",
    "claim_validator.eligibility.validators.rule_based.npi.EligibilityNPIValidator",
    "claim_validator.eligibility.validators.rule_based.payer_id.PayerIDValidator",
    "claim_validator.eligibility.validators.rule_based.service_type.ServiceTypeValidator",
]


class ProviderConfig(BaseModel):
    """Typed LLM provider configuration."""
    provider: Literal["groq", "openai", "openai_compatible", "anthropic"]
    api_key: str
    model: str
    base_url: str | None = None
    temperature: float = Field(default=0.0, ge=0.0, le=2.0)
    max_tokens: int = Field(default=4096, gt=0)
    timeout: int = Field(default=30, gt=0)

    @model_validator(mode="after")
    def validate_base_url_for_compatible(self) -> "ProviderConfig":
        if self.provider == "openai_compatible" and not self.base_url:
            raise ValueError("base_url is required for openai_compatible provider")
        return self


class MemorySettings(BaseModel):
    """Tiered memory configuration."""
    enabled: bool = True
    redis_url: str | None = None
    postgres_url: str | None = None
    cross_claim_ttl_days: int = Field(default=7, ge=1, le=90)
    multi_turn_retention_days: int = Field(default=90, ge=1, le=365)
    within_claim_cleanup: bool = True


class ClaimValidatorSettings(BaseSettings):
    """Configuration for the claim-validator library.

    Reads from environment variables with ``CLAIM_VALIDATOR_`` prefix.
    All fields have sensible defaults for zero-config rule-based validation.
    """

    model_config = SettingsConfigDict(
        env_prefix="CLAIM_VALIDATOR_",
        frozen=True,
        env_nested_delimiter="__",
    )

    rule_validators: list[str] = DEFAULT_RULE_VALIDATORS
    ai_validators: list[str] = []
    skip_ai_on_rule_failure: bool = True
    ai_config: dict[str, Any] | None = None

    # Prior authorization settings (rule-based only by default — PA is a
    # deterministic lookup, not an interpretation problem)
    pa_rule_validators: list[str] = DEFAULT_PA_RULE_VALIDATORS
    pa_ai_validators: list[str] = []
    pa_skip_ai: bool = True
    pa_skip_ai_on_rule_failure: bool = True

    # Eligibility settings
    eligibility_rule_validators: list[str] = DEFAULT_ELIG_RULE_VALIDATORS
    eligibility_ai_validators: list[str] = DEFAULT_ELIG_AI_VALIDATORS
    eligibility_skip_ai: bool = False
    eligibility_skip_ai_on_rule_failure: bool = True

    # Clearinghouse settings (single provider — existing, backward compat)
    clearinghouse_config: dict[str, Any] | None = None

    # Multi-clearinghouse routing (opt-in)
    # Format: {"stedi": {"api_key": "..."}, "claimmd": {"account_key": "..."}}
    clearinghouse_configs: dict[str, dict[str, Any]] | None = None

    # Payer routing overrides — custom payer-to-clearinghouse mappings
    # Format: {"PAYER_ID": [{"clearinghouse": "...", "payer_id_at_clearinghouse": "...",
    #           "priority": 1, "supports": ["837P"]}]}
    payer_routing_overrides: dict[str, list[dict[str, Any]]] | None = None

    # Institutional (837I) claim validators
    institutional_rule_validators: list[str] = [
        "claim_validator.validators.institutional.bill_type.BillTypeValidator",
        "claim_validator.validators.institutional.revenue_code.RevenueCodeValidator",
        "claim_validator.validators.institutional.admission.AdmissionValidator",
        "claim_validator.validators.institutional.completeness.InstitutionalCompletenessValidator",
        "claim_validator.validators.institutional.condition_code.ConditionCodeValidator",
        "claim_validator.validators.institutional.value_code.ValueCodeValidator",
    ]
    institutional_ai_validators: list[str] = []

    # Per-stage AI provider overrides for process_claim_full().
    # Each is a dict with keys: provider, api_key, model (+ provider extras).
    # When set, overrides the global ai_config for that specific stage.
    # Example: use Groq for fast summaries, Claude for clinical reasoning.
    ai_claim_analysis_config: dict[str, Any] | None = None
    ai_rejection_summary_config: dict[str, Any] | None = None
    ai_pre_submission_config: dict[str, Any] | None = None

    # --- New typed provider config (Phase 1 — alongside existing ai_config) ---
    default_provider: ProviderConfig | None = None
    code_validation_provider: ProviderConfig | None = None
    prior_auth_provider: ProviderConfig | None = None
    coverage_check_provider: ProviderConfig | None = None
    eligibility_interpreter_provider: ProviderConfig | None = None
    pa_interpreter_provider: ProviderConfig | None = None
    rejection_summary_provider: ProviderConfig | None = None
    pre_submission_provider: ProviderConfig | None = None
    memory: MemorySettings = MemorySettings()

    def get_provider_config(self, stage: str) -> ProviderConfig | dict[str, Any] | None:
        """Per-stage config with fallback: typed per-stage -> typed default -> legacy per-stage -> legacy global."""
        stage_config = getattr(self, f"{stage}_provider", None)
        if stage_config is not None:
            return stage_config
        if self.default_provider is not None:
            return self.default_provider
        legacy_attr = f"ai_{stage}_config"
        legacy_config = getattr(self, legacy_attr, None)
        if legacy_config is not None:
            return legacy_config
        return self.ai_config
