import unittest

from mm_agents.qwen.actions import parse_base_response, parse_internal_response
from mm_agents.qwen.parser import parse_keys


def tool_call(*params):
    body = "\n".join(
        f"<parameter={name}>{value}</parameter>"
        for name, value in params
    )
    return (
        "Action: test\n"
        "<tool_call>\n"
        "<function=computer_use>\n"
        f"{body}\n"
        "</function>\n"
        "</tool_call>"
    )


class QwenActionParserTest(unittest.TestCase):
    def test_parse_keys_accepts_python_literal_lists(self):
        self.assertEqual(parse_keys("['ctrl', 's']", lowercase=True), ["ctrl", "s"])
        self.assertEqual(parse_keys("[\"ctrl\", \"shift\", \"t\"]", lowercase=True), ["ctrl", "shift", "t"])
        self.assertEqual(parse_keys([["ctrl"], "s"], lowercase=True), ["ctrl", "s"])

    def test_parse_keys_splits_plus_separated_shortcuts(self):
        self.assertEqual(parse_keys("ctrl+shift+t", lowercase=True), ["ctrl", "shift", "t"])

    def test_internal_parser_handles_non_success_terminate_aliases(self):
        for status in ["fail", "failed", "failure", "error", "infeasible"]:
            _, code = parse_internal_response(
                tool_call(("action", "terminate"), ("status", status)),
                coordinate_type="relative",
            )
            self.assertEqual(code, ["FAIL"])

    def test_base_parser_handles_non_success_terminate_aliases(self):
        _, code = parse_base_response(
            tool_call(("action", "terminate"), ("status", "fail")),
            coordinate_type="relative",
        )
        self.assertEqual(code, ["FAIL"])

    def test_internal_parser_generates_hotkeys_from_python_literal_lists(self):
        _, code = parse_internal_response(
            tool_call(("action", "key"), ("keys", "['ctrl', 's']")),
            coordinate_type="relative",
        )
        self.assertEqual(code, ['pyautogui.hotkey("ctrl", "s")'])


if __name__ == "__main__":
    unittest.main()
