"""Robot Framework helper for tool-level execution environment preferences."""

from __future__ import annotations

import importlib
import sys
from pathlib import Path
from typing import Any
from unittest.mock import create_autospec

# 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)

import cleveragents  # noqa: E402

importlib.reload(cleveragents)

from cleveragents.domain.models.core.execution_environment_preference import (  # noqa: E402
    EnvironmentPreferenceMode,
    ExecutionEnvironmentPreference,
)
from cleveragents.domain.models.core.tool import Tool, ToolSource  # noqa: E402
from cleveragents.tool.registry import ToolRegistry  # noqa: E402
from cleveragents.tool.runner import ToolRunner  # noqa: E402
from cleveragents.tool.runtime import ToolResult, ToolSpec  # noqa: E402


def _make_handler(inputs: dict[str, Any]) -> dict[str, Any]:
    return {"result": "ok"}


def _run_default_preference() -> None:
    """Default preference is NONE."""
    pref = ExecutionEnvironmentPreference()
    assert pref.mode == EnvironmentPreferenceMode.NONE
    assert pref.target_resource is None
    print("default-preference-ok")


def _run_required_mode() -> None:
    """Required mode validates correctly."""
    pref = ExecutionEnvironmentPreference(mode=EnvironmentPreferenceMode.REQUIRED)
    assert pref.mode == EnvironmentPreferenceMode.REQUIRED
    assert pref.target_resource is None
    print("required-mode-ok")


def _run_preferred_mode() -> None:
    """Preferred mode validates correctly."""
    pref = ExecutionEnvironmentPreference(mode=EnvironmentPreferenceMode.PREFERRED)
    assert pref.mode == EnvironmentPreferenceMode.PREFERRED
    assert pref.target_resource is None
    print("preferred-mode-ok")


def _run_specific_mode() -> None:
    """Specific mode requires target_resource."""
    pref = ExecutionEnvironmentPreference(
        mode=EnvironmentPreferenceMode.SPECIFIC,
        target_resource="local/api-dev",
    )
    assert pref.mode == EnvironmentPreferenceMode.SPECIFIC
    assert pref.target_resource == "local/api-dev"

    # Should fail without target_resource
    try:
        ExecutionEnvironmentPreference(mode=EnvironmentPreferenceMode.SPECIFIC)
        print("FAIL: expected ValueError")
        sys.exit(1)
    except ValueError:
        pass

    print("specific-mode-ok")


def _run_specific_mode_validates_target() -> None:
    """Specific mode validates that target_resource is present."""
    try:
        ExecutionEnvironmentPreference(mode=EnvironmentPreferenceMode.SPECIFIC)
        print("FAIL: expected ValueError for missing target")
        sys.exit(1)
    except ValueError as exc:
        assert "'specific' mode requires target_resource" in str(exc)

    # target_resource not allowed with non-specific modes
    try:
        ExecutionEnvironmentPreference(
            mode=EnvironmentPreferenceMode.REQUIRED,
            target_resource="local/api-dev",
        )
        print("FAIL: expected ValueError for invalid target")
        sys.exit(1)
    except ValueError as exc:
        assert "target_resource only valid" in str(exc)

    print("specific-validates-target-ok")


def _run_toolspec_field() -> None:
    """ToolSpec has execution_environment field."""
    spec = ToolSpec(
        name="test/tool",
        description="A test tool",
        handler=_make_handler,
    )
    assert spec.execution_environment.mode == EnvironmentPreferenceMode.NONE

    spec2 = ToolSpec(
        name="test/tool2",
        description="A required tool",
        handler=_make_handler,
        execution_environment=ExecutionEnvironmentPreference(
            mode=EnvironmentPreferenceMode.REQUIRED,
        ),
    )
    assert spec2.execution_environment.mode == EnvironmentPreferenceMode.REQUIRED
    print("toolspec-field-ok")


def _run_domain_tool_field() -> None:
    """Domain Tool has execution_environment field."""
    tool = Tool(
        name="local/test-tool",
        description="A test tool",
        source=ToolSource.BUILTIN,
    )
    assert tool.execution_environment.mode == EnvironmentPreferenceMode.NONE
    print("domain-tool-field-ok")


def _run_tool_from_config() -> None:
    """Tool.from_config parses execution_environment."""
    config: dict[str, Any] = {
        "name": "local/test-tool",
        "description": "A test tool",
        "source": "builtin",
        "execution_environment": {"mode": "required"},
    }
    tool = Tool.from_config(config)
    assert tool.execution_environment.mode == EnvironmentPreferenceMode.REQUIRED

    # Without execution_environment
    config2: dict[str, Any] = {
        "name": "local/test-tool2",
        "description": "Another test tool",
        "source": "builtin",
    }
    tool2 = Tool.from_config(config2)
    assert tool2.execution_environment.mode == EnvironmentPreferenceMode.NONE

    # With specific mode and target
    config3: dict[str, Any] = {
        "name": "local/test-tool3",
        "description": "Specific test tool",
        "source": "builtin",
        "execution_environment": {
            "mode": "specific",
            "target_resource": "local/api-dev",
        },
    }
    tool3 = Tool.from_config(config3)
    assert tool3.execution_environment.mode == EnvironmentPreferenceMode.SPECIFIC
    assert tool3.execution_environment.target_resource == "local/api-dev"

    print("tool-from-config-ok")


def _run_runner_none_preference() -> None:
    """ToolRunner with NONE preference uses caller-supplied env."""
    registry = ToolRegistry()
    spec = ToolSpec(
        name="test/none-pref",
        description="Tool with no env preference",
        handler=_make_handler,
    )
    registry.register(spec)
    runner = ToolRunner(registry=registry)
    runner.activate("test/none-pref")
    result = runner.execute("test/none-pref", {"input": "value"})
    assert result.success is True
    print("runner-none-preference-ok")


def _run_runner_required_no_container() -> None:
    """ToolRunner with REQUIRED preference fails without container."""
    registry = ToolRegistry()
    spec = ToolSpec(
        name="test/required-pref",
        description="Tool requiring container",
        handler=_make_handler,
        execution_environment=ExecutionEnvironmentPreference(
            mode=EnvironmentPreferenceMode.REQUIRED,
        ),
    )
    registry.register(spec)
    runner = ToolRunner(registry=registry)
    runner.activate("test/required-pref")
    result = runner.execute("test/required-pref", {"input": "value"})
    assert result.success is False
    assert "requires container execution" in (result.error or "")
    print("runner-required-no-container-ok")


def _run_runner_preferred_fallback() -> None:
    """ToolRunner with PREFERRED preference falls back to host."""
    registry = ToolRegistry()
    spec = ToolSpec(
        name="test/preferred-pref",
        description="Tool preferring container",
        handler=_make_handler,
        execution_environment=ExecutionEnvironmentPreference(
            mode=EnvironmentPreferenceMode.PREFERRED,
        ),
    )
    registry.register(spec)
    runner = ToolRunner(registry=registry)
    runner.activate("test/preferred-pref")
    result = runner.execute("test/preferred-pref", {"input": "value"})
    assert result.success is True
    print("runner-preferred-fallback-ok")


def _run_runner_specific_container() -> None:
    """ToolRunner with SPECIFIC preference overrides tool_env."""
    registry = ToolRegistry()
    spec = ToolSpec(
        name="test/specific-pref",
        description="Tool targeting specific container",
        handler=_make_handler,
        execution_environment=ExecutionEnvironmentPreference(
            mode=EnvironmentPreferenceMode.SPECIFIC,
            target_resource="local/api-dev",
        ),
    )
    registry.register(spec)

    from cleveragents.tool.container_executor import ContainerToolExecutor

    mock_executor = create_autospec(ContainerToolExecutor, instance=True)
    mock_executor.execute_tool.return_value = ToolResult(
        success=True,
        output={"result": "container-ok"},
        duration_ms=1.0,
    )
    runner = ToolRunner(registry=registry, container_executor=mock_executor)
    runner.activate("test/specific-pref")
    result = runner.execute(
        "test/specific-pref",
        {"input": "value"},
        linked_resource_types=["container-instance"],
        project_name="test-project",
    )
    assert result.success is True
    print("runner-specific-container-ok")


if __name__ == "__main__":
    cmd = sys.argv[1] if len(sys.argv) > 1 else "all"
    dispatch = {
        "default-preference": _run_default_preference,
        "required-mode": _run_required_mode,
        "preferred-mode": _run_preferred_mode,
        "specific-mode": _run_specific_mode,
        "specific-validates-target": _run_specific_mode_validates_target,
        "toolspec-field": _run_toolspec_field,
        "domain-tool-field": _run_domain_tool_field,
        "tool-from-config": _run_tool_from_config,
        "runner-none-preference": _run_runner_none_preference,
        "runner-required-no-container": _run_runner_required_no_container,
        "runner-preferred-fallback": _run_runner_preferred_fallback,
        "runner-specific-container": _run_runner_specific_container,
    }

    if cmd == "all":
        for fn in dispatch.values():
            fn()
    elif cmd in dispatch:
        dispatch[cmd]()
    else:
        print(f"Unknown command: {cmd}")
        sys.exit(1)
