"""Jail management Pydantic models.

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

from pydantic import BaseModel, ConfigDict, Field

from app.models.config import BantimeEscalation


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

    model_config = ConfigDict(strict=True)

    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(BaseModel):
    """Domain model for a single fail2ban jail with its full configuration."""

    model_config = ConfigDict(strict=True)

    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(BaseModel):
    """Lightweight jail entry for the overview list."""

    model_config = ConfigDict(strict=True)

    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(BaseModel):
    """Response for ``GET /api/jails``."""

    model_config = ConfigDict(strict=True)

    jails: list[JailSummary] = Field(default_factory=list)
    total: int = Field(..., ge=0)


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

    model_config = ConfigDict(strict=True)

    jail: Jail


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

    model_config = ConfigDict(strict=True)

    message: str
    jail: str


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

    model_config = ConfigDict(strict=True)

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