"""Robot Framework helper for Tool/Validation domain model smoke tests.

Provides a CLI-style interface for Robot to invoke model creation and
YAML config loading.  Exit code 0 = success, 1 = failure.

Usage:
    python robot/helper_tool_model.py create-tool
    python robot/helper_tool_model.py create-validation
    python robot/helper_tool_model.py load-tool-yaml <yaml_file>
    python robot/helper_tool_model.py load-validation-yaml <yaml_file>
    python robot/helper_tool_model.py validate-constraints
    python robot/helper_tool_model.py validate-invalid-tool
"""

from __future__ import annotations

import sys
from pathlib import Path
from typing import Any

import yaml

# Ensure the src directory is on the import path.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
    sys.path.insert(0, _SRC)

from cleveragents.domain.models.core.tool import (  # noqa: E402
    Tool,
    ToolCapability,
    ToolSource,
    ToolType,
    Validation,
    ValidationMode,
)


def _cmd_create_tool() -> int:
    """Create a minimal Tool and verify fields."""
    tool = Tool(
        name="smoke/robot-tool",
        description="Robot smoke test tool",
        source=ToolSource.BUILTIN,
    )
    assert tool.name == "smoke/robot-tool"
    assert tool.namespace == "smoke"
    assert tool.short_name == "robot-tool"
    assert tool.source == ToolSource.BUILTIN
    assert tool.tool_type == ToolType.TOOL
    assert tool.timeout == 300
    print(f"tool-model-ok: {tool.name}")
    return 0


def _cmd_create_validation() -> int:
    """Create a Validation and verify forced constraints."""
    val = Validation(
        name="smoke/robot-val",
        description="Robot smoke validation",
        source=ToolSource.BUILTIN,
    )
    assert val.tool_type == ToolType.VALIDATION
    assert val.capability.read_only is True
    assert val.capability.writes is False
    assert val.capability.checkpointable is False
    assert val.mode == ValidationMode.REQUIRED
    print(f"validation-model-ok: {val.name}")
    return 0


def _cmd_load_tool_yaml(yaml_path: str) -> int:
    """Load a Tool from a YAML config file and verify."""
    path = Path(yaml_path)
    if not path.exists():
        print(f"tool-yaml-fail: file not found: {yaml_path}")
        return 1
    with path.open() as f:
        config: dict[str, Any] = yaml.safe_load(f)
    tool = Tool.from_config(config)
    cli_dict = tool.as_cli_dict()
    assert "name" in cli_dict
    assert "source" in cli_dict
    assert "capability" in cli_dict
    print(f"tool-yaml-ok: {tool.name} source={tool.source.value}")
    return 0


def _cmd_load_validation_yaml(yaml_path: str) -> int:
    """Load a Validation from a YAML config file and verify."""
    path = Path(yaml_path)
    if not path.exists():
        print(f"validation-yaml-fail: file not found: {yaml_path}")
        return 1
    with path.open() as f:
        config: dict[str, Any] = yaml.safe_load(f)
    val = Validation.from_config(config)
    assert val.tool_type == ToolType.VALIDATION
    assert val.capability.read_only is True
    assert val.capability.writes is False
    cli_dict = val.as_cli_dict()
    assert "mode" in cli_dict
    print(f"validation-yaml-ok: {val.name} mode={val.mode.value}")
    return 0


def _cmd_validate_constraints() -> int:
    """Verify that Validation forces read_only and blocks writes."""
    val = Validation(
        name="smoke/constraint-check",
        description="Constraint test",
        source=ToolSource.BUILTIN,
        capability=ToolCapability(writes=True, checkpointable=True),
    )
    # Validation must force these even when given writable capability
    assert val.capability.read_only is True, "Validation must force read_only=True"
    assert val.capability.writes is False, "Validation must force writes=False"
    assert val.capability.checkpointable is False, (
        "Validation must force checkpointable=False"
    )
    print("validate-constraints-ok")
    return 0


def _cmd_validate_invalid_tool() -> int:
    """Verify that invalid tool config is rejected."""
    from pydantic import ValidationError

    # Test: invalid name pattern
    try:
        Tool(
            name="no-namespace",
            description="Bad name",
            source=ToolSource.BUILTIN,
        )
        print("validate-invalid-unexpected-success: bad name accepted")
        return 1
    except ValidationError:
        pass

    # Test: custom source without code
    try:
        Tool(
            name="local/test",
            description="Missing code",
            source=ToolSource.CUSTOM,
        )
        print("validate-invalid-unexpected-success: missing code accepted")
        return 1
    except ValidationError:
        pass

    # Test: read_only with writes
    try:
        ToolCapability(read_only=True, writes=True)
        print("validate-invalid-unexpected-success: read_only+writes accepted")
        return 1
    except ValidationError:
        pass

    print("validate-invalid-ok")
    return 0


def main() -> int:
    """Entry point called by Robot Framework ``Run Process``."""
    if len(sys.argv) < 2:
        print(
            "Usage: helper_tool_model.py "
            "<create-tool|create-validation|load-tool-yaml|"
            "load-validation-yaml|validate-constraints|validate-invalid-tool> "
            "[args...]"
        )
        return 1

    command = sys.argv[1]

    if command == "create-tool":
        return _cmd_create_tool()
    if command == "create-validation":
        return _cmd_create_validation()
    if command == "load-tool-yaml":
        if len(sys.argv) < 3:
            print("Usage: helper_tool_model.py load-tool-yaml <file>")
            return 1
        return _cmd_load_tool_yaml(sys.argv[2])
    if command == "load-validation-yaml":
        if len(sys.argv) < 3:
            print("Usage: helper_tool_model.py load-validation-yaml <file>")
            return 1
        return _cmd_load_validation_yaml(sys.argv[2])
    if command == "validate-constraints":
        return _cmd_validate_constraints()
    if command == "validate-invalid-tool":
        return _cmd_validate_invalid_tool()

    print(f"Unknown command: {command}")
    return 1


if __name__ == "__main__":
    sys.exit(main())
