"""Tests for ban response mappers."""

from app.mappers import (
    map_domain_active_ban_list_to_response,
    map_domain_active_ban_to_response,
    map_domain_bans_by_country_to_response,
    map_domain_bans_by_jail_to_response,
    map_domain_ban_trend_to_response,
    map_domain_dashboard_ban_item_to_response,
    map_domain_dashboard_ban_list_to_response,
)
from app.models.ban_domain import (
    DomainActiveBan,
    DomainActiveBanList,
    DomainBansByCountry,
    DomainBansByJail,
    DomainBanTrend,
    DomainBanTrendBucket,
    DomainDashboardBanItem,
    DomainDashboardBanList,
    DomainJailBanCount,
)


class TestActiveBanMapper:
    """Test mapping from DomainActiveBan to ActiveBan."""

    def test_maps_all_fields(self) -> None:
        """All fields are correctly mapped."""
        domain_ban = DomainActiveBan(
            ip="192.168.1.1",
            jail="sshd",
            banned_at="2026-04-28T07:00:00+00:00",
            expires_at="2026-04-28T08:00:00+00:00",
            ban_count=3,
            country="DE",
        )

        result = map_domain_active_ban_to_response(domain_ban)

        assert result.ip == "192.168.1.1"
        assert result.jail == "sshd"
        assert result.banned_at == "2026-04-28T07:00:00+00:00"
        assert result.expires_at == "2026-04-28T08:00:00+00:00"
        assert result.ban_count == 3
        assert result.country == "DE"

    def test_handles_null_timestamps(self) -> None:
        """Null timestamps are preserved."""
        domain_ban = DomainActiveBan(
            ip="10.0.0.1",
            jail="test",
            banned_at=None,
            expires_at=None,
        )

        result = map_domain_active_ban_to_response(domain_ban)

        assert result.banned_at is None
        assert result.expires_at is None


class TestActiveBanListMapper:
    """Test mapping from DomainActiveBanList to ActiveBanListResponse."""

    def test_maps_list_and_total(self) -> None:
        """List and total are correctly mapped."""
        domain_list = DomainActiveBanList(
            bans=[
                DomainActiveBan(ip="1.1.1.1", jail="sshd", ban_count=1),
                DomainActiveBan(ip="2.2.2.2", jail="httpd", ban_count=2),
            ],
            total=2,
        )

        result = map_domain_active_ban_list_to_response(domain_list)

        assert result.total == 2
        assert len(result.items) == 2
        assert result.items[0].ip == "1.1.1.1"
        assert result.items[1].ip == "2.2.2.2"

    def test_handles_empty_list(self) -> None:
        """Empty list is handled correctly."""
        domain_list = DomainActiveBanList(bans=[], total=0)

        result = map_domain_active_ban_list_to_response(domain_list)

        assert result.total == 0
        assert len(result.items) == 0


class TestDashboardBanItemMapper:
    """Test mapping from DomainDashboardBanItem to DashboardBanItem."""

    def test_maps_all_fields(self) -> None:
        """All fields are correctly mapped."""
        domain_item = DomainDashboardBanItem(
            ip="203.0.113.1",
            jail="sshd",
            banned_at="2026-04-28T07:00:00+00:00",
            service="SSH login attempt",
            country_code="US",
            country_name="United States",
            asn="AS15169",
            org="Google LLC",
            ban_count=5,
            origin="selfblock",
        )

        result = map_domain_dashboard_ban_item_to_response(domain_item)

        assert result.ip == "203.0.113.1"
        assert result.jail == "sshd"
        assert result.banned_at == "2026-04-28T07:00:00+00:00"
        assert result.service == "SSH login attempt"
        assert result.country_code == "US"
        assert result.country_name == "United States"
        assert result.asn == "AS15169"
        assert result.org == "Google LLC"
        assert result.ban_count == 5
        assert result.origin == "selfblock"


class TestDashboardBanListMapper:
    """Test mapping from DomainDashboardBanList to DashboardBanListResponse."""

    def test_maps_pagination_and_items(self) -> None:
        """Pagination metadata and items are correctly mapped."""
        domain_list = DomainDashboardBanList(
            items=[
                DomainDashboardBanItem(
                    ip="1.1.1.1",
                    jail="sshd",
                    banned_at="2026-04-28T07:00:00+00:00",
                    ban_count=1,
                ),
            ],
            total=100,
            page=2,
            page_size=50,
        )

        result = map_domain_dashboard_ban_list_to_response(domain_list)

        assert result.pagination.total == 100
        assert result.pagination.page == 2
        assert result.pagination.page_size == 50
        assert len(result.items) == 1
        assert result.items[0].ip == "1.1.1.1"


class TestBansByCountryMapper:
    """Test mapping from DomainBansByCountry to BansByCountryResponse."""

    def test_maps_aggregation_and_items(self) -> None:
        """Country aggregation and companion items are correctly mapped."""
        domain_data = DomainBansByCountry(
            countries={"US": 10, "DE": 5, "GB": 3},
            country_names={"US": "United States", "DE": "Germany", "GB": "United Kingdom"},
            items=[
                DomainDashboardBanItem(
                    ip="1.1.1.1",
                    jail="sshd",
                    banned_at="2026-04-28T07:00:00+00:00",
                    ban_count=1,
                    origin="selfblock",
                ),
            ],
            total=18,
        )

        result = map_domain_bans_by_country_to_response(domain_data)

        assert result.countries == {"US": 10, "DE": 5, "GB": 3}
        assert result.country_names == {"US": "United States", "DE": "Germany", "GB": "United Kingdom"}
        assert result.total == 18
        assert len(result.bans) == 1


class TestBanTrendMapper:
    """Test mapping from DomainBanTrend to BanTrendResponse."""

    def test_maps_buckets_and_size_label(self) -> None:
        """Buckets and size label are correctly mapped."""
        domain_trend = DomainBanTrend(
            buckets=[
                DomainBanTrendBucket(timestamp="2026-04-28T00:00:00+00:00", count=10),
                DomainBanTrendBucket(timestamp="2026-04-28T01:00:00+00:00", count=15),
            ],
            bucket_size="1h",
        )

        result = map_domain_ban_trend_to_response(domain_trend)

        assert result.bucket_size == "1h"
        assert len(result.buckets) == 2
        assert result.buckets[0].timestamp == "2026-04-28T00:00:00+00:00"
        assert result.buckets[0].count == 10


class TestBansByJailMapper:
    """Test mapping from DomainBansByJail to BansByJailResponse."""

    def test_maps_jail_counts(self) -> None:
        """Jail counts are correctly mapped."""
        domain_data = DomainBansByJail(
            jails=[
                DomainJailBanCount(jail="sshd", count=50),
                DomainJailBanCount(jail="httpd", count=20),
            ],
            total=70,
        )

        result = map_domain_bans_by_jail_to_response(domain_data)

        assert result.total == 70
        assert len(result.jails) == 2
        assert result.jails[0].jail == "sshd"
        assert result.jails[0].count == 50
