"""Tests for the deprecation header middleware."""

from datetime import UTC, datetime, timedelta
from pathlib import Path

import pytest
from httpx import ASGITransport, AsyncClient

from app.main import create_app
from app.middleware.deprecation import (
    _DEPRECATED_ENDPOINTS,
    _is_deprecated,
    register_deprecated_endpoint,
)


def _make_utc(days_from_now: int) -> datetime:
    return datetime.now(UTC) + timedelta(days=days_from_now)


@pytest.fixture
def clean_registry() -> list:
    """Clear the deprecated endpoints registry before and after each test."""
    original = list(_DEPRECATED_ENDPOINTS)
    _DEPRECATED_ENDPOINTS.clear()
    yield _DEPRECATED_ENDPOINTS
    _DEPRECATED_ENDPOINTS.clear()
    _DEPRECATED_ENDPOINTS.extend(original)


class TestIsDeprecated:
    def test_path_matches_registered_prefix(self, clean_registry: list) -> None:
        register_deprecated_endpoint("/api/v1/jails", _make_utc(180))
        assert _is_deprecated("/api/v1/jails") is not None
        assert _is_deprecated("/api/v1/jails/test-jail") is not None

    def test_path_does_not_match_unregistered_prefix(self, clean_registry: list) -> None:
        register_deprecated_endpoint("/api/v1/jails", _make_utc(180))
        assert _is_deprecated("/api/v1/bans") is None

    def test_empty_registry_returns_none(self, clean_registry: list) -> None:
        assert _is_deprecated("/api/v1/jails") is None


class TestDeprecationHeadersIntegration:
    @pytest.mark.asyncio
    async def test_deprecated_endpoint_gets_headers(self, clean_registry: list, tmp_path: Path) -> None:
        register_deprecated_endpoint("/api/v1/jails", _make_utc(180), successor_url="/api/v2/jails")
        from app.config import Settings

        config_dir = tmp_path / "fail2ban"
        config_dir.mkdir()
        settings = Settings(
            database_path="/tmp/test.db",
            fail2ban_socket="/tmp/fake.sock",
            fail2ban_config_dir=str(config_dir),
            session_secret="test-secret-key-do-not-use-in-production",
            session_duration_minutes=60,
            timezone="UTC",
            log_level="debug",
        )
        app = create_app(settings=settings)

        async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
            response = await client.get("/api/v1/jails")

        # 307 = setup redirect (app redirects unauthenticated/unconfigured requests)
        assert response.status_code in (200, 307, 401, 403, 404)
        assert "Deprecation" in response.headers or "Sunset" in response.headers

    @pytest.mark.asyncio
    async def test_non_deprecated_endpoint_no_headers(self, clean_registry: list, tmp_path: Path) -> None:
        register_deprecated_endpoint("/api/v1/jails", _make_utc(180))
        from app.config import Settings

        config_dir = tmp_path / "fail2ban"
        config_dir.mkdir()
        settings = Settings(
            database_path="/tmp/test.db",
            fail2ban_socket="/tmp/fake.sock",
            fail2ban_config_dir=str(config_dir),
            session_secret="test-secret-key-do-not-use-in-production",
            session_duration_minutes=60,
            timezone="UTC",
            log_level="debug",
        )
        app = create_app(settings=settings)

        async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client:
            response = await client.get("/api/v1/bans")

        # No Deprecation header on non-deprecated path
        assert "Deprecation" not in response.headers
