from datetime import date, datetime
from zoneinfo import ZoneInfo

from fastapi.testclient import TestClient
from sqlmodel import Session, select

from app.db.session import engine, init_db
from app.main import app
from app.models import Child, ScheduleBlock, ScheduleDay, TaskInstance
from app.services.dashboard import child_timeline, get_afternoon_leave_home_time, get_first_afternoon_school_block, get_next_external_activity


def child_by_name(session: Session, name: str) -> Child:
    return session.exec(select(Child).where(Child.name == name)).one()

def test_dashboard_contains_children_tasks_timeline_and_coins():
    init_db()
    with TestClient(app) as client:
        response = client.get("/api/dashboard?date=2026-06-15")

    assert response.status_code == 200
    payload = response.json()
    assert payload["date"] == "2026-06-15"
    assert [item["child"]["name"] for item in payload["children"]] == ["Emilia", "Valerie"]
    first = payload["children"][0]
    assert first["timeline"]["segments"]
    assert "progress_percent" in first["timeline"]
    assert first["timeline"]["current_step"]
    assert any(task["title"] == "Musikinstrument üben" for task in first["tasks"]["open"])
    assert first["tasks"]["open"]
    assert set(first["coin_summary"]) == {"posted", "reserved", "available"}
    assert first["coin_summary"]["available"] == first["coin_summary"]["posted"] - first["coin_summary"]["reserved"]


def test_dashboard_lazy_task_generation_is_idempotent():
    init_db()
    target = date(2026, 6, 16)
    with TestClient(app) as client:
        first = client.get(f"/api/dashboard?date={target.isoformat()}")
        second = client.get(f"/api/dashboard?date={target.isoformat()}")

    assert first.status_code == 200
    assert second.status_code == 200
    with Session(engine) as session:
        tasks = session.exec(select(TaskInstance).where(TaskInstance.task_date == target)).all()
    assert len(tasks) == 8


def test_dashboard_weekend_mode():
    init_db()
    with TestClient(app) as client:
        response = client.get("/api/dashboard?date=2026-06-20")

    assert response.status_code == 200
    modes = [item["timeline"]["mode"] for item in response.json()["children"]]
    assert modes == ["weekend", "weekend"]


def test_dashboard_morning_uses_family_routine_until_ablaufen():
    init_db()
    target = date(2026, 6, 15)
    with Session(engine) as session:
        child = child_by_name(session, "Emilia")
        timeline = child_timeline(session, child, target, "Europe/Zurich", now=datetime(2026, 6, 15, 7, 0, tzinfo=ZoneInfo("Europe/Zurich")))

    labels = [step["shortLabel"] for step in timeline["timelineSteps"]]
    assert labels == ["Auf", "Frühstück", "Zähne", "Los", "Schule"]
    leave = next(step for step in timeline["timelineSteps"] if step["key"] == "leave_home")
    school_start = next(step for step in timeline["timelineSteps"] if step["key"] == "school_start")
    assert leave["kind"] == "range"
    assert leave["endTime"] == school_start["time"]
    assert school_start["kind"] == "milestone"
