"""ORCH-059 TC-01/02/03: resolver registration of the dedicated "Confirm Deploy"
status and its fail-closed absence in fallback environments.

Contract (AC-1, AC-7):
  * TC-01 — _PLANE_NAME_TO_KEY maps the board name "Confirm Deploy" to the logical
    key "confirm_deploy".
  * TC-02 — get_project_states for an ORCH-like project (Plane API mocked to
    include a "Confirm Deploy" state) returns a NON-empty uuid under
    "confirm_deploy", distinct from "approved".
  * TC-03 — fail-closed: when the status is absent (API fallback to
    _DEFAULT_STATES / unreachable Plane), the key is simply missing and a .get
    access yields None WITHOUT raising — the confirm-deploy branch never activates.
"""

import os
import tempfile

import pytest

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

import src.plane_sync as plane_sync  # noqa: E402
from src.plane_sync import (  # noqa: E402
    _PLANE_NAME_TO_KEY,
    _DEFAULT_STATES,
    get_project_states,
    reload_project_states,
)


@pytest.fixture(autouse=True)
def fresh_cache():
    reload_project_states()
    yield
    reload_project_states()


# ---------------------------------------------------------------------------
# TC-01: name -> key mapping is registered
# ---------------------------------------------------------------------------
def test_tc01_confirm_deploy_name_to_key_mapping():
    assert _PLANE_NAME_TO_KEY.get("Confirm Deploy") == "confirm_deploy"


def test_tc01_confirm_deploy_not_in_default_states():
    """Fail-closed by construction: NO fallback UUID exists for confirm_deploy, so
    enduro / API-fallback environments never resolve a (wrong) deploy trigger."""
    assert "confirm_deploy" not in _DEFAULT_STATES


# ---------------------------------------------------------------------------
# TC-02: live API resolves a real, distinct uuid for an ORCH-like project
# ---------------------------------------------------------------------------
def test_tc02_get_project_states_resolves_confirm_deploy(monkeypatch):
    confirm_uuid = "cfd00000-0000-0000-0000-000000000059"
    approved_uuid = "a519a341-dada-4a91-8910-7604f82b79c5"

    class _Resp:
        def raise_for_status(self):
            pass

        def json(self):
            return {
                "results": [
                    {"name": "In Progress", "id": "b873d9eb-993c-48cd-97ac-99a9b1623967"},
                    {"name": "Approved", "id": approved_uuid},
                    {"name": "Confirm Deploy", "id": confirm_uuid},
                ]
            }

    monkeypatch.setattr(plane_sync.httpx, "get", lambda *a, **k: _Resp())

    states = get_project_states("orch-project-uuid")
    assert states.get("confirm_deploy") == confirm_uuid
    # Distinct gestures: confirm-deploy must NOT alias the human "Approved" gate.
    assert states["confirm_deploy"] != states["approved"]


# ---------------------------------------------------------------------------
# TC-03: fail-closed when the status is absent (API fallback / unreachable)
# ---------------------------------------------------------------------------
def test_tc03_fail_closed_when_api_unreachable(monkeypatch):
    """A Plane outage -> get_project_states falls back to _DEFAULT_STATES, which
    has no confirm_deploy key. .get must yield None, never raise."""

    def _boom(*a, **k):
        raise RuntimeError("plane down")

    monkeypatch.setattr(plane_sync.httpx, "get", _boom)

    states = get_project_states("any-project-uuid")
    # No KeyError, branch never activates.
    assert states.get("confirm_deploy") is None
    # The human gate "Approved" still resolves (fallback is intact).
    assert states.get("approved") == _DEFAULT_STATES["approved"]


def test_tc03_fail_closed_when_status_not_on_board(monkeypatch):
    """Project whose board lacks "Confirm Deploy": the key is filled by NEITHER the
    API loop NOR the _DEFAULT_STATES backfill -> absent -> fail-closed."""

    class _Resp:
        def raise_for_status(self):
            pass

        def json(self):
            return {
                "results": [
                    {"name": "In Progress", "id": "b873d9eb-993c-48cd-97ac-99a9b1623967"},
                    {"name": "Approved", "id": "a519a341-dada-4a91-8910-7604f82b79c5"},
                ]
            }

    monkeypatch.setattr(plane_sync.httpx, "get", lambda *a, **k: _Resp())

    states = get_project_states("board-without-confirm")
    assert states.get("confirm_deploy") is None
    assert states.get("approved") == "a519a341-dada-4a91-8910-7604f82b79c5"
