"""Integration tests for FastAPI dependency."""

from datetime import UTC, datetime
from uuid import uuid4

import pytest
from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient

from ingress_recipient import RecipientData, ValidatedRecipientData, validate_recipient_data


@pytest.fixture
def app():
    """Create test FastAPI app with recipient endpoint."""
    app = FastAPI()

    @app.post("/test/depends")
    async def test_endpoint_with_depends(
        data: RecipientData = Depends(validate_recipient_data),
    ):
        return {
            "status": "accepted",
            "channel_id": data.channel_id,
            "tenant_id": str(data.tenant_id),
        }

    @app.post("/test/annotated")
    async def test_endpoint_with_annotated(data: ValidatedRecipientData):
        return {
            "status": "accepted",
            "channel_id": data.channel_id,
            "tenant_id": str(data.tenant_id),
        }

    return app


@pytest.fixture
def client(app):
    """Create test client."""
    return TestClient(app)


class TestFastAPIIntegration:
    """Tests for FastAPI integration."""

    def test_valid_request_accepted_with_depends(self, client):
        """Test that valid request is accepted with Depends()."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {"value": 1},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 200
        assert response.json()["status"] == "accepted"
        assert response.json()["channel_id"] == "ch_test"

    def test_valid_request_accepted_with_annotated(self, client):
        """Test that valid request is accepted with ValidatedRecipientData."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {"value": 1},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/annotated", json=payload)

        assert response.status_code == 200
        assert response.json()["status"] == "accepted"
        assert response.json()["channel_id"] == "ch_test"

    def test_invalid_request_returns_422(self, client):
        """Test that invalid request returns 422."""
        payload = {
            "channel_id": "",  # Invalid - empty
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422

    def test_invalid_uuid_returns_422(self, client):
        """Test that invalid UUID returns 422."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": "not-a-uuid",
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422

    def test_invalid_timestamp_returns_422(self, client):
        """Test that invalid timestamp returns 422."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": "not-a-timestamp",
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422

    def test_missing_required_fields_returns_422(self, client):
        """Test that missing required fields returns 422."""
        payload = {"channel_id": "ch_test"}

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422

    def test_error_response_has_detail(self, client):
        """Test that error response has detail field."""
        payload = {
            "channel_id": "",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422
        assert "detail" in response.json()
        assert isinstance(response.json()["detail"], list)

    def test_error_detail_has_correct_format(self, client):
        """Test that error detail has correct Pydantic format."""
        payload = {
            "channel_id": "",
            "tenant_id": "not-a-uuid",
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 422

        detail = response.json()["detail"]
        assert len(detail) > 0

        for error in detail:
            assert "loc" in error
            assert "msg" in error
            assert "type" in error
            assert isinstance(error["loc"], list)

    def test_empty_data_object_accepted(self, client):
        """Test that empty data object is accepted."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {},
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 200

    def test_nested_data_accepted(self, client):
        """Test that nested data structures are accepted."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {
                "vessel": {"id": "v_123", "name": "Test Vessel"},
                "position": {"lat": 59.9139, "lng": 10.7522},
            },
            "metadata": {"ingress_timestamp": datetime.now(UTC).isoformat()},
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 200

    def test_optional_metadata_fields(self, client):
        """Test that optional metadata fields work."""
        payload = {
            "channel_id": "ch_test",
            "tenant_id": str(uuid4()),
            "timestamp": datetime.now(UTC).isoformat(),
            "data": {"value": 1},
            "metadata": {
                "source_ip": "192.168.1.100",
                "ingress_timestamp": datetime.now(UTC).isoformat(),
                "transformations_applied": ["normalize", "enrich"],
            },
        }

        response = client.post("/test/depends", json=payload)

        assert response.status_code == 200
