"""Regression tests for Client.Python-037 and Client.Python-038.

Client.Python-037: ``pyproject.toml`` description must not contain "scaffold".
Client.Python-038: ``advise-supervisory`` CLI subcommand must have coverage
                   (registration smoke test + happy-path command-shape test).

Tests are TDD-first — written before the fix and expected to pass once the
source change lands.
"""

from __future__ import annotations

import json
from pathlib import Path
from typing import Any

from click.testing import CliRunner

from zb_mom_ww_mxgateway import ClientOptions, GatewayClient
from zb_mom_ww_mxgateway.generated import mxaccess_gateway_pb2 as pb
from zb_mom_ww_mxgateway_cli.commands import main


# ---------------------------------------------------------------------------
# Client.Python-037 — pyproject.toml description must not contain "scaffold".
# ---------------------------------------------------------------------------


def test_pyproject_description_does_not_contain_scaffold() -> None:
    """The ``description`` field in ``pyproject.toml`` must not include the
    word "scaffold" — a regression of Client.Python-001 that re-entered the
    file at the package-rename commit.
    """

    pyproject = (
        Path(__file__).resolve().parent.parent / "pyproject.toml"
    ).read_text(encoding="utf-8")

    # Find the description line and assert "scaffold" is absent.
    for line in pyproject.splitlines():
        stripped = line.strip()
        if stripped.startswith("description"):
            assert "scaffold" not in stripped.lower(), (
                f"pyproject.toml description must not contain 'scaffold': {stripped!r}"
            )
            return

    raise AssertionError("pyproject.toml has no 'description' line")


# ---------------------------------------------------------------------------
# Client.Python-038 — advise-supervisory must be registered + have a happy path.
# ---------------------------------------------------------------------------


def test_advise_supervisory_is_registered() -> None:
    """``advise-supervisory`` must be a registered subcommand of ``main``.

    A ``--help`` invocation must exit 0 and the help text must include the
    required options (--server-handle and --item-handle).
    """

    runner = CliRunner()
    result = runner.invoke(main, ["advise-supervisory", "--help"])

    assert result.exit_code == 0, result.output
    assert "--server-handle" in result.output
    assert "--item-handle" in result.output


# --------------- fake-stub infrastructure (mirrors test_review_findings_022_to_026) ----


class _FakeUnary:
    def __init__(self, replies: list[Any]) -> None:
        self.replies = replies
        self.requests: list[Any] = []
        self.metadata: tuple[tuple[str, str], ...] | None = None

    async def __call__(self, request: Any, *, metadata: tuple[tuple[str, str], ...]) -> Any:
        self.requests.append(request)
        self.metadata = metadata
        return self.replies.pop(0)


class _FakeStub:
    def __init__(self) -> None:
        self.open_session = _FakeUnary(
            [
                pb.OpenSessionReply(
                    session_id="session-1",
                    protocol_status=pb.ProtocolStatus(code=pb.PROTOCOL_STATUS_CODE_OK),
                ),
            ],
        )
        self.invoke = _FakeUnary([])
        self.OpenSession = self.open_session
        self.Invoke = self.invoke

    def set_invoke_replies(self, replies: list[Any]) -> None:
        self.invoke.replies = replies


def _install_fake_connect(monkeypatch: Any, stub: _FakeStub) -> None:
    """Patch ``GatewayClient.connect`` so the CLI uses the supplied fake stub."""

    real_connect = GatewayClient.connect

    @classmethod  # type: ignore[misc]
    async def _spy_connect(cls: Any, options: ClientOptions, **kwargs: Any) -> GatewayClient:
        return await real_connect(options, stub=stub)

    monkeypatch.setattr(GatewayClient, "connect", _spy_connect)


def test_cli_advise_supervisory_happy_path(monkeypatch: Any) -> None:
    """``advise-supervisory`` must forward server_handle and item_handle in an
    ``MX_COMMAND_KIND_ADVISE_SUPERVISORY`` ``MxCommand``.

    Pattern mirrors ``test_cli_acknowledge_alarm_happy_path`` in
    ``test_review_findings_022_to_026.py``.
    """

    stub = _FakeStub()
    stub.set_invoke_replies(
        [
            pb.MxCommandReply(
                session_id="session-1",
                kind=pb.MX_COMMAND_KIND_ADVISE_SUPERVISORY,
                protocol_status=pb.ProtocolStatus(code=pb.PROTOCOL_STATUS_CODE_OK),
            ),
        ],
    )
    _install_fake_connect(monkeypatch, stub)

    runner = CliRunner()
    result = runner.invoke(
        main,
        [
            "advise-supervisory",
            "--endpoint",
            "localhost:5000",
            "--plaintext",
            "--session-id",
            "session-1",
            "--server-handle",
            "7",
            "--item-handle",
            "42",
            "--json",
        ],
    )

    assert result.exit_code == 0, result.output
    payload = json.loads(result.output)
    assert payload["ok"] is True

    # Verify the MxCommand shape forwarded to the gateway.
    assert len(stub.invoke.requests) == 1
    cmd = stub.invoke.requests[0].command
    assert cmd.kind == pb.MX_COMMAND_KIND_ADVISE_SUPERVISORY
    assert cmd.advise_supervisory.server_handle == 7
    assert cmd.advise_supervisory.item_handle == 42
