import re
import secrets
from typing import Optional

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Application settings from environment variables."""
    
    model_config = SettingsConfigDict(env_file=".env", extra="ignore")
    
    jwt_secret_key: str = Field(
        default_factory=lambda: secrets.token_urlsafe(32),
        validation_alias="JWT_SECRET_KEY",
    )
    password_salt: str = Field(
        default="default-salt",
        validation_alias="PASSWORD_SALT"
    )
    master_password_hash: Optional[str] = Field(
        default=None,
        validation_alias="MASTER_PASSWORD_HASH"
    )
    # ⚠️ WARNING: DEVELOPMENT ONLY - NEVER USE IN PRODUCTION ⚠️
    # This field allows setting a plaintext master password via environment
    # variable for development/testing purposes only. In production
    # deployments, use MASTER_PASSWORD_HASH instead and NEVER set this field.
    master_password: Optional[str] = Field(
        default=None,
        validation_alias="MASTER_PASSWORD",
        description=(
            "**DEVELOPMENT ONLY** - Plaintext master password. "
            "NEVER enable in production. Use MASTER_PASSWORD_HASH instead."
        ),
    )
    token_expiry_hours: int = Field(
        default=24,
        validation_alias="SESSION_TIMEOUT_HOURS"
    )
    anime_directory: str = Field(
        default="",
        validation_alias="ANIME_DIRECTORY"
    )
    log_level: str = Field(
        default="INFO",
        validation_alias="LOG_LEVEL"
    )

    # Additional settings from .env
    database_url: str = Field(
        default="sqlite:///./data/aniworld.db",
        validation_alias="DATABASE_URL"
    )
    cors_origins: str = Field(
        default="http://localhost:3000",
        validation_alias="CORS_ORIGINS",
    )
    api_rate_limit: int = Field(
        default=100,
        validation_alias="API_RATE_LIMIT"
    )
    default_provider: str = Field(
        default="aniworld.to",
        validation_alias="DEFAULT_PROVIDER"
    )
    provider_timeout: int = Field(
        default=30,
        validation_alias="PROVIDER_TIMEOUT"
    )
    retry_attempts: int = Field(
        default=3,
        validation_alias="RETRY_ATTEMPTS"
    )
    
    # NFO / TMDB Settings
    tmdb_api_key: Optional[str] = Field(
        default=None,
        validation_alias="TMDB_API_KEY",
        description="TMDB API key for scraping TV show metadata"
    )
    nfo_auto_create: bool = Field(
        default=False,
        validation_alias="NFO_AUTO_CREATE",
        description="Automatically create NFO files when scanning series"
    )
    nfo_update_on_scan: bool = Field(
        default=False,
        validation_alias="NFO_UPDATE_ON_SCAN",
        description="Update existing NFO files when scanning series"
    )
    nfo_download_poster: bool = Field(
        default=True,
        validation_alias="NFO_DOWNLOAD_POSTER",
        description="Download poster.jpg when creating NFO"
    )
    nfo_download_logo: bool = Field(
        default=True,
        validation_alias="NFO_DOWNLOAD_LOGO",
        description="Download logo.png when creating NFO"
    )
    nfo_download_fanart: bool = Field(
        default=True,
        validation_alias="NFO_DOWNLOAD_FANART",
        description="Download fanart.jpg when creating NFO"
    )
    nfo_image_size: str = Field(
        default="original",
        validation_alias="NFO_IMAGE_SIZE",
        description="Image size to download (original, w500, etc.)"
    )
    nfo_prefer_fsk_rating: bool = Field(
        default=True,
        validation_alias="NFO_PREFER_FSK_RATING",
        description="Prefer German FSK rating over MPAA rating in NFO files"
    )
    nfo_folder_ignore_patterns: str = Field(
        default="The Last of Us|Loki|Chernobyl|Star Trek Discovery|Marvel|Matrix|Fast & Furious|Jurassic|James Bond|Mission: Impossible|Bourne|Hunger Games|Die Hard|John Wick|Pacific Rim|Guardians of the Galaxy|Avengers|Batman|Superman|Wonder Woman|Spider-Man|X-Men|Fantastic Four|Terminator|Predator|Rambo|Rocky|Expendables|Tomb Raider|Jumanji|Jurassic Park|Pirates of the Caribbean|Harry Potter|Lord of the Rings|Hobbit|Game of Thrones|Westworld|Stranger Things|Breaking Bad|Better Call Saul|Sherlock|Downton Abbey|The Crown|Bridgerton|Sex Education|Normal People|Emily in Paris|The Witcher|Servant|Lucifer|Dark|Shadow and Bone|Grimm|Fairytale",
        validation_alias="NFO_FOLDER_IGNORE_PATTERNS",
        description="Regex patterns for folder names to skip during scan (pipe-separated)"
    )

    @property
    def folder_ignore_patterns(self) -> list[str]:
        """Parse ignore patterns from comma-separated string into list.

        Returns:
            List of regex patterns to skip during folder scanning.
        """
        if not self.nfo_folder_ignore_patterns:
            return []
        return [
            pattern.strip()
            for pattern in self.nfo_folder_ignore_patterns.split("|")
            if pattern.strip()
        ]

    def should_ignore_folder(self, folder_name: str) -> bool:
        """Check if folder should be ignored based on ignore patterns.

        Args:
            folder_name: Name of folder to check.

        Returns:
            True if folder matches any ignore pattern, False otherwise.
        """
        for pattern in self.folder_ignore_patterns:
            if re.search(pattern, folder_name, re.IGNORECASE):
                return True
        return False

    @property
    def allowed_origins(self) -> list[str]:
        """Return the list of allowed CORS origins.

        The environment variable should contain a comma-separated list.
        When ``*`` is provided we fall back to a safe local development
        default instead of allowing every origin in production.
        """

        raw = (self.cors_origins or "").strip()
        if not raw:
            return []
        if raw == "*":
            return [
                "http://localhost:3000",
                "http://localhost:8000",
            ]
        return [origin.strip() for origin in raw.split(",") if origin.strip()]

    @property
    def scan_key_overrides(self) -> dict[str, str]:
        """Return scan key overrides from config.json.
        
        Maps folder names to provider keys for cases where auto-generated
        keys from folder names are incorrect.
        
        Returns:
            Dict mapping folder names to provider keys.
        """
        from src.server.services.config_service import ConfigService
        try:
            config_service = ConfigService()
            config = config_service.load_config()
            return config.scan_key_overrides or {}
        except Exception:
            return {}


settings = Settings()
