# Copyright 2026 4f4d
# Licensed under the Apache License, Version 2.0

"""Tests for f1radio.context."""

import pytest

from f1radio.context import (
    ContextEnricher,
    _extract_timestamps,
    _find_nearest,
    _find_nearby,
)
from tests.conftest import (
    MOCK_DRIVERS,
    MOCK_INTERVALS,
    MOCK_LAPS,
    MOCK_OVERTAKES,
    MOCK_PIT,
    MOCK_POSITION,
    MOCK_RACE_CONTROL,
    MOCK_STINTS,
)


class TestExtractTimestamps:
    def test_basic(self):
        data = [
            {"date": "2023-09-03T13:00:00+00:00", "value": 1},
            {"date": "2023-09-03T14:00:00+00:00", "value": 2},
        ]
        result = _extract_timestamps(data)
        assert len(result) == 2
        assert result[0][0] < result[1][0]  # Sorted by timestamp

    def test_missing_date(self):
        data = [{"value": 1}, {"date": "2023-09-03T13:00:00+00:00", "value": 2}]
        result = _extract_timestamps(data)
        assert len(result) == 1

    def test_empty(self):
        assert _extract_timestamps([]) == []


class TestFindNearest:
    def test_exact_match(self):
        data = _extract_timestamps([
            {"date": "2023-09-03T13:00:00+00:00", "v": "a"},
            {"date": "2023-09-03T14:00:00+00:00", "v": "b"},
        ])
        from f1radio.utils import _parse_iso_datetime
        target = _parse_iso_datetime("2023-09-03T13:00:00+00:00").timestamp()
        result = _find_nearest(data, target)
        assert result["v"] == "a"

    def test_nearest(self):
        data = _extract_timestamps([
            {"date": "2023-09-03T13:00:00+00:00", "v": "a"},
            {"date": "2023-09-03T14:00:00+00:00", "v": "b"},
        ])
        from f1radio.utils import _parse_iso_datetime
        # Closer to 14:00:00
        target = _parse_iso_datetime("2023-09-03T13:45:00+00:00").timestamp()
        result = _find_nearest(data, target)
        assert result["v"] == "b"

    def test_max_delta(self):
        data = _extract_timestamps([
            {"date": "2023-09-03T13:00:00+00:00", "v": "a"},
        ])
        from f1radio.utils import _parse_iso_datetime
        target = _parse_iso_datetime("2023-09-03T15:00:00+00:00").timestamp()
        # 2 hours = 7200 seconds, max_delta = 60 → should return None
        assert _find_nearest(data, target, max_delta=60) is None

    def test_empty(self):
        assert _find_nearest([], 0) is None


class TestFindNearby:
    def test_within_window(self):
        data = _extract_timestamps([
            {"date": "2023-09-03T13:00:00+00:00", "v": "a"},
            {"date": "2023-09-03T13:00:05+00:00", "v": "b"},
            {"date": "2023-09-03T13:00:20+00:00", "v": "c"},
        ])
        from f1radio.utils import _parse_iso_datetime
        target = _parse_iso_datetime("2023-09-03T13:00:03+00:00").timestamp()
        result = _find_nearby(data, target, window_seconds=10)
        assert len(result) == 2  # a and b, not c
        values = [r["v"] for r in result]
        assert "a" in values
        assert "b" in values

    def test_empty_window(self):
        data = _extract_timestamps([
            {"date": "2023-09-03T15:00:00+00:00", "v": "a"},
        ])
        from f1radio.utils import _parse_iso_datetime
        target = _parse_iso_datetime("2023-09-03T13:00:00+00:00").timestamp()
        assert _find_nearby(data, target, window_seconds=10) == []


class TestContextEnricher:
    def test_enrich_basic(self):
        enricher = ContextEnricher(
            position_data=MOCK_POSITION,
            interval_data=MOCK_INTERVALS,
            stint_data=MOCK_STINTS,
            lap_data=MOCK_LAPS,
            race_control_data=MOCK_RACE_CONTROL,
            overtake_data=MOCK_OVERTAKES,
            pit_data=MOCK_PIT,
            drivers_data=MOCK_DRIVERS,
        )

        # Enrich VER's first radio clip
        ctx = enricher.enrich("2023-09-03T13:32:15.000000+00:00", driver_number=1)

        assert ctx.position == 1
        assert ctx.compound == "MEDIUM"
        assert ctx.lap_number == 14
        assert ctx.gap_to_leader is not None

    def test_enrich_ham(self):
        enricher = ContextEnricher(
            position_data=MOCK_POSITION,
            interval_data=MOCK_INTERVALS,
            stint_data=MOCK_STINTS,
            lap_data=MOCK_LAPS,
            race_control_data=MOCK_RACE_CONTROL,
            overtake_data=MOCK_OVERTAKES,
            pit_data=MOCK_PIT,
            drivers_data=MOCK_DRIVERS,
        )

        ctx = enricher.enrich("2023-09-03T13:45:30.000000+00:00", driver_number=44)
        assert ctx.position is not None
        assert ctx.compound == "SOFT"

    def test_nearby_events(self):
        enricher = ContextEnricher(
            position_data=MOCK_POSITION,
            interval_data=MOCK_INTERVALS,
            stint_data=MOCK_STINTS,
            lap_data=MOCK_LAPS,
            race_control_data=MOCK_RACE_CONTROL,
            overtake_data=MOCK_OVERTAKES,
            pit_data=MOCK_PIT,
            drivers_data=MOCK_DRIVERS,
        )

        # VER's clip at 13:32:15 is within 10s of the yellow flag at 13:32:12
        ctx = enricher.enrich("2023-09-03T13:32:15.000000+00:00", driver_number=1)
        assert len(ctx.events) > 0
        assert any("YELLOW" in e for e in ctx.events)

    def test_nearby_overtakes(self):
        enricher = ContextEnricher(
            position_data=MOCK_POSITION,
            interval_data=MOCK_INTERVALS,
            stint_data=MOCK_STINTS,
            lap_data=MOCK_LAPS,
            race_control_data=MOCK_RACE_CONTROL,
            overtake_data=MOCK_OVERTAKES,
            pit_data=MOCK_PIT,
            drivers_data=MOCK_DRIVERS,
        )

        # VER overtook NOR at 13:32:18 — within 15s of clip at 13:32:15
        ctx = enricher.enrich("2023-09-03T13:32:15.000000+00:00", driver_number=1)
        assert len(ctx.overtakes) > 0
        assert any("VER" in o for o in ctx.overtakes)

    def test_empty_data(self):
        enricher = ContextEnricher(
            position_data=[],
            interval_data=[],
            stint_data=[],
            lap_data=[],
            race_control_data=[],
            overtake_data=[],
            pit_data=[],
            drivers_data=[],
        )

        ctx = enricher.enrich("2023-09-03T13:32:15.000000+00:00", driver_number=1)
        assert ctx.position is None
        assert ctx.compound is None
        assert ctx.events == []

    def test_invalid_date(self):
        enricher = ContextEnricher(
            position_data=MOCK_POSITION,
            interval_data=[],
            stint_data=[],
            lap_data=[],
            race_control_data=[],
            overtake_data=[],
            pit_data=[],
            drivers_data=MOCK_DRIVERS,
        )

        ctx = enricher.enrich("invalid-date", driver_number=1)
        assert ctx.position is None  # Should not crash
