"""ORCH-067 — Group A: bump is the DEFAULT tracker mode (AC-1..AC-4, AC-15).

The default flipped edit -> bump: out of the box the live card is re-created at
the BOTTOM of the chat (delete old + send new silent + repoint id), one card per
task. edit stays available via ORCH_TRACKER_MODE=edit. Network is isolated: the
low-level send/edit/delete helpers are patched per case; the DB is a temp SQLite.

Test ids TC-01..TC-04 + TC-17 from 04-test-plan.yaml.
"""

import os
import tempfile

os.environ.setdefault("ORCH_PLANE_API_TOKEN", "test-token")
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")

_test_db = os.path.join(tempfile.gettempdir(), "test_orchestrator_bump_default.db")
os.environ["ORCH_DB_PATH"] = _test_db

import pytest  # noqa: E402

import src.db as db_module  # noqa: E402
from src.config import Settings  # noqa: E402
from src.db import (  # noqa: E402
    init_db, get_db, get_tracker_message_id, set_tracker_message_id,
)
from src import notifications as N  # noqa: E402


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


def _mk_task(stage="development", wid="ORCH-067"):
    conn = get_db()
    cur = conn.execute(
        "INSERT INTO tasks (plane_id, work_item_id, repo, branch, stage, title) "
        "VALUES (?, ?, ?, ?, ?, ?)",
        ("p1", wid, "orchestrator", "feature/ORCH-067-x", stage, "bump default"),
    )
    tid = cur.lastrowid
    conn.commit()
    conn.close()
    return tid


# --------------------------------------------------------------------------- #
# TC-01 / AC-1 — default tracker_mode == "bump"
# --------------------------------------------------------------------------- #
def test_tc01_default_tracker_mode_is_bump(monkeypatch):
    monkeypatch.delenv("ORCH_TRACKER_MODE", raising=False)
    assert Settings().tracker_mode == "bump"


# --------------------------------------------------------------------------- #
# TC-02 / AC-2, AC-15 — repeat update: delete(old) -> send(silent) -> repoint
# --------------------------------------------------------------------------- #
def test_tc02_repeat_delete_send_silent_repoint(monkeypatch):
    # No env -> resolves to the new bump default (no explicit mode pin).
    monkeypatch.setattr(N._get_settings(), "tracker_mode", "bump", raising=False)
    tid = _mk_task()
    set_tracker_message_id(tid, 100)

    order = []
    monkeypatch.setattr(N, "delete_telegram",
                        lambda mid: order.append(("delete", mid)) or True)
    monkeypatch.setattr(N, "send_telegram",
                        lambda text, disable_notification=False:
                        order.append(("send", disable_notification)) or 200)

    N.update_task_tracker(tid)

    # delete(old) strictly before send; the new card is SILENT (disable=True).
    assert order == [("delete", 100), ("send", True)]
    assert get_tracker_message_id(tid) == 200  # one card -> repointed


# --------------------------------------------------------------------------- #
# TC-03 / AC-3 — transient send None must NOT wipe the pointer / duplicate
# --------------------------------------------------------------------------- #
def test_tc03_send_none_keeps_pointer_no_dupe(monkeypatch):
    monkeypatch.setattr(N._get_settings(), "tracker_mode", "bump", raising=False)
    tid = _mk_task()
    set_tracker_message_id(tid, 100)

    sends = []
    monkeypatch.setattr(N, "delete_telegram", lambda mid: True)
    monkeypatch.setattr(N, "send_telegram",
                        lambda text, disable_notification=False:
                        sends.append(1) or None)

    N.update_task_tracker(tid)  # must not raise

    assert len(sends) == 1            # exactly one (failed) attempt, no retry
    assert get_tracker_message_id(tid) == 100  # pointer preserved, not None


# --------------------------------------------------------------------------- #
# TC-04 / AC-4 — edit mode still reachable via env -> editMessageText path
# --------------------------------------------------------------------------- #
def test_tc04_edit_mode_still_available(monkeypatch):
    monkeypatch.setattr(N._get_settings(), "tracker_mode", "edit", raising=False)
    tid = _mk_task()
    set_tracker_message_id(tid, 777)

    edited = {}
    monkeypatch.setattr(N, "edit_telegram",
                        lambda mid, text: edited.update(mid=mid) or N.EDIT_OK)
    monkeypatch.setattr(
        N, "send_telegram",
        lambda *a, **k: (_ for _ in ()).throw(
            AssertionError("edit mode must not send when edit succeeds")),
    )

    N.update_task_tracker(tid)
    assert edited["mid"] == 777  # edited in place, no new card


def test_tc04b_edit_mode_resolution_case_insensitive(monkeypatch):
    """Anything other than 'bump' resolves to edit (e.g. 'EDIT')."""
    monkeypatch.setattr(N._get_settings(), "tracker_mode", "EDIT", raising=False)
    tid = _mk_task()
    set_tracker_message_id(tid, 5)
    edited = {}
    monkeypatch.setattr(N, "edit_telegram",
                        lambda mid, text: edited.update(mid=mid) or N.EDIT_OK)
    monkeypatch.setattr(N, "send_telegram",
                        lambda *a, **k: (_ for _ in ()).throw(
                            AssertionError("should edit, not send")))
    N.update_task_tracker(tid)
    assert edited["mid"] == 5


# --------------------------------------------------------------------------- #
# TC-17 / AC-15 — first bump call: NO delete, silent send, id stored
# --------------------------------------------------------------------------- #
def test_tc17_first_call_silent_no_delete(monkeypatch):
    monkeypatch.setattr(N._get_settings(), "tracker_mode", "bump", raising=False)
    tid = _mk_task(stage="analysis")

    sends = []
    monkeypatch.setattr(N, "send_telegram",
                        lambda text, disable_notification=False:
                        sends.append(disable_notification) or 555)
    monkeypatch.setattr(N, "delete_telegram",
                        lambda mid: (_ for _ in ()).throw(
                            AssertionError("delete must not run on first call")))

    N.update_task_tracker(tid)

    assert sends == [True]                      # exactly one SILENT send
    assert get_tracker_message_id(tid) == 555   # id stored
