"""연합 시나리오 통합 테스트 — 캡처→분류→확인→tasks 등장→risks→dashboard 집계.
LLM은 HeuristicProvider로 고정(conftest, 결정론적). golden case 기준.
"""

GOLDEN_RAW = "다음 주에 한국 놀러가는 비행기 티켓 사기"


def _flatten(nodes):
    out = []
    for n in nodes:
        out.append(n)
        out.extend(_flatten(n.get("children", []) or []))
    return out


def test_health(client):
    assert client.get("/api/health").json() == {"status": "ok"}


def test_capture_classifies_to_task_life_travel(client):
    """① 캡처 → 분류: 비행기 티켓 = 작업 / life / 개인 › 여행 — 한국"""
    r = client.post("/api/inbox/capture", json={"kind": "text", "raw": GOLDEN_RAW})
    assert r.status_code == 200
    c = r.json()["classification"]
    assert c["type"] == "task"
    assert c["sphere"] == "life"
    assert "여행" in c["proj_label"] and "한국" in c["proj_label"]
    assert "작업" in c["reason"]
    assert 0.0 <= c["confidence"] <= 1.0
    assert r.json()["item"]["status"] == "classified"


def test_confirm_materializes_into_task_tree(client):
    """① 확인(실체화): confirm 시 task 생성 + tasks 트리·life 필터에 등장"""
    cap = client.post("/api/inbox/capture", json={"kind": "text", "raw": GOLDEN_RAW}).json()
    item_id = cap["item"]["id"]
    confirmed = client.post(f"/api/inbox/{item_id}/confirm").json()
    new_task_id = confirmed["task"]["id"]
    assert new_task_id

    inbox = client.get("/api/inbox").json()
    target = next(i for i in inbox if i["id"] == item_id)
    assert target["status"] == "confirmed"
    assert target["materialized_task_id"] == new_task_id

    life = client.get("/api/tasks", params={"area": "life"}).json()
    flat = _flatten(life)
    created = next(t for t in flat if t["id"] == new_task_id)
    assert created["project_id"] == "life-trip"
    assert "비행기 티켓" in created["title"]
    assert created["status"] == "todo"
    assert "가격 추적" in created["notes"]


def test_confirm_idempotent(client):
    """confirm 두 번 호출 — 동일 materialized_task_id, 중복 task 생성 금지"""
    cap = client.post("/api/inbox/capture", json={"kind": "text", "raw": GOLDEN_RAW}).json()
    iid = cap["item"]["id"]
    first = client.post(f"/api/inbox/{iid}/confirm").json()
    first_tid = first["task"]["id"]
    # 두 번째 confirm: 이미 confirmed → task 미생성(없음), materialized_task_id 유지
    second = client.post(f"/api/inbox/{iid}/confirm").json()
    assert second["task"] is None
    inbox = {i["id"]: i for i in client.get("/api/inbox").json()}
    assert inbox[iid]["materialized_task_id"] == first_tid


def test_risk_recompute_after_task_change(client):
    """② 작업 데이터 → 리스크 레이더 자동 계산(최대 3건, TODAY=8)"""
    risks = client.get("/api/risks", params={"area": "work"}).json()
    assert len(risks) <= 3
    kinds = [r["kind"] for r in risks]
    assert "지연 위험" in kinds
    delay = next(r for r in risks if r["kind"] == "지연 위험")
    assert delay["tone"] == "coral" and delay["icon"] == "clock"
    if "의존성" in kinds:
        dep = next(r for r in risks if r["kind"] == "의존성")
        assert dep["tone"] == "violet" and dep["icon"] == "link"


def test_risk_disappears_when_done(client):
    """k1(분기 리포트)을 done 으로 PATCH 후 → 지연 위험에서 k1 사라짐(재계산)"""
    before = client.get("/api/risks", params={"area": "work"}).json()
    delay_before = next((r for r in before if r["kind"] == "지연 위험"), None)
    assert delay_before and delay_before["task_id"] == "k1"
    client.patch("/api/tasks/k1", json={"status": "done"})
    after = client.get("/api/risks", params={"area": "work"}).json()
    delay_after = next((r for r in after if r["kind"] == "지연 위험"), None)
    # k1 이 done → 지연 위험이 없거나 다른 작업으로 바뀜(k1 아님)
    assert delay_after is None or delay_after["task_id"] != "k1"


def test_dashboard_aggregates_tasks_inbox_approvals(client):
    """③ 대시보드 집계 — 작업/인박스/결재함 요약 + 배지"""
    cap = client.post("/api/inbox/capture", json={"kind": "text", "raw": GOLDEN_RAW}).json()
    client.post(f"/api/inbox/{cap['item']['id']}/confirm")

    d = client.get("/api/dashboard").json()
    assert "user" in d and d["user"]["name"]
    assert "briefing" in d and "schedule" in d
    assert "task_summary" in d and "goals" in d
    assert "approvals_summary" in d and "inbox_recent" in d
    assert "open_count" in d["task_summary"] and "items" in d["task_summary"]
    assert len(d["approvals_summary"]) <= 3
    assert set(d["badges"]) == {"appr", "task", "noti"}
    assert isinstance(d["inbox_recent"], list)
