"""Run with python3 -m unittest -v test_tool_agent.py. No key/network required."""
import json
import unittest
from tool_agent import execute_tool, fixture_model, run_agent


class AgentTests(unittest.TestCase):
    def test_read_observe_answer(self):
        result = run_agent(fixture_model, "Look up DEMO-1001")
        self.assertEqual(result["steps"], 2)
        self.assertIn("shipped (synthetic_fixture)", result["answer"])
        self.assertEqual(result["history"][2]["call_id"], "demo-call-1")

    def test_unknown_order_is_an_error_not_a_guess(self):
        self.assertEqual(execute_tool("lookup_order", '{"order_id":"MISSING"}'),
                         {"ok": False, "error": "order_not_found"})

    def test_rejects_unregistered_tools(self):
        self.assertEqual(execute_tool("delete_order", '{}')["error"], "unknown_tool")

    def test_bad_json(self):
        self.assertEqual(execute_tool("lookup_order", '{')["error"], "invalid_json")

    def test_invalid_arguments(self):
        for value in [[], None, {}, {"order_id": 1001},
                      {"order_id": "DEMO-1001", "delete": True}]:
            with self.subTest(value=value):
                self.assertEqual(execute_tool("lookup_order", json.dumps(value))["error"],
                                 "invalid_arguments")

    def test_repeated_calls_stop(self):
        with self.assertRaisesRegex(RuntimeError, "step_limit_reached"):
            run_agent(lambda _: fixture_model([]), "loop", max_steps=2)

    def test_multiple_calls_rejected(self):
        with self.assertRaisesRegex(RuntimeError, "too_many_tool_calls"):
            run_agent(lambda _: fixture_model([]) * 2, "too many")

    def test_empty_answer_is_not_success(self):
        with self.assertRaisesRegex(RuntimeError, "model_returned_no_answer"):
            run_agent(lambda _: [], "empty")

    def test_model_failure_surfaces(self):
        def unavailable(_):
            raise TimeoutError("provider timeout")
        with self.assertRaises(TimeoutError):
            run_agent(unavailable, "timeout")


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