"""Tests for planet events tool and Skyfield provider."""

import pytest

# Check if Skyfield is available
try:
    from chuk_mcp_celestial.providers.skyfield_provider import (
        SkyfieldProvider,
        SKYFIELD_AVAILABLE,
    )
except ImportError:
    SKYFIELD_AVAILABLE = False
    SkyfieldProvider = None  # type: ignore

from chuk_mcp_celestial.models import Planet


pytestmark = pytest.mark.skipif(not SKYFIELD_AVAILABLE, reason="Skyfield not installed")


@pytest.fixture
def skyfield_provider():
    """Create a Skyfield provider with memory backend."""
    return SkyfieldProvider(storage_backend="memory")


# ============================================================================
# Planet Events via Provider
# ============================================================================


@pytest.mark.asyncio
async def test_jupiter_events(skyfield_provider, seattle_coords):
    """Test getting Jupiter rise/set/transit events."""
    result = await skyfield_provider.get_planet_events(
        planet="Jupiter",
        date="2025-6-15",
        latitude=seattle_coords["latitude"],
        longitude=seattle_coords["longitude"],
    )

    assert result is not None
    assert result.type == "Feature"
    assert result.apiversion == "Skyfield 1.x"

    data = result.properties.data
    assert data.planet == Planet.JUPITER
    assert data.date == "2025-6-15"
    assert isinstance(data.events, list)
    assert isinstance(data.constellation, str)
    assert isinstance(data.magnitude, float)

    # Jupiter should normally have rise/set/transit events at mid-latitudes
    if data.events:
        for event in data.events:
            assert event.phen in ("Rise", "Set", "Upper Transit")
            assert ":" in event.time


@pytest.mark.asyncio
async def test_all_planets_events(skyfield_provider, seattle_coords):
    """Test events for each supported planet."""
    for planet in Planet:
        result = await skyfield_provider.get_planet_events(
            planet=planet.value,
            date="2025-6-15",
            latitude=seattle_coords["latitude"],
            longitude=seattle_coords["longitude"],
        )
        assert result is not None
        assert result.properties.data.planet == planet


@pytest.mark.asyncio
async def test_events_with_timezone(skyfield_provider, seattle_coords):
    """Test events with timezone offset."""
    result = await skyfield_provider.get_planet_events(
        planet="Mars",
        date="2025-6-15",
        latitude=seattle_coords["latitude"],
        longitude=seattle_coords["longitude"],
        timezone=-7,
    )

    assert result is not None
    data = result.properties.data
    assert data.planet == Planet.MARS


@pytest.mark.asyncio
async def test_events_with_dst(skyfield_provider, seattle_coords):
    """Test events with DST applied."""
    result = await skyfield_provider.get_planet_events(
        planet="Venus",
        date="2025-6-15",
        latitude=seattle_coords["latitude"],
        longitude=seattle_coords["longitude"],
        timezone=-8,
        dst=True,
    )

    assert result is not None
    data = result.properties.data
    assert data.planet == Planet.VENUS


@pytest.mark.asyncio
async def test_invalid_planet_events(skyfield_provider, seattle_coords):
    """Test that invalid planet name raises ValueError."""
    with pytest.raises(ValueError, match="Unknown planet"):
        await skyfield_provider.get_planet_events(
            planet="InvalidPlanet",
            date="2025-1-15",
            latitude=seattle_coords["latitude"],
            longitude=seattle_coords["longitude"],
        )


@pytest.mark.asyncio
async def test_events_geojson_structure(skyfield_provider, greenwich_coords):
    """Test GeoJSON Feature output structure."""
    result = await skyfield_provider.get_planet_events(
        planet="Saturn",
        date="2025-3-1",
        latitude=greenwich_coords["latitude"],
        longitude=greenwich_coords["longitude"],
    )

    data = result.model_dump()
    assert data["type"] == "Feature"
    assert "geometry" in data
    assert data["geometry"]["type"] == "Point"
    assert len(data["geometry"]["coordinates"]) == 2
    assert "properties" in data
    assert "data" in data["properties"]

    events_data = data["properties"]["data"]
    assert "planet" in events_data
    assert "date" in events_data
    assert "events" in events_data
    assert "constellation" in events_data
    assert "magnitude" in events_data


@pytest.mark.asyncio
async def test_events_sorted_by_time(skyfield_provider, seattle_coords):
    """Test that events are sorted chronologically."""
    result = await skyfield_provider.get_planet_events(
        planet="Mars",
        date="2025-6-15",
        latitude=seattle_coords["latitude"],
        longitude=seattle_coords["longitude"],
    )

    events = result.properties.data.events
    if len(events) > 1:
        times = [e.time for e in events]
        assert times == sorted(times)


@pytest.mark.asyncio
async def test_events_southern_hemisphere(skyfield_provider, sydney_coords):
    """Test planet events for Southern Hemisphere location."""
    result = await skyfield_provider.get_planet_events(
        planet="Jupiter",
        date="2025-7-1",
        latitude=sydney_coords["latitude"],
        longitude=sydney_coords["longitude"],
    )

    assert result is not None
    assert result.geometry.coordinates[0] == pytest.approx(sydney_coords["longitude"], abs=0.1)
    assert result.geometry.coordinates[1] == pytest.approx(sydney_coords["latitude"], abs=0.1)
