"""Integration tests for API endpoints."""

from unittest.mock import Mock, patch

import pytest
from fastapi.testclient import TestClient

from apps.backend.api.main import app, get_db
from packages.core.storage.models import Driver, Horse, Trainer


class TestAPIEndpoints:
    """Tests for API endpoints."""

    @pytest.fixture
    def client(self, mock_db_session):
        """Create test client."""

        def override_get_db():
            yield mock_db_session

        app.dependency_overrides[get_db] = override_get_db
        with TestClient(app) as test_client:
            yield test_client
        app.dependency_overrides.clear()

    @pytest.fixture
    def mock_db_session(self):
        """Create mock database session."""
        return Mock()

    def test_health_endpoint(self, client):
        """Test health check endpoint."""
        response = client.get("/health")
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "healthy"
        assert "version" in data

    def test_driver_detail_endpoint(self, client, mock_db_session):
        """Test driver detail endpoint."""
        # Mock driver
        mock_driver = Mock(spec=Driver)
        mock_driver.id = 1
        mock_driver.name = "Test Driver"

        # Mock snapshots
        mock_snapshot = Mock()
        mock_snapshot.as_of_race_id = 100
        mock_snapshot.rating = 1650.0
        mock_snapshot.rd = 120.0

        mock_query = Mock()
        mock_query.join.return_value = mock_query
        mock_query.filter.return_value = mock_query
        mock_query.order_by.return_value = mock_query
        mock_query.first.return_value = mock_driver
        mock_query.all.return_value = [mock_snapshot]

        mock_db_session.query.return_value = mock_query

        response = client.get("/ratings/drivers/1")
        assert response.status_code == 200
        data = response.json()
        assert data["driver_id"] == 1
        assert data["name"] == "Test Driver"

    def test_trainer_detail_endpoint(self, client, mock_db_session):
        """Test trainer detail endpoint."""
        # Mock trainer
        mock_trainer = Mock(spec=Trainer)
        mock_trainer.id = 1
        mock_trainer.name = "Test Trainer"

        # Mock snapshots
        mock_snapshot = Mock()
        mock_snapshot.as_of_race_id = 100
        mock_snapshot.rating = 1600.0
        mock_snapshot.rd = 100.0

        mock_query = Mock()
        mock_query.join.return_value = mock_query
        mock_query.filter.return_value = mock_query
        mock_query.order_by.return_value = mock_query
        mock_query.first.return_value = mock_trainer
        mock_query.all.return_value = [mock_snapshot]

        mock_db_session.query.return_value = mock_query

        response = client.get("/ratings/trainers/1")
        assert response.status_code == 200
        data = response.json()
        assert data["trainer_id"] == 1
        assert data["name"] == "Test Trainer"

    def test_csv_export_format(self, client):
        """Test CSV export functionality."""
        # Mock empty results
        with patch(
            "apps.backend.api.main.RatingSnapshotRepository.get_top_ratings"
        ) as mock_repo:
            mock_repo.return_value = []

            response = client.get("/ratings/horses?format=csv")
            assert response.status_code == 200
            assert response.headers["content-type"] == "text/csv; charset=utf-8"

    def test_cors_headers(self, client):
        """Test CORS headers are present."""
        response = client.options("/health")
        # CORS middleware should add headers
        assert (
            "access-control-allow-origin" in response.headers
            or response.status_code
            in [
                200,
                405,
            ]
        )

    def test_race_predictions_endpoint(self, client, mock_db_session):
        """Test race predictions endpoint."""
        from datetime import datetime

        from packages.core.ratings.predictions import PredictionResult, RacePrediction
        from packages.core.storage.models import Meeting, Race, Starter

        # Mock race
        mock_race = Mock(spec=Race)
        mock_race.id = 1
        mock_race.race_number = 5
        mock_race.distance_m = 2000
        mock_race.meeting = Mock(spec=Meeting)
        mock_race.meeting.venue = "Test Venue"
        mock_race.meeting.meeting_date = "2025-01-26"

        # Mock starters
        mock_starter = Mock(spec=Starter)
        mock_starter.id = 1
        mock_starter.horse_id = 100
        mock_starter.driver_id = 10
        mock_starter.trainer_id = 20
        mock_starter.barrier = 1
        mock_starter.placing = None

        mock_horse = Mock(spec=Horse)
        mock_horse.id = 100
        mock_horse.name = "Test Horse"

        # Setup mock queries
        def query_side_effect(model):
            mock_q = Mock()
            if model == Race:
                mock_q.filter.return_value.first.return_value = mock_race
                mock_q.options.return_value.filter.return_value.first.return_value = (
                    mock_race
                )
            elif model == Starter:
                mock_q.filter.return_value.all.return_value = [mock_starter]
            elif model == Horse:
                mock_q.filter.return_value.first.return_value = mock_horse
            else:
                mock_q.filter.return_value.first.return_value = None
            return mock_q

        mock_db_session.query.side_effect = query_side_effect

        mock_prediction = RacePrediction(
            race_id=1,
            race_number=5,
            venue="Test Venue",
            distance_m=2000,
            race_date=mock_race.meeting.meeting_date,
            predictions=[
                PredictionResult(
                    starter_id=1,
                    horse_id=100,
                    horse_name="Test Horse",
                    driver_id=10,
                    driver_name="Test Driver",
                    trainer_id=20,
                    trainer_name="Test Trainer",
                    barrier=1,
                    handicap_m=None,
                    effective_rating=1500.0,
                    win_probability=0.5,
                    place_probability=0.8,
                    place_score=1520.0,
                    confidence_interval_low=1400.0,
                    confidence_interval_high=1600.0,
                    predicted_placing=1,
                )
            ],
            prediction_timestamp=datetime.now(),
            metadata={},
        )

        with patch(
            "packages.core.ratings.predictions.PredictionEngine"
        ) as mock_engine_class:
            mock_engine = Mock()
            mock_engine.predict_race.return_value = mock_prediction
            mock_engine_class.return_value = mock_engine

            response = client.get("/races/1/predictions")
            assert response.status_code == 200
            data = response.json()
            assert data["race_id"] == 1
            assert "predictions" in data
