from functools import lru_cache
from pathlib import Path

from pydantic import ValidationInfo, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

BASE_DIR = Path(__file__).resolve().parents[3]


class Settings(BaseSettings):
    """Application configuration loaded from environment variables."""

    model_config = SettingsConfigDict(
        env_file=str(BASE_DIR / ".env"),
        env_file_encoding="utf-8",
        extra="ignore",
    )

    app_name: str = "Telegram Commerce Platform"
    app_env: str = "development"
    debug: bool = False
    api_prefix: str = "/api/v1"

    database_url: str
    db_pool_size: int = 5
    db_max_overflow: int = 5

    jwt_secret: str
    jwt_algorithm: str = "HS256"
    access_token_minutes: int = 120
    refresh_token_days: int = 14

    bot_token: str = ""
    bot_api_token: str = "change-me"
    bot_username: str = ""
    telegram_webhook_secret: str = ""

    admin_username: str = "admin"
    admin_password: str = "admin"

    tron_api_url: str = "https://api.trongrid.io"
    tron_api_key: str = ""

    fragment_api_url: str = ""
    fragment_api_key: str = ""

    ton_api_url: str = ""
    ton_api_key: str = ""

    upload_path: str = str(BASE_DIR / "uploads")
    upload_url_prefix: str = "/uploads"
    max_upload_mb: int = 10

    log_path: str = str(BASE_DIR / "logs")
    log_level: str = "INFO"

    cors_origins: str = "*"

    @field_validator("upload_path", "log_path", mode="before")
    @classmethod
    def _fallback_paths(cls, value: str, info: ValidationInfo) -> str:
        """An empty value in .env must not become the current directory."""
        if value:
            return value
        return str(BASE_DIR / ("uploads" if info.field_name == "upload_path" else "logs"))

    @property
    def cors_origin_list(self) -> list[str]:
        return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()]

    @property
    def upload_dir(self) -> Path:
        return Path(self.upload_path)

    @property
    def log_dir(self) -> Path:
        return Path(self.log_path)


@lru_cache
def get_settings() -> Settings:
    return Settings()


settings = get_settings()
