"""Jail management Pydantic models.

Request, response, and domain models used by the jails router and service.
"""

from pydantic import Field

from app.models.config import BantimeEscalation
from app.models.response import BanGuiBaseModel, CommandResponse, CollectionResponse

class JailStatus(BanGuiBaseModel):
    """Runtime metrics for a single jail."""

    currently_banned: int = Field(..., ge=0)
    total_banned: int = Field(..., ge=0)
    currently_failed: int = Field(..., ge=0)
    total_failed: int = Field(..., ge=0)

class Jail(BanGuiBaseModel):
    """Domain model for a single fail2ban jail with its full configuration."""

    name: str = Field(..., description="Jail name as configured in fail2ban.")
    enabled: bool = Field(..., description="Whether the jail is currently active.")
    running: bool = Field(..., description="Whether the jail backend is running.")
    idle: bool = Field(default=False, description="Whether the jail is in idle mode.")
    backend: str = Field(..., description="Log monitoring backend (e.g. polling, systemd).")
    log_paths: list[str] = Field(default_factory=list, description="Monitored log files.")
    fail_regex: list[str] = Field(default_factory=list, description="Failure detection regex patterns.")
    ignore_regex: list[str] = Field(default_factory=list, description="Regex patterns that bypass the ban logic.")
    ignore_ips: list[str] = Field(default_factory=list, description="IP addresses or CIDRs on the ignore list.")
    date_pattern: str | None = Field(default=None, description="Custom date pattern for log parsing.")
    log_encoding: str = Field(default="UTF-8", description="Log file encoding.")
    find_time: int = Field(..., description="Time window (seconds) for counting failures.")
    ban_time: int = Field(..., description="Duration (seconds) of a ban. -1 means permanent.")
    max_retry: int = Field(..., description="Number of failures before a ban is issued.")
    actions: list[str] = Field(default_factory=list, description="Names of actions attached to this jail.")
    bantime_escalation: BantimeEscalation | None = Field(
        default=None,
        description="Incremental ban-time escalation settings, or None if not configured.",
    )
    status: JailStatus | None = Field(default=None, description="Runtime counters.")

class JailSummary(BanGuiBaseModel):
    """Lightweight jail entry for the overview list."""

    name: str
    enabled: bool
    running: bool
    idle: bool
    backend: str
    find_time: int
    ban_time: int
    max_retry: int
    status: JailStatus | None = None

class JailListResponse(CollectionResponse[JailSummary]):
    """Response for ``GET /api/jails``.

    Returns a non-paginated collection of jail summaries with their current status.
    """

    pass

class IgnoreListResponse(CollectionResponse[str]):
    """Response for ``GET /api/jails/{name}/ignoreip``.

    Returns the jailed ignore list as a standard collection response.
    """

    pass

class JailDetailResponse(BanGuiBaseModel):
    """Response for ``GET /api/jails/{name}``.

    Includes the primary jail object together with supplemental metadata
    required by the UI.
    """

    jail: Jail
    ignore_list: list[str] = Field(
        default_factory=list,
        description="List of IP addresses and networks currently ignored by the jail.",
    )
    ignore_self: bool = Field(
        default=False,
        description="Whether the jail ignores the server's own IP addresses.",
    )

class JailCommandResponse(CommandResponse):
    """Generic response for jail control commands (start, stop, reload, idle).

    Extends the base CommandResponse with a jail field to identify the target.
    """

    jail: str = Field(..., description="Target jail name, or '*' for operations on all jails.")

class IgnoreIpRequest(BanGuiBaseModel):
    """Payload for adding an IP or network to a jail's ignore list."""

    ip: str = Field(..., description="IP address or CIDR network to ignore.")
