"""
Central configuration for the AI Crop Decision Support System.

All settings are loaded from environment variables (.env file in development,
real environment variables in production on the VPS). Nothing is hardcoded
here — this file only defines defaults and types, never secrets.

Why this matters for production:
- A missing or malformed env var fails LOUDLY at startup (via Pydantic
  validation), not silently three hours later when a request hits it.
- Secrets (API keys, DB passwords) never live in source control.
"""

from functools import lru_cache
from typing import List

from pydantic import field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
    )

    # ── App identity ──────────────────────────────────────────
    APP_NAME: str = "AI Crop Decision Support System"
    APP_VERSION: str = "1.0.0"
    ENVIRONMENT: str = "development"  # development | staging | production
    DEBUG: bool = False

    # ── API ───────────────────────────────────────────────────
    API_V1_PREFIX: str = "/api/v1"
    HOST: str = "0.0.0.0"
    PORT: int = 8000

    # CORS — comma separated origins, parsed into a list
    CORS_ORIGINS: str = "http://localhost:3000,http://127.0.0.1:3000,http://0.0.0.0:3000"

    @property
    def cors_origins_list(self) -> List[str]:
        return [o.strip() for o in self.CORS_ORIGINS.split(",") if o.strip()]

    # ── Security ──────────────────────────────────────────────
    API_KEY_HEADER: str = "X-API-Key"
    VALID_API_KEYS: str = ""  # comma separated, set via env in production

    @property
    def valid_api_keys_list(self) -> List[str]:
        return [k.strip() for k in self.VALID_API_KEYS.split(",") if k.strip()]

    SECRET_KEY: str = "CHANGE_ME_IN_PRODUCTION"
    RATE_LIMIT_PER_MINUTE: int = 30

    # ── Database (PostgreSQL) ────────────────────────────────
    DATABASE_URL: str = "postgresql+asyncpg://crop_user:crop_pass@localhost:5432/crop_db"
    DB_POOL_SIZE: int = 10
    DB_MAX_OVERFLOW: int = 20
    DB_ECHO: bool = False

    # ── Redis (cache + Celery broker) ────────────────────────
    REDIS_URL: str = "redis://localhost:6379/0"
    REDIS_CACHE_TTL_SECONDS: int = 86400  # 24 hours

    # ── Celery ────────────────────────────────────────────────
    CELERY_BROKER_URL: str = "redis://localhost:6379/1"
    CELERY_RESULT_BACKEND: str = "redis://localhost:6379/2"
    CELERY_TASK_TIME_LIMIT: int = 60  # hard kill after 60s
    CELERY_TASK_SOFT_TIME_LIMIT: int = 45  # warn at 45s

    # ── ML models ─────────────────────────────────────────────
    MODEL_DIR: str = "data/models/v1"
    MODEL_VERSION: str = "v1"

    # ── LLM (Anthropic) ───────────────────────────────────────
    ANTHROPIC_API_KEY: str = ""
    LLM_MODEL: str = "claude-sonnet-4-6"
    LLM_MAX_TOKENS: int = 1000
    LLM_TIMEOUT_SECONDS: int = 30
    LLM_MAX_RETRIES: int = 2

    # ── Email (notifications, module 1.1.11) ─────────────────
    SMTP_HOST: str = ""
    SMTP_PORT: int = 587
    SMTP_USERNAME: str = ""
    SMTP_PASSWORD: str = ""
    SMTP_USE_TLS: bool = True
    EMAIL_FROM_ADDRESS: str = "noreply@agrifield.example"
    EMAIL_FROM_NAME: str = "AgriField"
    EMAIL_ENABLED: bool = False  # explicit opt-in — stays off until SMTP is configured

    # ── Logging ───────────────────────────────────────────────
    LOG_LEVEL: str = "INFO"
    LOG_DIR: str = "logs"
    LOG_JSON: bool = True  # structured JSON logs in production

    # ── Sentry (error tracking) ──────────────────────────────
    SENTRY_DSN: str = ""

    # ── Monitoring ────────────────────────────────────────────
    ENABLE_METRICS: bool = True
    METRICS_PORT: int = 9090

    @field_validator("ENVIRONMENT")
    @classmethod
    def validate_environment(cls, v: str) -> str:
        allowed = {"development", "staging", "production"}
        if v not in allowed:
            raise ValueError(f"ENVIRONMENT must be one of {allowed}, got '{v}'")
        return v

    @field_validator("ANTHROPIC_API_KEY")
    @classmethod
    def validate_anthropic_key(cls, v: str) -> str:
        # Don't crash dev/test environments without a key, but warn loudly.
        # Production startup separately enforces this — see main.py lifespan.
        return v

    @property
    def is_production(self) -> bool:
        return self.ENVIRONMENT == "production"


@lru_cache
def get_settings() -> Settings:
    """Cached settings instance — env is read once per process, not per request."""
    return Settings()
