"""
AccessList Pydantic models for Nginx Proxy Manager.

This module defines the AccessList model and related sub-models for managing
IP-based access control and HTTP Basic Authentication in Nginx Proxy Manager.
"""

from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field


class AccessListItem(BaseModel):
    """
    Pydantic model for Access List Item (IP access rule).

    Represents a single IP-based access control rule with allow or deny directive.

    Attributes:
        directive: Access directive ('allow' or 'deny')
        address: IP address, CIDR notation, or 'all'

    Example:
        >>> item = AccessListItem(
        ...     directive="allow",
        ...     address="192.168.1.0/24",
        ... )
        >>> item.directive
        'allow'
    """

    directive: str = Field(..., pattern="^(allow|deny)$")
    address: str

    model_config = {
        "json_schema_extra": {
            "examples": [
                {"directive": "allow", "address": "192.168.1.0/24"},
                {"directive": "deny", "address": "all"},
                {"directive": "allow", "address": "2001:db8::/32"},
            ]
        }
    }


class AccessListClient(BaseModel):
    """
    Pydantic model for Access List Client (HTTP Basic Auth user).

    Represents an HTTP Basic Authentication user for the access list.

    Attributes:
        username: Username for HTTP Basic Auth
        password: Password for HTTP Basic Auth

    Example:
        >>> client = AccessListClient(
        ...     username="admin",
        ...     password="secure_password",
        ... )
        >>> client.username
        'admin'
    """

    username: str
    password: str

    model_config = {
        "json_schema_extra": {
            "examples": [
                {"username": "admin", "password": "secure_password123"},
            ]
        }
    }


class AccessList(BaseModel):
    """
    Pydantic model for Nginx Proxy Manager Access List.

    An access list defines IP-based access control rules and optional HTTP Basic
    Authentication for protecting proxy hosts.

    Attributes:
        id: Unique identifier (auto-generated by NPM)
        created_on: Timestamp when the access list was created
        modified_on: Timestamp when the access list was last modified
        name: Human-readable name for the access list
        satisfy_any: Whether to satisfy any rule (OR logic) or all rules (AND logic)
        pass_auth: Whether to pass authentication to the backend
        items: List of IP access control rules (allow/deny)
        clients: List of HTTP Basic Auth users (optional)
        meta: Additional metadata as key-value pairs

    Example:
        >>> # IP-based access list
        >>> access_list = AccessList(
        ...     name="Office Network",
        ...     items=[
        ...         {"directive": "allow", "address": "192.168.1.0/24"},
        ...         {"directive": "deny", "address": "all"},
        ...     ],
        ... )
        >>> len(access_list.items)
        2

        >>> # Access list with HTTP Basic Auth
        >>> access_list = AccessList(
        ...     name="Protected Area",
        ...     satisfy_any=False,  # Require both IP AND password
        ...     items=[{"directive": "allow", "address": "192.168.1.0/24"}],
        ...     clients=[{"username": "admin", "password": "secure_pass"}],
        ... )
        >>> access_list.satisfy_any
        False
    """

    # Identifiers
    id: int | None = None
    created_on: datetime | None = None
    modified_on: datetime | None = None

    # Access list details
    name: str

    # Logic configuration
    satisfy_any: bool = False  # False = satisfy all (AND), True = satisfy any (OR)
    pass_auth: bool = False  # Whether to pass auth to backend

    # Access control rules
    items: list[AccessListItem] = Field(default_factory=list)
    clients: list[AccessListClient] = Field(default_factory=list)

    # Metadata
    meta: dict[str, Any] = Field(default_factory=dict)

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "name": "Office Network Access",
                    "satisfy_any": False,
                    "items": [
                        {"directive": "allow", "address": "192.168.1.0/24"},
                        {"directive": "deny", "address": "all"},
                    ],
                },
                {
                    "name": "Protected with Password",
                    "satisfy_any": False,
                    "items": [{"directive": "allow", "address": "all"}],
                    "clients": [
                        {"username": "admin", "password": "secure_password"},
                    ],
                },
            ]
        }
    }
