"""Helper script for tool_cli.robot smoke tests.

Each subcommand is a self-contained check that prints a sentinel on success.
"""

from __future__ import annotations

import os
import sys
import tempfile
from pathlib import Path
from typing import Any
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 typer.testing import CliRunner  # noqa: E402

from cleveragents.cli.commands.tool import app as tool_app  # noqa: E402
from cleveragents.cli.commands.validation import app as validation_app  # noqa: E402

runner = CliRunner()

_TOOL_YAML = """\
name: local/smoke-tool
description: Smoke test tool
source: custom
code: |
  def run(inputs):
      return {"result": True}
"""

_VALIDATION_YAML = """\
name: local/smoke-val
description: Smoke test validation
source: custom
mode: required
code: |
  def run(inputs):
      return {"passed": True}
"""


def _mock_tool(
    name: str = "local/smoke-tool",
    tool_type: str = "tool",
) -> dict[str, Any]:
    ns, sn = name.split("/", 1)
    return {
        "name": name,
        "description": f"Smoke test {tool_type}",
        "source": "custom",
        "tool_type": tool_type,
        "namespace": ns,
        "short_name": sn,
        "capability": {"read_only": False, "writes": False, "checkpointable": False},
        "timeout": 300,
    }


def _mock_attachment() -> dict[str, Any]:
    return {
        "attachment_id": "att-smoke-001",
        "validation_name": "local/smoke-val",
        "resource_id": "resource/r1",
        "mode": "required",
        "project_name": None,
        "plan_id": None,
        "created_at": "2026-01-01T00:00:00",
    }


def _write_yaml(content: str) -> str:
    fd, path = tempfile.mkstemp(suffix=".yaml")
    with os.fdopen(fd, "w") as fh:
        fh.write(content)
    return path


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


def tool_add_config() -> None:
    """Verify tool add --config works."""
    path = _write_yaml(_TOOL_YAML)
    try:
        svc = MagicMock()
        svc.register_tool.return_value = _mock_tool()
        svc.get_tool.return_value = None
        with patch(
            "cleveragents.cli.commands.tool._get_tool_registry_service",
            return_value=svc,
        ):
            result = runner.invoke(tool_app, ["add", "--config", path])
        assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
        print("tool-cli-add-config-ok")
    finally:
        Path(path).unlink(missing_ok=True)


def tool_list_all() -> None:
    """Verify tool list works."""
    svc = MagicMock()
    svc.list_tools.return_value = [_mock_tool()]
    with patch(
        "cleveragents.cli.commands.tool._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(tool_app, ["list"])
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    print("tool-cli-list-ok")


def tool_show_name() -> None:
    """Verify tool show accepts a namespaced name."""
    svc = MagicMock()
    svc.get_tool.return_value = _mock_tool()
    with patch(
        "cleveragents.cli.commands.tool._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(tool_app, ["show", "local/smoke-tool"])
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    print("tool-cli-show-ok")


def tool_remove_name() -> None:
    """Verify tool remove accepts a namespaced name."""
    svc = MagicMock()
    svc.get_tool.return_value = _mock_tool()
    svc.remove_tool.return_value = True
    with patch(
        "cleveragents.cli.commands.tool._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(tool_app, ["remove", "local/smoke-tool", "--yes"])
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    print("tool-cli-remove-ok")


def validation_add_config() -> None:
    """Verify validation add --config works."""
    path = _write_yaml(_VALIDATION_YAML)
    try:
        svc = MagicMock()
        svc.register_tool.return_value = _mock_tool("local/smoke-val", "validation")
        svc.get_tool.return_value = None
        with patch(
            "cleveragents.cli.commands.validation._get_tool_registry_service",
            return_value=svc,
        ):
            result = runner.invoke(validation_app, ["add", "--config", path])
        assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
        print("validation-cli-add-ok")
    finally:
        Path(path).unlink(missing_ok=True)


def validation_attach() -> None:
    """Verify validation attach works."""
    svc = MagicMock()
    svc.attach_validation.return_value = _mock_attachment()
    with patch(
        "cleveragents.cli.commands.validation._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(
            validation_app,
            ["attach", "resource/r1", "local/smoke-val"],
        )
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    print("validation-cli-attach-ok")


def validation_detach() -> None:
    """Verify validation detach works."""
    svc = MagicMock()
    svc.detach_validation.return_value = True
    with patch(
        "cleveragents.cli.commands.validation._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(
            validation_app,
            ["detach", "att-smoke-001", "--yes"],
        )
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    print("validation-cli-detach-ok")


def tool_list_type_tool() -> None:
    """Verify tool list --type tool returns only tools."""
    svc = MagicMock()
    svc.list_tools.return_value = [_mock_tool("local/smoke-tool", "tool")]
    with patch(
        "cleveragents.cli.commands.tool._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(tool_app, ["list", "--type", "tool"])
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    svc.list_tools.assert_called_once_with(
        namespace=None, tool_type="tool", source=None
    )
    print("tool-cli-list-type-tool-ok")


def tool_list_type_validation() -> None:
    """Verify tool list --type validation returns only validations."""
    svc = MagicMock()
    svc.list_tools.return_value = [_mock_tool("local/smoke-val", "validation")]
    with patch(
        "cleveragents.cli.commands.tool._get_tool_registry_service",
        return_value=svc,
    ):
        result = runner.invoke(tool_app, ["list", "--type", "validation"])
    assert result.exit_code == 0, f"exit={result.exit_code}: {result.output}"
    svc.list_tools.assert_called_once_with(
        namespace=None, tool_type="validation", source=None
    )
    print("tool-cli-list-type-validation-ok")


_COMMANDS = {
    "tool-add-config": tool_add_config,
    "tool-list": tool_list_all,
    "tool-list-type-tool": tool_list_type_tool,
    "tool-list-type-validation": tool_list_type_validation,
    "tool-show": tool_show_name,
    "tool-remove": tool_remove_name,
    "validation-add-config": validation_add_config,
    "validation-attach": validation_attach,
    "validation-detach": validation_detach,
}

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)
    _COMMANDS[sys.argv[1]]()
