"""Tests for WNBA scraper."""

from datetime import datetime
from unittest.mock import patch

import pytest

from sportstime_parser.scrapers.wnba import WNBAScraper, create_wnba_scraper
from sportstime_parser.scrapers.base import RawGameData
from sportstime_parser.tests.fixtures import (
    load_json_fixture,
    WNBA_ESPN_SCOREBOARD_JSON,
)


class TestWNBAScraperInit:
    """Test WNBAScraper initialization."""

    def test_creates_scraper_with_season(self):
        """Test scraper initializes with correct season."""
        scraper = WNBAScraper(season=2026)
        assert scraper.sport == "wnba"
        assert scraper.season == 2026

    def test_factory_function_creates_scraper(self):
        """Test factory function creates correct scraper."""
        scraper = create_wnba_scraper(season=2026)
        assert isinstance(scraper, WNBAScraper)
        assert scraper.season == 2026

    def test_expected_game_count(self):
        """Test expected game count is correct for WNBA."""
        scraper = WNBAScraper(season=2026)
        assert scraper.expected_game_count == 220

    def test_sources_in_priority_order(self):
        """Test sources are returned in correct priority order."""
        scraper = WNBAScraper(season=2026)
        sources = scraper._get_sources()
        assert sources == ["espn"]


class TestESPNParsing:
    """Test ESPN API response parsing."""

    def test_parses_completed_games(self):
        """Test parsing completed games from ESPN."""
        scraper = WNBAScraper(season=2026)
        data = load_json_fixture(WNBA_ESPN_SCOREBOARD_JSON)
        games = scraper._parse_espn_response(data, "http://espn.com/api")

        completed = [g for g in games if g.status == "final"]
        assert len(completed) == 2

        # Aces @ Liberty
        lv_ny = next(g for g in completed if g.away_team_raw == "Las Vegas Aces")
        assert lv_ny.home_team_raw == "New York Liberty"
        assert lv_ny.away_score == 88
        assert lv_ny.home_score == 92
        assert lv_ny.stadium_raw == "Barclays Center"

    def test_parses_scheduled_games(self):
        """Test parsing scheduled games from ESPN."""
        scraper = WNBAScraper(season=2026)
        data = load_json_fixture(WNBA_ESPN_SCOREBOARD_JSON)
        games = scraper._parse_espn_response(data, "http://espn.com/api")

        scheduled = [g for g in games if g.status == "scheduled"]
        assert len(scheduled) == 1

        phx_sea = scheduled[0]
        assert phx_sea.away_team_raw == "Phoenix Mercury"
        assert phx_sea.home_team_raw == "Seattle Storm"
        assert phx_sea.stadium_raw == "Climate Pledge Arena"

    def test_parses_venue_info(self):
        """Test venue information is extracted."""
        scraper = WNBAScraper(season=2026)
        data = load_json_fixture(WNBA_ESPN_SCOREBOARD_JSON)
        games = scraper._parse_espn_response(data, "http://espn.com/api")

        for game in games:
            assert game.stadium_raw is not None


class TestGameNormalization:
    """Test game normalization and canonical ID generation."""

    def test_normalizes_games_with_canonical_ids(self):
        """Test games are normalized with correct canonical IDs."""
        scraper = WNBAScraper(season=2026)

        raw_games = [
            RawGameData(
                game_date=datetime(2026, 5, 20),
                home_team_raw="New York Liberty",
                away_team_raw="Las Vegas Aces",
                stadium_raw="Barclays Center",
                home_score=92,
                away_score=88,
                status="final",
                source_url="http://example.com",
            )
        ]

        games, review_items = scraper._normalize_games(raw_games)

        assert len(games) == 1
        game = games[0]

        # Check canonical ID format
        assert game.id == "wnba_2026_lv_ny_0520"
        assert game.sport == "wnba"
        assert game.season == 2026

        # Check team IDs
        assert game.home_team_id == "team_wnba_ny"
        assert game.away_team_id == "team_wnba_lv"

        # Check scores preserved
        assert game.home_score == 92
        assert game.away_score == 88

    def test_creates_review_items_for_unresolved_teams(self):
        """Test review items are created for unresolved teams."""
        scraper = WNBAScraper(season=2026)

        raw_games = [
            RawGameData(
                game_date=datetime(2026, 5, 20),
                home_team_raw="Unknown Team XYZ",
                away_team_raw="Las Vegas Aces",
                stadium_raw="Barclays Center",
                status="scheduled",
            ),
        ]

        games, review_items = scraper._normalize_games(raw_games)

        # Game should not be created due to unresolved team
        assert len(games) == 0

        # But there should be a review item
        assert len(review_items) >= 1


class TestTeamAndStadiumScraping:
    """Test team and stadium data scraping."""

    def test_scrapes_all_wnba_teams(self):
        """Test all WNBA teams are returned."""
        scraper = WNBAScraper(season=2026)
        teams = scraper.scrape_teams()

        # WNBA has 13 teams (including Golden State Valkyries)
        assert len(teams) == 13

        # Check team IDs are unique
        team_ids = [t.id for t in teams]
        assert len(set(team_ids)) == 13

        # Check all teams have required fields
        for team in teams:
            assert team.id.startswith("team_wnba_")
            assert team.sport == "wnba"
            assert team.city
            assert team.name
            assert team.full_name
            assert team.abbreviation

    def test_scrapes_all_wnba_stadiums(self):
        """Test all WNBA stadiums are returned."""
        scraper = WNBAScraper(season=2026)
        stadiums = scraper.scrape_stadiums()

        # Should have stadiums for all teams
        assert len(stadiums) == 13

        # Check stadium IDs are unique
        stadium_ids = [s.id for s in stadiums]
        assert len(set(stadium_ids)) == 13

        # Check all stadiums have required fields
        for stadium in stadiums:
            assert stadium.id.startswith("stadium_wnba_")
            assert stadium.sport == "wnba"
            assert stadium.name
            assert stadium.city
            assert stadium.state
            assert stadium.country == "USA"
            assert stadium.latitude != 0
            assert stadium.longitude != 0


class TestScrapeFallback:
    """Test fallback behavior (WNBA only has ESPN)."""

    def test_returns_failure_when_espn_fails(self):
        """Test scraper returns failure when ESPN fails."""
        scraper = WNBAScraper(season=2026)

        with patch.object(scraper, '_scrape_espn') as mock_espn:
            mock_espn.side_effect = Exception("ESPN failed")

            result = scraper.scrape_games()

            assert not result.success
            assert "All sources failed" in result.error_message


class TestSeasonMonths:
    """Test season month calculation."""

    def test_gets_correct_season_months(self):
        """Test correct months are returned for WNBA season."""
        scraper = WNBAScraper(season=2026)
        months = scraper._get_season_months()

        # WNBA season is May-October
        assert len(months) == 6  # May, Jun, Jul, Aug, Sep, Oct

        # Check first month is May of season year
        assert months[0] == (2026, 5)

        # Check last month is October
        assert months[-1] == (2026, 10)
