"""Config domain models.

Internal domain-focused models used by config_service. These represent the
business domain layer and are independent of HTTP response shapes.

Response models are defined in `app.models.config` and mappers convert domain
models to response models at the router boundary.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal


DNSMode = Literal["yes", "warn", "no", "raw"]
LogEncoding = Literal["auto", "ascii", "utf-8", "UTF-8", "latin-1"]
BackendType = Literal["auto", "polling", "pyinotify", "systemd", "gamin"]
LogLevel = Literal["CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"]


@dataclass(frozen=True)
class DomainBantimeEscalation:
    """Incremental ban-time escalation configuration (domain model)."""

    increment: bool = False
    factor: float | None = None
    formula: str | None = None
    multipliers: str | None = None
    max_time: int | None = None
    rnd_time: int | None = None
    overall_jails: bool = False


@dataclass(frozen=True)
class DomainJailConfig:
    """Configuration snapshot of a single jail (domain model)."""

    name: str
    ban_time: int
    max_retry: int
    find_time: int
    fail_regex: list[str]
    ignore_regex: list[str]
    log_paths: list[str]
    actions: list[str]
    date_pattern: str | None = None
    log_encoding: LogEncoding = "UTF-8"
    backend: BackendType = "polling"
    use_dns: DNSMode = "warn"
    prefregex: str = ""
    bantime_escalation: DomainBantimeEscalation | None = None


@dataclass(frozen=True)
class DomainJailConfigList:
    """List of jail configurations (domain model)."""

    items: list[DomainJailConfig]
    total: int


@dataclass(frozen=True)
class DomainGlobalConfig:
    """Global fail2ban settings (domain model)."""

    log_level: LogLevel
    log_target: str
    db_purge_age: int
    db_max_matches: int


@dataclass(frozen=True)
class DomainServiceStatus:
    """Fail2ban service health status (domain model)."""

    online: bool
    version: str | None = None
    jail_count: int = 0
    total_bans: int = 0
    total_failures: int = 0
    log_level: str | None = None
    log_target: str | None = None


@dataclass(frozen=True)
class DomainMapColorThresholds:
    """Map color threshold configuration (domain model)."""

    threshold_high: int
    threshold_medium: int
    threshold_low: int


@dataclass(frozen=True)
class DomainRegexTest:
    """Result of a regex test (domain model)."""

    matched: bool
    groups: list[str]
    error: str | None = None


@dataclass(frozen=True)
class DomainFilterConfig:
    """Structured representation of a filter.d/*.conf file (domain model)."""

    name: str
    filename: str
    before: str | None = None
    after: str | None = None
    variables: dict[str, str] | None = None
    prefregex: str | None = None
    failregex: list[str] | None = None
    ignoreregex: list[str] | None = None
    maxlines: int | None = None
    datepattern: str | None = None
    journalmatch: str | None = None
    active: bool = False
    used_by_jails: list[str] | None = None
    source_file: str = ""
    has_local_override: bool = False


@dataclass(frozen=True)
class DomainFilterList:
    """List of filter configurations (domain model)."""

    items: list[DomainFilterConfig]
    total: int
