from typing import Literal

from pydantic import BaseModel, model_validator

_ALLOWED_ALGORITHMS = (
    "HS256",
    "HS384",
    "HS512",
    "RS256",
    "RS384",
    "RS512",
    "ES256",
    "ES384",
    "ES512",
)


class AuthSettings(BaseModel):
    secret_key: str  # No default. Must be explicitly set.
    algorithm: Literal[
        "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "ES256", "ES384", "ES512"
    ] = "HS256"
    access_token_expire_minutes: int = 30
    refresh_token_expire_days: int = 7
    token_audience: str = "bluefox"
    auth_prefix: str = "/auth"

    # Cookie configuration
    cookie_name_access: str = "bf_access_token"
    cookie_name_refresh: str = "bf_refresh_token"
    cookie_name_csrf: str = "bf_csrf_token"
    cookie_secure: bool = True
    cookie_samesite: Literal["lax", "strict", "none"] = "lax"
    cookie_domain: str | None = None
    cookie_path: str = "/"

    # Password policy
    password_min_length: int = 8
    password_max_bytes: int = 72  # bcrypt's actual limit

    @model_validator(mode="after")
    def _validate_secret_key(self):
        blocked = {"change-me-in-production", "secret", "changeme", ""}
        if self.secret_key in blocked:
            raise ValueError(
                "secret_key must be explicitly set to a strong, unique value. "
                'Generate one with: python -c "import secrets; print(secrets.token_urlsafe(64))"'
            )
        if len(self.secret_key) < 32:
            raise ValueError("secret_key must be at least 32 characters.")
        return self
