from __future__ import annotations

from functools import lru_cache
from typing import Literal

from pydantic import SecretStr, 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",
    )

    # ── Telegram ─────────────────────────────────────────────
    telegram_bot_token: SecretStr
    telegram_webhook_secret: SecretStr
    telegram_webhook_url: str

    # ── Database ──────────────────────────────────────────────
    database_url: SecretStr           # asyncpg
    database_url_sync: SecretStr      # psycopg2 (alembic / sync workers)

    # ── Redis ─────────────────────────────────────────────────
    redis_url: SecretStr

    # ── Object Storage ────────────────────────────────────────
    s3_endpoint_url: str
    s3_access_key_id: SecretStr
    s3_secret_access_key: SecretStr
    s3_bucket_name: str
    s3_region: str = "us-east-1"

    # ── AI APIs ───────────────────────────────────────────────
    anthropic_api_key: SecretStr
    openai_api_key: SecretStr
    embedding_model: str = "text-embedding-3-small"
    embedding_dimensions: int = 1536
    llm_model: str = "claude-sonnet-4-6"

    # ── Application ───────────────────────────────────────────
    app_env: Literal["development", "staging", "production"] = "development"
    app_secret_key: SecretStr
    log_level: str = "INFO"
    log_format: Literal["console", "json"] = "console"

    # ── Limits ────────────────────────────────────────────────
    max_download_bytes: int = 524_288_000        # 500 MB
    max_tokens_per_analysis: int = 4_000
    max_items_per_user: int = 10_000
    max_storage_bytes_per_user: int = 10_737_418_240  # 10 GB
    max_concurrent_jobs_per_user: int = 5

    # ── Workers ───────────────────────────────────────────────
    download_worker_concurrency: int = 4
    ai_worker_concurrency: int = 2
    embed_worker_concurrency: int = 4
    notif_worker_concurrency: int = 4
    job_claim_timeout_ms: int = 300_000   # 5 min for XAUTOCLAIM
    job_max_attempts: int = 3

    @field_validator("log_level")
    @classmethod
    def upper_log_level(cls, v: str) -> str:
        return v.upper()

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


@lru_cache(maxsize=1)
def get_settings() -> Settings:
    return Settings()  # type: ignore[call-arg]
