"""Helper script for validation_attach_type_guard.robot E2E tests.

Each subcommand is a self-contained check that prints a sentinel on success.
Tests the type-discriminator guard in ``attach_validation`` that rejects
plain Tools and only accepts genuine Validations.
"""

from __future__ import annotations

import sys
from collections.abc import Callable
from pathlib import Path
from unittest.mock import MagicMock, patch

# Ensure local source tree is importable
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from helpers_common import reset_global_state  # noqa: E402
from typer.testing import CliRunner  # noqa: E402

from cleveragents.cli.commands.validation import app as validation_app  # noqa: E402
from cleveragents.core.exceptions import ToolTypeMismatchError  # noqa: E402

runner = CliRunner()

_ATTACHMENT_ULID = "01TYPEGUARD000000000000001"


# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------


def attach_plain_tool_rejected() -> None:
    """Verify that attaching a plain Tool (domain object) is rejected."""
    mock_svc = MagicMock()
    mock_svc.attach_validation.side_effect = ToolTypeMismatchError(
        tool_name="local/my-plain-tool",
        actual_type="tool",
    )
    with patch(
        "cleveragents.cli.commands.validation._get_tool_registry_service",
        return_value=mock_svc,
    ):
        result = runner.invoke(
            validation_app,
            [
                "attach",
                "git-checkout/my-repo",
                "local/my-plain-tool",
                "--format",
                "plain",
            ],
        )
    # Must be rejected (non-zero exit) and output must mention "plain Tool"
    if result.exit_code != 0 and "plain Tool" in result.output:
        print("validation-attach-plain-tool-rejected-ok")
    else:
        print(
            f"FAIL: exit={result.exit_code} "
            f"output={result.output!r} "
            f"(expected non-zero exit and 'plain Tool' in output)"
        )
        sys.exit(1)


def attach_validation_accepted() -> None:
    """Verify that attaching a genuine Validation succeeds."""
    mock_svc = MagicMock()
    mock_attachment = MagicMock()
    mock_attachment.attachment_id = _ATTACHMENT_ULID
    mock_attachment.validation_name = "local/coverage-check"
    mock_attachment.resource_id = "git-checkout/my-repo"
    mock_attachment.mode = "required"
    mock_attachment.project_name = None
    mock_attachment.plan_id = None
    mock_attachment.created_at = "2026-01-01T00:00:00"
    mock_svc.attach_validation.return_value = mock_attachment
    with patch(
        "cleveragents.cli.commands.validation._get_tool_registry_service",
        return_value=mock_svc,
    ):
        result = runner.invoke(
            validation_app,
            [
                "attach",
                "git-checkout/my-repo",
                "local/coverage-check",
                "--format",
                "plain",
            ],
        )
    if result.exit_code == 0:
        print("validation-attach-validation-accepted-ok")
    else:
        print(f"FAIL: exit={result.exit_code} output={result.output!r}")
        sys.exit(1)


def attach_plain_tool_dict_rejected() -> None:
    """Verify that attaching a plain Tool stored as a dict is rejected."""
    mock_svc = MagicMock()
    mock_svc.attach_validation.side_effect = ToolTypeMismatchError(
        tool_name="local/dict-tool",
        actual_type="tool",
    )
    with patch(
        "cleveragents.cli.commands.validation._get_tool_registry_service",
        return_value=mock_svc,
    ):
        result = runner.invoke(
            validation_app,
            [
                "attach",
                "git-checkout/my-repo",
                "local/dict-tool",
                "--format",
                "plain",
            ],
        )
    if result.exit_code != 0 and "plain Tool" in result.output:
        print("validation-attach-plain-tool-dict-rejected-ok")
    else:
        print(
            f"FAIL: exit={result.exit_code} "
            f"output={result.output!r} "
            f"(expected non-zero exit and 'plain Tool' in output)"
        )
        sys.exit(1)


# ---------------------------------------------------------------------------
# Dispatcher
# ---------------------------------------------------------------------------

_COMMANDS: dict[str, Callable[[], None]] = {
    "attach-plain-tool-rejected": attach_plain_tool_rejected,
    "attach-validation-accepted": attach_validation_accepted,
    "attach-plain-tool-dict-rejected": attach_plain_tool_dict_rejected,
}

if __name__ == "__main__":
    if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS:
        print(f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>")
        sys.exit(1)
    reset_global_state()
    fn = _COMMANDS[sys.argv[1]]
    fn()
