"""Application configuration loaded from environment variables and .env file.

Follows pydantic-settings patterns: all values are prefixed with BANGUI_
and validated at startup via the Settings singleton.
"""

from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """BanGUI runtime configuration.

    All fields are loaded from environment variables prefixed with ``BANGUI_``
    or from a ``.env`` file located next to the process working directory.
    The application will raise a :class:`pydantic.ValidationError` on startup
    if any required field is missing or has an invalid value.
    """

    database_path: str = Field(
        default="bangui.db",
        description="Filesystem path to the BanGUI SQLite application database.",
    )
    fail2ban_socket: str = Field(
        default="/var/run/fail2ban/fail2ban.sock",
        description="Path to the fail2ban Unix domain socket.",
    )
    session_secret: str = Field(
        ...,
        description=(
            "Secret key used when generating session tokens. "
            "Must be unique and never committed to source control."
        ),
    )
    session_duration_minutes: int = Field(
        default=60,
        ge=1,
        description="Number of minutes a session token remains valid after creation.",
    )
    timezone: str = Field(
        default="UTC",
        description="IANA timezone name used when displaying timestamps in the UI.",
    )
    log_level: str = Field(
        default="info",
        description="Application log level: debug | info | warning | error | critical.",
    )
    geoip_db_path: str | None = Field(
        default=None,
        description=(
            "Optional path to a MaxMind GeoLite2-Country .mmdb file. "
            "When set, failed ip-api.com lookups fall back to local resolution."
        ),
    )
    fail2ban_config_dir: str = Field(
        default="/config/fail2ban",
        description=(
            "Path to the fail2ban configuration directory. "
            "Must contain subdirectories jail.d/, filter.d/, and action.d/. "
            "Used for listing, viewing, and editing configuration files through the web UI."
        ),
    )
    fail2ban_start_command: str = Field(
        default="fail2ban-client start",
        description=(
            "Shell command used to start (not reload) the fail2ban daemon during "
            "recovery rollback.  Split by whitespace to build the argument list — "
            "no shell interpretation is performed.  "
            "Example: 'systemctl start fail2ban' or 'fail2ban-client start'."
        ),
    )

    model_config = SettingsConfigDict(
        env_prefix="BANGUI_",
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
    )


def get_settings() -> Settings:
    """Return a fresh :class:`Settings` instance loaded from the environment.

    Returns:
        A validated :class:`Settings` object. Raises :class:`pydantic.ValidationError`
        if required keys are absent or values fail validation.
    """
    return Settings()  # type: ignore[call-arg]  # pydantic-settings populates required fields from env vars
