from datetime import date

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

from app.main import app
from app.db.session import engine
from app.models import Child, TaskInstance, TaskKind, TaskStatus, TaskTemplate
from tests.conftest import admin_headers


def _children():
    with Session(engine) as session:
        return session.exec(select(Child).order_by(Child.id)).all()


def test_admin_template_update_syncs_open_dashboard_instances():
    client = TestClient(app)
    headers = admin_headers(client)
    child = _children()[1]
    day = date(2026, 7, 13)

    created = client.post(
        "/api/admin/task-templates",
        headers=headers,
        json={
            "child_id": child.id,
            "slug": "duolingo-test-valerie",
            "title": "Duolingo",
            "kind": "bonus",
            "coin_value": 1,
            "penalty_value": 0,
            "applies_weekdays": "0,1,2,3,4,5,6",
            "active": True,
            "sort_order": 10,
        },
    )
    assert created.status_code == 201
    template_id = created.json()["task_template"]["id"]
    dash = client.get(f"/api/dashboard?date={day.isoformat()}")
    assert dash.status_code == 200
    valerie = next(row for row in dash.json()["children"] if row["child"]["id"] == child.id)
    assert any(task["title"] == "Duolingo" and task["kind"] == "bonus" for task in valerie["tasks"]["open"])

    patched = client.patch(
        f"/api/admin/task-templates/{template_id}",
        headers=headers,
        json={"title": "Duolingo Französisch", "kind": "required", "coin_value": 0, "penalty_value": -1},
    )
    assert patched.status_code == 200
    assert patched.json()["synced_instances"] >= 1

    dash = client.get(f"/api/dashboard?date={day.isoformat()}")
    valerie = next(row for row in dash.json()["children"] if row["child"]["id"] == child.id)
    assert any(task["title"] == "Duolingo Französisch" and task["kind"] == "required" for task in valerie["tasks"]["open"])
    assert not any(task["title"] == "Duolingo" and task["kind"] == "bonus" for task in valerie["tasks"]["open"])


def test_shared_task_template_is_completed_once_for_both_children():
    client = TestClient(app)
    headers = admin_headers(client)
    day = date(2026, 7, 13)
    created = client.post(
        "/api/admin/task-templates",
        headers=headers,
        json={
            "child_id": None,
            "slug": "wuschi-fuettern-test",
            "title": "Wuschi füttern",
            "kind": "required",
            "coin_value": 0,
            "penalty_value": -1,
            "applies_weekdays": "0,1,2,3,4,5,6",
            "active": True,
            "sort_order": 5,
        },
    )
    assert created.status_code == 201
    assert created.json()["task_template"]["scope"] == "shared"

    dash = client.get(f"/api/dashboard?date={day.isoformat()}").json()
    task_ids = []
    for child in dash["children"]:
        match = next(task for task in child["tasks"]["open"] if task["title"] == "Wuschi füttern")
        task_ids.append(match["id"])
    assert len(task_ids) == 2

    done = client.post(f"/api/tasks/{task_ids[0]}/complete", json={"idempotency_key": "wuschi"})
    assert done.status_code == 200

    dash = client.get(f"/api/dashboard?date={day.isoformat()}").json()
    for child in dash["children"]:
        assert any(task["title"] == "Wuschi füttern" and task["status"] == "done" for task in child["tasks"]["done"])

    undone = client.post(f"/api/tasks/{task_ids[0]}/undo", json={"idempotency_key": "wuschi-undo"})
    assert undone.status_code == 200
    dash = client.get(f"/api/dashboard?date={day.isoformat()}").json()
    for child in dash["children"]:
        assert any(task["title"] == "Wuschi füttern" and task["status"] == "open" for task in child["tasks"]["open"])
