import sys
import tempfile
import types
import unittest
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch

sys.modules.setdefault("wrapt_timeout_decorator", types.ModuleType("wrapt_timeout_decorator"))

os_symphony_common_utils = types.ModuleType("mm_agents.os_symphony.utils.common_utils")
os_symphony_common_utils.draw_coordinates = lambda *args, **kwargs: None
sys.modules.setdefault("mm_agents.os_symphony.utils.common_utils", os_symphony_common_utils)

os_symphony_process_context = types.ModuleType("mm_agents.os_symphony.utils.process_context")
os_symphony_process_context.set_current_result_dir = lambda *args, **kwargs: None
sys.modules.setdefault("mm_agents.os_symphony.utils.process_context", os_symphony_process_context)

import lib_run_single


class FakeController:
    def start_recording(self):
        pass

    def end_recording(self, _path):
        pass


class FakeEnv:
    def __init__(self):
        self.controller = FakeController()
        self.action_history = []

    def reset(self, task_config=None):
        self.task_config = task_config

    def _get_obs(self):
        return {"screenshot": b"fake-image"}

    def step(self, action, _pause):
        self.action_history.append(action)
        done = action == "FAIL"
        info = {"fail": True} if done else {}
        return self._get_obs(), 0.0, done, info

    def evaluate(self):
        return 1 if self.action_history and self.action_history[-1] == "FAIL" else 0


class FakeAgent:
    def reset(self, _runtime_logger):
        pass

    def predict(self, _instruction, _obs):
        return {
            "response": "[INFEASIBLE]",
            "state_correct": False,
            "infeasible_message": True,
            "model_usage": {},
            "messages": [],
        }, []


class GPT54InfeasibleTest(unittest.TestCase):
    def test_infeasible_response_emits_fail_action(self):
        agent = FakeAgent()
        env = FakeEnv()
        args = SimpleNamespace(sleep_after_execution=0)
        example = {"id": "example-1"}

        with tempfile.TemporaryDirectory() as tmpdir:
            result_dir = Path(tmpdir)

            with patch("lib_run_single.time.sleep", return_value=None), patch(
                "lib_run_single.setup_logger", return_value=None
            ):
                lib_run_single.run_single_example_gpt54(
                    agent=agent,
                    env=env,
                    example=example,
                    max_steps=1,
                    instruction="test infeasible handling",
                    args=args,
                    example_result_dir=str(result_dir),
                    scores=[],
                )

            self.assertEqual(env.action_history, ["FAIL"])
            self.assertEqual((result_dir / "result.txt").read_text(encoding="utf-8").strip(), "1")


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