"""ORCH-066: To Analyse resume semantics (F-1 status-only model).

`handle_status_start` forks on (existing task?) + (active job?):

  * TC-02 (AC-2, BR-11) — an EXISTING task with NO active job + To Analyse ->
    RELAUNCH the current stage's agent (the analyst resumes from Needs Input);
    NO second task is created; the issue is re-indicated `Analysis`.
  * TC-04 (AC-4)        — an EXISTING task WITH an active job + To Analyse ->
    busy-guard: NO relaunch (no double launch).

handle_status_start is exercised directly; enqueue_job + Plane side-effects are
mocked. A real isolated sqlite DB backs get_task_by_plane_id / the job guard.
"""

import os
import tempfile

import pytest

_test_db = os.path.join(tempfile.gettempdir(), "test_orch066_to_analyse_resume.db")
os.environ["ORCH_DB_PATH"] = _test_db
os.environ["ORCH_REPOS_DIR"] = tempfile.gettempdir()
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")
os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token")

from unittest.mock import patch, AsyncMock, MagicMock  # noqa: E402

import src.db as _db  # noqa: E402
from src.db import init_db, get_db  # noqa: E402
from src.webhooks.plane import handle_status_start  # noqa: E402


@pytest.fixture(autouse=True)
def fresh_db(monkeypatch):
    monkeypatch.setattr(_db.settings, "db_path", _test_db)
    if os.path.exists(_test_db):
        os.unlink(_test_db)
    init_db()
    yield
    if os.path.exists(_test_db):
        os.unlink(_test_db)


def _make_task(plane_id="resume-1", stage="analysis", repo="enduro-trails",
               branch="feature/ET-001-x", wi="ET-001"):
    conn = get_db()
    cur = conn.execute(
        "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage) "
        "VALUES (?, ?, ?, ?, ?)",
        (plane_id, wi, repo, branch, stage),
    )
    tid = cur.lastrowid
    conn.commit()
    conn.close()
    return tid


def _count(plane_id):
    conn = get_db()
    n = conn.execute("SELECT COUNT(*) FROM tasks WHERE plane_id=?", (plane_id,)).fetchone()[0]
    conn.close()
    return n


# ---------------------------------------------------------------------------
# TC-02 (AC-2 / BR-11): existing task, no active job -> RELAUNCH (resume), no dup.
# ---------------------------------------------------------------------------
@pytest.mark.asyncio
async def test_tc02_to_analyse_resume_relaunches_analyst_no_duplicate():
    _make_task("resume-1", stage="analysis")
    data = {"id": "resume-1", "state": {"id": "ip-uuid", "name": "To Analyse"}}

    with patch("src.webhooks.plane.enqueue_job", return_value=7) as mock_enqueue, \
         patch("src.webhooks.plane.start_pipeline", new_callable=AsyncMock) as mock_start, \
         patch("src.plane_sync.add_comment", MagicMock()), \
         patch("src.plane_sync.set_issue_analysis") as mock_analysis:
        await handle_status_start(data, "proj-1")

    # No new pipeline start (it is a resume, not a fresh task).
    mock_start.assert_not_called()
    assert _count("resume-1") == 1               # NO duplicate task
    # The current stage's agent (analyst) was relaunched exactly once.
    assert mock_enqueue.call_count == 1
    assert mock_enqueue.call_args.args[0] == "analyst"
    # AC-3: the resumed analysis stage is re-indicated as Analysis.
    mock_analysis.assert_called_once_with("ET-001")


# ---------------------------------------------------------------------------
# TC-04 (AC-4): existing task WITH active job -> busy-guard, NO relaunch.
# ---------------------------------------------------------------------------
@pytest.mark.asyncio
async def test_tc04_to_analyse_with_active_job_does_not_relaunch():
    tid = _make_task("resume-2", stage="analysis")
    # Seed an active (queued) job so has_active_job_for_task reports busy.
    conn = get_db()
    conn.execute(
        "INSERT INTO jobs (agent, repo, task_id, status) VALUES (?, ?, ?, 'queued')",
        ("analyst", "enduro-trails", tid),
    )
    conn.commit()
    conn.close()

    data = {"id": "resume-2", "state": {"id": "ip-uuid", "name": "To Analyse"}}
    with patch("src.webhooks.plane.enqueue_job", return_value=9) as mock_enqueue, \
         patch("src.webhooks.plane.start_pipeline", new_callable=AsyncMock) as mock_start, \
         patch("src.plane_sync.add_comment", MagicMock()), \
         patch("src.plane_sync.set_issue_analysis") as mock_analysis:
        await handle_status_start(data, "proj-1")

    mock_start.assert_not_called()
    mock_enqueue.assert_not_called()   # busy-guard held: NO double launch
    mock_analysis.assert_not_called()
    assert _count("resume-2") == 1
