"""Setup wizard Pydantic models.

Request, response, and domain models for the first-run configuration wizard.
"""

from pydantic import Field, field_validator

from app.models.response import BanGuiBaseModel

# Top-50 most-common plaintext passwords (lower-case).
# Source: aggregated public breach compilations (Have I Been Pwned, Wikipedia).
# Covers passwords that pass structural checks (uppercase + digit + special char)
# but are trivial to guess.
_COMMON_PASSWORDS: frozenset[str] = frozenset(
    {
        "password",
        "password1",
        "password123",
        "password1234",
        "password!",
        "letmein",
        "welcome",
        "admin",
        "admin123",
        "administrator",
        "qwerty",
        "qwerty123",
        "qwerty1234",
        "abc123",
        "abcdef",
        "123456",
        "1234567",
        "12345678",
        "123456789",
        "1234567890",
        "iloveyou",
        "iloveyou1",
        "monkey",
        "dragon",
        "master",
        "login",
        "login123",
        "passw0rd",
        "passw0rd!",
        "changeme",
        "default",
        "guest",
        "guest123",
        "fuckyou",
        "fuckyou1",
        "shit",
        "asshole",
        "hello",
        "hello123",
        "hello!",
        "world",
        "pass",
        "test",
        "test123",
        "test!",
        "root",
        "root123",
        "p@ssword",
        "p@ssword1",
        "p@ssw0rd",
        "p@ssw0rd!",
        "sunshine",
        "princess",
        "shadow",
        "shadow123",
        "access",
        "access123",
        "mypass",
        "mypass123",
    }
)


class SetupRequest(BanGuiBaseModel):
    """Payload for ``POST /api/setup``."""

    master_password: str = Field(
        ...,
        min_length=8,
        max_length=72,
        description="Master password that protects the BanGUI interface (max 72 bytes due to bcrypt truncation).",
    )

    @field_validator("master_password")
    @classmethod
    def validate_master_password(cls, value: str) -> str:
        if len(value) < 8:
            raise ValueError("Password must be at least 8 characters long.")
        if len(value) > 72:
            raise ValueError("Password must not exceed 72 bytes (bcrypt limitation).")
        if not any(char.isupper() for char in value):
            raise ValueError("Password must include at least one uppercase letter.")
        if not any(char.isdigit() for char in value):
            raise ValueError("Password must include at least one number.")
        if not any(char in "!@#$%^&*()" for char in value):
            raise ValueError("Password must include at least one special character (!@#$%^&*()).")
        if value.lower() in _COMMON_PASSWORDS:
            raise ValueError("Password is too common. Choose something more unique.")
        return 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.",
    )
    timezone: str = Field(
        default="UTC",
        description="IANA timezone name used when displaying timestamps.",
    )
    session_duration_minutes: int = Field(
        default=60,
        ge=1,
        description="Number of minutes a user session remains valid.",
    )


class SetupResponse(BanGuiBaseModel):
    """Response returned after a successful initial setup."""

    message: str = Field(
        default="Setup completed successfully. Please log in.",
    )


class SetupTimezoneResponse(BanGuiBaseModel):
    """Response for ``GET /api/setup/timezone``."""

    timezone: str = Field(..., description="Configured IANA timezone identifier.")


class SetupStatusResponse(BanGuiBaseModel):
    """Response indicating whether setup has been completed."""

    completed: bool = Field(
        ...,
        description="``True`` if the initial setup has already been performed.",
    )
