from __future__ import annotations

import pytest

from kantan_agents_tools.normalize import _ALIAS_MAP, _SECONDS_ALIASES, normalize_tool_payload

_ALIAS_CASES: list[tuple[str, str, str]] = []
for tool_name, mapping in sorted(_ALIAS_MAP.items()):
    for canonical, aliases in sorted(mapping.items()):
        for alias in sorted(aliases):
            _ALIAS_CASES.append((tool_name, canonical, alias))


def test_normalize_fs_write_alias_and_mode() -> None:
    payload = {"file_path": "/tmp/a.txt", "content": "hello", "mode": "w", "policy": {"x": 1}}

    normalized, error = normalize_tool_payload("kantan_fs_write", payload)

    assert error is None
    assert normalized["path"] == "/tmp/a.txt"
    assert normalized["text"] == "hello"
    assert normalized["mode"] == "overwrite"
    assert "policy" not in normalized


def test_normalize_web_fetch_timeout_seconds() -> None:
    payload = {"url": "http://example.com", "timeout": "2.5"}

    normalized, error = normalize_tool_payload("kantan_web_fetch", payload)

    assert error is None
    assert normalized["timeout_ms"] == 2500


def test_normalize_browser_act_action() -> None:
    payload = {
        "pageId": "p1",
        "action": {"action": "type", "css": "#input", "value": "hi", "timeout": 1},
    }

    normalized, error = normalize_tool_payload("kantan_browser_act", payload)

    assert error is None
    assert normalized["page_id"] == "p1"
    assert isinstance(normalized["actions"], list)
    action = normalized["actions"][0]
    assert action["type"] == "fill"
    assert action["selector"] == "#input"
    assert action["text"] == "hi"
    assert action["timeout_ms"] == 1000


def test_normalize_shell_run_env_list() -> None:
    payload = {"command": "echo hi", "env": ["A=1", "B=two"]}

    normalized, error = normalize_tool_payload("kantan_shell_run", payload)

    assert error is None
    assert normalized["cmd"] == "echo hi"
    assert normalized["env"] == {"A": "1", "B": "two"}


def test_normalize_fs_read_range_alias() -> None:
    payload = {"path": "sample.txt", "range": {"start": "2", "end": 4}}

    normalized, error = normalize_tool_payload("kantan_fs_read", payload)

    assert error is None
    assert normalized["range"] == {"start_line": 2, "end_line": 4}


@pytest.mark.parametrize("tool_name, canonical, alias", _ALIAS_CASES)
def test_normalize_alias_map(tool_name: str, canonical: str, alias: str) -> None:
    value, expected = _sample_value(tool_name, canonical, alias)
    payload = {alias: value}

    normalized, error = normalize_tool_payload(tool_name, payload)

    assert error is None
    assert alias not in normalized
    if canonical == "actions":
        assert normalized["actions"] == expected
    else:
        assert normalized[canonical] == expected


def _sample_value(tool_name: str, canonical: str, alias: str) -> tuple[object, object]:
    if canonical == "timeout_ms":
        if alias in _SECONDS_ALIASES:
            return "2.5", 2500
        return "1500", 1500
    if canonical in {
        "max_results",
        "max_entries",
        "max_matches",
        "max_bytes",
        "max_chars",
        "strip",
        "head",
        "tail",
    }:
        return "3", 3
    if canonical == "recursive":
        return "true", True
    if canonical in {"domains_allow", "domains_block"}:
        return "example.com", ["example.com"]
    if canonical == "selectors":
        return "body", ["body"]
    if canonical == "extract":
        return "link", ["links"]
    if canonical == "mode":
        if tool_name == "kantan_fs_write":
            return "w", "overwrite"
        return "md", "markdown"
    if canonical == "method":
        return "get", "GET"
    if canonical == "actions":
        return {"action": "tap", "css": "#a"}, [{"type": "click", "selector": "#a"}]
    if canonical == "range":
        return {"start": "2", "end": 4}, {"start_line": 2, "end_line": 4}
    if canonical == "env":
        return ["A=1", "B=two"], {"A": "1", "B": "two"}
    if canonical == "cmd":
        if alias in {"args", "argv"}:
            return ["echo", "hi"], ["echo", "hi"]
        return "echo hi", "echo hi"
    if canonical == "headers":
        return {"X": "1"}, {"X": "1"}
    if canonical == "viewport":
        return {"width": 100, "height": 100}, {"width": 100, "height": 100}
    if canonical in {"page_id", "url"}:
        return "value", "value"
    if canonical in {"path", "root"}:
        return "/tmp/example", "/tmp/example"
    return "value", "value"
