"""Tests for the daily planner time-block algorithm."""
from datetime import UTC, datetime

from dobby.core.planner import PlannerEngine, PlannerPrefs
from dobby.models import DailyPlan, TimeBlock


def test_time_block_creation():
    block = TimeBlock(
        start=datetime(2026, 3, 25, 9, 0, tzinfo=UTC),
        end=datetime(2026, 3, 25, 10, 30, tzinfo=UTC),
        block_type="focus",
        title="SPARE - Deep Work",
        project="spare",
        source="planner",
    )
    assert block.duration_minutes == 90
    assert block.block_type == "focus"


def test_time_block_to_dict_roundtrip():
    block = TimeBlock(
        start=datetime(2026, 3, 25, 9, 0, tzinfo=UTC),
        end=datetime(2026, 3, 25, 10, 30, tzinfo=UTC),
        block_type="focus",
        title="SPARE - Deep Work",
        project="spare",
    )
    d = block.to_dict()
    restored = TimeBlock.from_dict(d)
    assert restored.duration_minutes == 90
    assert restored.title == "SPARE - Deep Work"
    assert restored.project == "spare"


def test_daily_plan_creation():
    plan = DailyPlan(
        date="2026-03-25",
        timezone="America/Los_Angeles",
        blocks=[],
        calendar_events=[],
    )
    assert plan.id.startswith("plan-")
    assert plan.date == "2026-03-25"


def test_daily_plan_to_dict_roundtrip():
    block = TimeBlock(
        start=datetime(2026, 3, 25, 9, 0, tzinfo=UTC),
        end=datetime(2026, 3, 25, 10, 30, tzinfo=UTC),
        block_type="focus",
        title="Test",
    )
    plan = DailyPlan(
        date="2026-03-25",
        timezone="America/Los_Angeles",
        blocks=[block],
        calendar_events=[{"summary": "meeting"}],
    )
    d = plan.to_dict()
    restored = DailyPlan.from_dict(d)
    assert len(restored.blocks) == 1
    assert restored.blocks[0].duration_minutes == 90
    assert restored.calendar_events == [{"summary": "meeting"}]


# ---------------------------------------------------------------------------
# Algorithm tests (PlannerEngine)
# ---------------------------------------------------------------------------


def test_planner_prefs_defaults():
    prefs = PlannerPrefs()
    assert prefs.work_start == "09:00"
    assert prefs.work_end == "18:00"
    assert prefs.min_focus_minutes == 60
    assert prefs.break_minutes == 15
    assert prefs.lunch_start == "12:00"
    assert prefs.lunch_minutes == 60


def test_generate_blocks_empty_calendar():
    prefs = PlannerPrefs(
        work_start="09:00", work_end="17:00", min_focus_minutes=90,
        break_minutes=15, lunch_minutes=60,
    )
    engine = PlannerEngine(prefs)
    projects = [
        {"name": "spare", "priority": "high", "weight": 3},
        {"name": "adpo", "priority": "high", "weight": 2},
        {"name": "dobby", "priority": "normal", "weight": 1},
    ]
    blocks = engine.generate_blocks(
        date="2026-03-25", tz_name="America/Los_Angeles",
        calendar_events=[], projects=projects, todos=[],
    )
    types = {b.block_type for b in blocks}
    assert "focus" in types
    assert "lunch" in types
    focus_minutes = sum(b.duration_minutes for b in blocks if b.block_type == "focus")
    assert focus_minutes >= 300


def test_generate_blocks_with_meetings():
    prefs = PlannerPrefs(work_start="09:00", work_end="17:00", min_focus_minutes=60)
    engine = PlannerEngine(prefs)
    meetings = [
        {
            "summary": "STLM",
            "start": {"dateTime": "2026-03-25T10:00:00-07:00"},
            "end": {"dateTime": "2026-03-25T11:00:00-07:00"},
        },
        {
            "summary": "1:1 with advisor",
            "start": {"dateTime": "2026-03-25T14:00:00-07:00"},
            "end": {"dateTime": "2026-03-25T15:00:00-07:00"},
        },
    ]
    blocks = engine.generate_blocks(
        date="2026-03-25", tz_name="America/Los_Angeles",
        calendar_events=meetings,
        projects=[{"name": "spare", "priority": "high", "weight": 1}],
        todos=[],
    )
    meeting_blocks = [b for b in blocks if b.block_type == "meeting"]
    assert len(meeting_blocks) == 2
    focus_blocks = [b for b in blocks if b.block_type == "focus"]
    for fb in focus_blocks:
        for mb in meeting_blocks:
            assert fb.end <= mb.start or fb.start >= mb.end


def test_project_weight_allocation():
    prefs = PlannerPrefs(work_start="09:00", work_end="17:00")
    engine = PlannerEngine(prefs)
    projects = [
        {"name": "spare", "priority": "high", "weight": 3},
        {"name": "dobby", "priority": "low", "weight": 1},
    ]
    blocks = engine.generate_blocks(
        date="2026-03-25", tz_name="America/Los_Angeles",
        calendar_events=[], projects=projects, todos=[],
    )
    spare_mins = sum(b.duration_minutes for b in blocks if b.project == "spare")
    dobby_mins = sum(b.duration_minutes for b in blocks if b.project == "dobby")
    assert spare_mins > dobby_mins
