"""Demand-weighted suggestion backlog tests (STATE-WP-0061)."""
from __future__ import annotations

import pytest

from tests.conftest import create_test_repo, create_test_workplan
from tests.test_capability_requests import _create_domain, _create_topic


async def _create_suggestion(client, **kwargs):
    payload = {
        "domain": "custodian",
        "title": "Issue-core ingestion API key path",
        "description": "OpenBao KV path for issue-core ingestion",
        "origin_ref": "issue-core-ingestion-api-key",
        "base_value": 4.0,
        "job_size": 2.0,
    }
    payload.update(kwargs)
    r = await client.post("/suggestions/", json=payload)
    assert r.status_code == 201, r.text
    return r.json()


@pytest.mark.asyncio
async def test_create_list_and_wsjf_ranking(client):
    await _create_domain(client, "custodian", "Custodian")
    low = await _create_suggestion(
        client,
        title="Low priority path",
        origin_ref="low-priority",
        base_value=1.0,
        job_size=5.0,
    )
    high = await _create_suggestion(
        client,
        title="High priority path",
        origin_ref="high-priority",
        base_value=5.0,
        job_size=1.0,
    )

    r = await client.get("/suggestions/?rank=wsjf")
    assert r.status_code == 200
    ranked = r.json()
    assert ranked[0]["id"] == high["id"]
    assert ranked[0]["wsjf"] > ranked[1]["wsjf"]

    await client.post(
        f"/suggestions/{low['id']}/bump-relevance",
        json={"reason": "hit again", "author": "agent-a"},
    )
    await client.post(
        f"/suggestions/{low['id']}/bump-relevance",
        json={"reason": "hit again", "author": "agent-b"},
    )
    r2 = await client.get(f"/suggestions/{low['id']}")
    assert r2.json()["relevance"] == 2


@pytest.mark.asyncio
async def test_bump_relevance_debounces_duplicate_explicit_bumps(client):
    await _create_domain(client, "custodian", "Custodian")
    suggestion = await _create_suggestion(client)
    first = await client.post(
        f"/suggestions/{suggestion['id']}/bump-relevance",
        json={"reason": "routing gap", "author": "codex"},
    )
    second = await client.post(
        f"/suggestions/{suggestion['id']}/bump-relevance",
        json={"reason": "routing gap", "author": "codex"},
    )
    assert first.status_code == 200
    assert second.status_code == 200
    refreshed = await client.get(f"/suggestions/{suggestion['id']}")
    assert refreshed.json()["relevance"] == 1


@pytest.mark.asyncio
async def test_vet_decline_and_promote_flow(client):
    await _create_domain(client, "custodian", "Custodian")
    topic = await _create_topic(client, "custodian")
    repo = await create_test_repo(client, domain_slug="custodian", slug="state-hub")
    workplan = await create_test_workplan(
        client, repo_id=repo["id"], topic_id=topic["id"], slug="state-wp-0061", title="WP-0061",
    )

    suggestion = await _create_suggestion(
        client,
        workplan_id=workplan["id"],
        title="Promotable gated need",
        origin_ref="promote-me",
    )

    vet = await client.post(
        f"/suggestions/{suggestion['id']}/vet",
        json={"note": "Vetted as requirement", "author": "codex"},
    )
    assert vet.status_code == 200
    assert vet.json()["stage"] == "requirement"

    bad_promote = await client.post(
        f"/suggestions/{suggestion['id']}/promote",
        json={"note": "too early"},
    )
    assert bad_promote.status_code == 200

    promoted = bad_promote.json()
    assert promoted["stage"] == "promoted"
    assert promoted["promoted_task_id"] is not None

    task = await client.get(f"/tasks/{promoted['promoted_task_id']}")
    assert task.status_code == 200
    assert task.json()["title"] == "Promotable gated need"

    fresh = await _create_suggestion(client, title="Decline me", origin_ref="decline-me")
    declined = await client.post(
        f"/suggestions/{fresh['id']}/decline",
        json={"note": "Not needed", "author": "codex"},
    )
    assert declined.status_code == 200
    assert declined.json()["stage"] == "declined"

    illegal = await client.post(
        f"/suggestions/{fresh['id']}/vet",
        json={"note": "too late"},
    )
    assert illegal.status_code == 409


@pytest.mark.asyncio
async def test_next_steps_surfaces_and_bumps_suggestions(client):
    await _create_domain(client, "custodian", "Custodian")
    await _create_suggestion(client, title="Surfaced need", origin_ref="surfaced-need")
    before = await client.get("/suggestions/?origin_ref=surfaced-need")
    # no filter by origin_ref on list - get all and find
    all_items = await client.get("/suggestions/")
    item = next(i for i in all_items.json() if i["origin_ref"] == "surfaced-need")
    assert item["relevance"] == 0

    steps = await client.get("/state/next_steps")
    assert steps.status_code == 200
    payload = steps.json()
    assert any(s["type"] == "open_suggestion" for s in payload)

    after = await client.get(f"/suggestions/{item['id']}")
    assert after.json()["relevance"] >= 1


@pytest.mark.asyncio
async def test_summary_includes_ranked_suggestions(client):
    await _create_domain(client, "custodian", "Custodian")
    await _create_suggestion(client, title="Summary ranked", origin_ref="summary-ranked")
    summary = await client.get("/state/summary")
    assert summary.status_code == 200
    data = summary.json()
    assert "ranked_suggestions" in data
    assert any(s["origin_ref"] == "summary-ranked" for s in data["ranked_suggestions"])