"""
Redirection Pydantic model for Nginx Proxy Manager.

This module defines the Redirection model representing URL redirection
configurations in Nginx Proxy Manager.
"""

from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field, field_validator


class Redirection(BaseModel):
    """
    Pydantic model for Nginx Proxy Manager Redirection Host.

    A redirection host redirects traffic from one or more source domains to
    a target domain with a specified HTTP status code.

    Attributes:
        id: Unique identifier (auto-generated by NPM)
        created_on: Timestamp when the redirection was created
        modified_on: Timestamp when the redirection was last modified
        domain_names: List of source domain names to redirect from
        forward_scheme: Target protocol ('http', 'https', or '$scheme' to preserve)
        forward_domain_name: Target domain to redirect to
        forward_http_code: HTTP redirect status code (301, 302, 307, 308)
        preserve_path: Whether to preserve the URL path in the redirect
        certificate_id: ID of SSL certificate (if SSL is used)
        ssl_forced: Whether to force SSL (redirect HTTP to HTTPS)
        hsts_enabled: Whether to enable HTTP Strict Transport Security
        hsts_subdomains: Whether to include subdomains in HSTS
        http2_support: Whether to enable HTTP/2 support
        block_exploits: Whether to block common exploits
        advanced_config: Custom Nginx configuration
        enabled: Whether this redirection is enabled
        meta: Additional metadata as key-value pairs

    Example:
        >>> # Permanent redirect (301) from old to new domain
        >>> redirect = Redirection(
        ...     domain_names=["oldsite.com", "www.oldsite.com"],
        ...     forward_scheme="https",
        ...     forward_domain_name="newsite.com",
        ...     forward_http_code=301,
        ...     preserve_path=True,
        ... )
        >>> redirect.forward_http_code
        301

        >>> # Temporary redirect (302) for maintenance
        >>> redirect = Redirection(
        ...     domain_names=["app.example.com"],
        ...     forward_scheme="https",
        ...     forward_domain_name="maintenance.example.com",
        ...     forward_http_code=302,
        ...     preserve_path=False,
        ... )
        >>> redirect.forward_http_code
        302

        >>> # WWW to non-WWW redirect preserving scheme
        >>> redirect = Redirection(
        ...     domain_names=["www.example.com"],
        ...     forward_scheme="$scheme",
        ...     forward_domain_name="example.com",
        ...     forward_http_code=301,
        ... )
        >>> redirect.forward_scheme
        '$scheme'
    """

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

    # Source domain configuration
    domain_names: list[str] = Field(..., min_length=1)

    # Target configuration
    forward_scheme: str = Field(..., pattern="^(http|https|\\$scheme)$")
    forward_domain_name: str

    # Redirect configuration
    forward_http_code: int = Field(default=301, ge=301, le=308)
    preserve_path: bool = True

    # SSL/TLS configuration
    certificate_id: int | None = None
    ssl_forced: bool = False
    hsts_enabled: bool = False
    hsts_subdomains: bool = False

    # Feature flags
    http2_support: bool = False
    block_exploits: bool = True

    # Advanced configuration
    advanced_config: str | None = None

    # Status
    enabled: bool = True

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

    @field_validator("domain_names")
    @classmethod
    def validate_domain_names(cls, v: list[str]) -> list[str]:
        """
        Validate that domain_names is not empty.

        Args:
            v: List of domain names

        Returns:
            Validated list of domain names

        Raises:
            ValueError: If domain_names is empty
        """
        if not v:
            msg = "domain_names cannot be empty"
            raise ValueError(msg)
        return v

    @field_validator("forward_http_code")
    @classmethod
    def validate_http_code(cls, v: int) -> int:
        """
        Validate that forward_http_code is a valid redirect code.

        Valid codes: 301 (Moved Permanently), 302 (Found), 307 (Temporary Redirect),
        308 (Permanent Redirect)

        Args:
            v: HTTP status code

        Returns:
            Validated HTTP status code

        Raises:
            ValueError: If code is not a valid redirect code
        """
        valid_codes = {301, 302, 307, 308}
        if v not in valid_codes:
            msg = f"forward_http_code must be one of {valid_codes}, got {v}"
            raise ValueError(msg)
        return v

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "domain_names": ["oldsite.com", "www.oldsite.com"],
                    "forward_scheme": "https",
                    "forward_domain_name": "newsite.com",
                    "forward_http_code": 301,
                    "preserve_path": True,
                },
                {
                    "domain_names": ["www.example.com"],
                    "forward_scheme": "$scheme",
                    "forward_domain_name": "example.com",
                    "forward_http_code": 301,
                },
            ]
        }
    }
