"""Ban domain models (DTOs).

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

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

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

# Domain-specific ban origin type
BanOriginDomain = Literal["blocklist", "selfblock"]


@dataclass(frozen=True)
class DomainActiveBan:
    """A currently active ban entry (domain model).

    This is the service-layer representation, independent of API response shape.
    """

    ip: str
    jail: str
    banned_at: str | None = None
    expires_at: str | None = None
    ban_count: int = 1
    country: str | None = None


@dataclass(frozen=True)
class DomainActiveBanList:
    """List of currently active bans (domain model)."""

    bans: list[DomainActiveBan]
    total: int


@dataclass(frozen=True)
class DomainDashboardBanItem:
    """A single row in the dashboard ban-list table (domain model).

    Populated from the fail2ban database and enriched with geo data.
    """

    ip: str
    jail: str
    banned_at: str
    service: str | None = None
    country_code: str | None = None
    country_name: str | None = None
    asn: str | None = None
    org: str | None = None
    ban_count: int = 1
    origin: BanOriginDomain = "selfblock"


@dataclass(frozen=True)
class DomainDashboardBanList:
    """Paginated dashboard ban-list (domain model)."""

    items: list[DomainDashboardBanItem]
    total: int
    page: int
    page_size: int


@dataclass(frozen=True)
class DomainBansByCountry:
    """Bans aggregated by country (domain model)."""

    countries: dict[str, int]
    country_names: dict[str, str]
    items: list[DomainDashboardBanItem]
    total: int


@dataclass(frozen=True)
class DomainBanTrendBucket:
    """A single time bucket in the ban trend series (domain model)."""

    timestamp: str
    count: int


@dataclass(frozen=True)
class DomainBanTrend:
    """Ban trend data over time (domain model)."""

    buckets: list[DomainBanTrendBucket]
    bucket_size: str


@dataclass(frozen=True)
class DomainJailBanCount:
    """Ban count for a single jail (domain model)."""

    jail: str
    count: int


@dataclass(frozen=True)
class DomainBansByJail:
    """Bans aggregated by jail (domain model)."""

    jails: list[DomainJailBanCount]
    total: int
