"""Tests for schedule/calendar support."""

import httpx
import pytest

from basecamp_mcp.server import _filter_entries_by_date, _summarize_schedule_entry
from .conftest import BASE_URL, make_project, make_schedule_entry


# ── Summarizer unit tests ────────────────────────────────────────


def test_summarize_schedule_entry():
    entry = make_schedule_entry(
        id=5,
        summary="Weekly Sync",
        starts_at="2026-03-25T14:00:00.000Z",
        ends_at="2026-03-25T15:00:00.000Z",
        participants=[{"name": "Alice"}, {"name": "Bob"}],
        comments_count=3,
    )
    result = _summarize_schedule_entry(entry)

    assert result["id"] == 5
    assert result["summary"] == "Weekly Sync"
    assert result["starts_at"] == "2026-03-25T14:00:00.000Z"
    assert result["ends_at"] == "2026-03-25T15:00:00.000Z"
    assert result["all_day"] is False
    assert result["creator"] == "Jacob Filer"
    assert result["participants"] == ["Alice", "Bob"]
    assert result["comments_count"] == 3
    assert "recurrence" not in result


def test_summarize_schedule_entry_with_recurrence():
    recurrence = {"frequency": "weekly", "days": ["Monday"], "hour": 9, "minute": 0}
    entry = make_schedule_entry(id=6, recurrence_schedule=recurrence)
    result = _summarize_schedule_entry(entry)

    assert result["recurrence"] == recurrence


# ── Client method tests ──────────────────────────────────────────


@pytest.mark.asyncio
async def test_list_schedule_entries(client, mock_api):
    entries = [
        make_schedule_entry(id=1, summary="Standup"),
        make_schedule_entry(id=2, summary="Retro"),
    ]
    mock_api.get(f"{BASE_URL}/buckets/1/schedules/100/entries.json").mock(
        return_value=httpx.Response(200, json=entries)
    )

    result = await client.list_schedule_entries(1, 100)
    assert len(result) == 2
    assert result[0]["summary"] == "Standup"
    assert result[1]["summary"] == "Retro"


@pytest.mark.asyncio
async def test_list_schedule_entries_empty(client, mock_api):
    mock_api.get(f"{BASE_URL}/buckets/1/schedules/100/entries.json").mock(
        return_value=httpx.Response(200, json=[])
    )

    result = await client.list_schedule_entries(1, 100)
    assert result == []


@pytest.mark.asyncio
async def test_get_schedule_entry(client, mock_api):
    entry = make_schedule_entry(id=42, summary="All Hands")
    mock_api.get(f"{BASE_URL}/buckets/1/schedule_entries/42.json").mock(
        return_value=httpx.Response(200, json=entry)
    )

    result = await client.get_schedule_entry(1, 42)
    assert result is not None
    assert result["summary"] == "All Hands"


@pytest.mark.asyncio
async def test_get_schedule_entry_not_found(client, mock_api):
    mock_api.get(f"{BASE_URL}/buckets/1/schedule_entries/999.json").mock(
        return_value=httpx.Response(404)
    )

    result = await client.get_schedule_entry(1, 999)
    assert result is None


# ── Date filtering tests ─────────────────────────────────────────


def test_filter_entries_by_date():
    entries = [
        make_schedule_entry(
            id=1,
            starts_at="2026-03-15T09:00:00.000Z",
            ends_at="2026-03-15T10:00:00.000Z",
        ),
        make_schedule_entry(
            id=2,
            starts_at="2026-03-20T09:00:00.000Z",
            ends_at="2026-03-20T10:00:00.000Z",
        ),
        make_schedule_entry(
            id=3,
            starts_at="2026-03-25T09:00:00.000Z",
            ends_at="2026-03-25T10:00:00.000Z",
        ),
        make_schedule_entry(
            id=4,
            starts_at="2026-04-01T09:00:00.000Z",
            ends_at="2026-04-01T10:00:00.000Z",
        ),
    ]

    filtered = _filter_entries_by_date(
        entries, starts_after="2026-03-18", ends_before="2026-03-30"
    )

    assert len(filtered) == 2
    assert filtered[0]["id"] == 2
    assert filtered[1]["id"] == 3


def test_filter_entries_missing_starts_at():
    """Entries without starts_at are excluded during date filtering."""
    entries = [
        {"id": 1, "summary": "No date"},
        make_schedule_entry(id=2, starts_at="2026-03-20T09:00:00.000Z"),
    ]

    filtered = _filter_entries_by_date(entries, starts_after="2026-03-01")

    assert len(filtered) == 1
    assert filtered[0]["id"] == 2


# ── Search integration tests ────────────────────────────────────


@pytest.mark.asyncio
async def test_search_project_includes_schedule(client, mock_api):
    project = make_project(project_id=1, schedule_id=100)

    # Mock message board — empty
    mock_api.get(f"{BASE_URL}/buckets/1/message_boards/10/messages.json").mock(
        return_value=httpx.Response(200, json=[])
    )

    # Mock recordings for docs/uploads — empty
    mock_api.get(f"{BASE_URL}/projects/recordings.json").mock(
        return_value=httpx.Response(200, json=[])
    )

    # Mock todoset — empty
    mock_api.get(f"{BASE_URL}/buckets/1/todosets/20/todolists.json").mock(
        return_value=httpx.Response(200, json=[])
    )

    # Mock schedule entries — one match
    mock_api.get(f"{BASE_URL}/buckets/1/schedules/100/entries.json").mock(
        return_value=httpx.Response(
            200,
            json=[
                make_schedule_entry(id=1, summary="Team Planning Meeting"),
                make_schedule_entry(id=2, summary="Lunch Break"),
            ],
        )
    )

    result = await client.search_project(1, "planning", project=project)

    assert "schedule_entries" in result
    assert len(result["schedule_entries"]) == 1
    assert result["schedule_entries"][0]["summary"] == "Team Planning Meeting"


@pytest.mark.asyncio
async def test_list_schedule_no_dock(client, mock_api):
    """Project with no schedule dock returns empty from search."""
    project = make_project(project_id=1)
    # Remove schedule from dock
    project["dock"] = [d for d in project["dock"] if d["name"] != "schedule"]

    mock_api.get(f"{BASE_URL}/buckets/1/message_boards/10/messages.json").mock(
        return_value=httpx.Response(200, json=[])
    )
    mock_api.get(f"{BASE_URL}/projects/recordings.json").mock(
        return_value=httpx.Response(200, json=[])
    )
    mock_api.get(f"{BASE_URL}/buckets/1/todosets/20/todolists.json").mock(
        return_value=httpx.Response(200, json=[])
    )

    result = await client.search_project(1, "meeting", project=project)
    assert result["schedule_entries"] == []
