"""Ehemals parse_codex_jsonl + CodexProcessAdapter (zweiter Parser, beliebige argv,
geerbte Umgebung). Neuer Vertrag: ein Parser (hardened_codex.decode_events),
CodexAdapter mit echtem SubprocessRunner und Clearance (docs/AENDERUNGEN.md)."""
import json
import tempfile
import unittest
from pathlib import Path

from aria_router.adapter_contract import ResultStatus
from aria_router.codex_adapter import CodexAdapter
from aria_router.hardened_codex import decode_events

from tests.helpers import GuardedSubprocessRunner, AdapterHarness, fake_codex_template


def events(*items):
    return ("\n".join(json.dumps(x) for x in items) + "\n").encode()


class CodexAdapterTests(unittest.TestCase):

    def setUp(self):
        self._tmp = tempfile.TemporaryDirectory()
        root = Path(self._tmp.name)
        (root / "work").mkdir()
        self.harness = AdapterHarness(root)
        self.runner = GuardedSubprocessRunner(root / "work")

    def tearDown(self):
        self._tmp.cleanup()

    def run_mode(self, mode, timeout=5, *extra):
        adapter = CodexAdapter(self.harness.verifier, runner=self.runner,
                               command_template=fake_codex_template(mode, *extra),
                               env={"PATH": "/usr/bin:/bin", "LANG": "C.UTF-8"})
        job = self.harness.job("#public test", timeout=timeout)
        return adapter.execute(self.harness.clear(adapter, job), job)

    def test_successful_jsonl(self):
        outcome = decode_events(events(
            {"type": "turn.started"},
            {"type": "item.completed", "item": {"type": "agent_message", "text": "CODEX_OK"}},
            {"type": "turn.completed"},
        ))
        self.assertTrue(outcome.success)
        self.assertEqual(outcome.output, "CODEX_OK")

    def test_invalid_jsonl(self):
        self.assertEqual(decode_events(b"invalid json").error_code, "INVALID_JSONL")

    def test_incomplete_turn(self):
        outcome = decode_events(events({"type": "turn.started"}))
        self.assertFalse(outcome.success)
        self.assertEqual(outcome.error_code, "INCOMPLETE_TURN")

    def test_failed_turn(self):
        outcome = decode_events(events({"type": "turn.failed"}, {"type": "turn.completed"}))
        self.assertFalse(outcome.success)
        self.assertEqual(outcome.error_code, "MODEL_FAILED")

    def test_process_success(self):
        result = self.run_mode("success")
        self.assertEqual(result.status, ResultStatus.SUCCESS)
        self.assertEqual(result.output, "MOCK_OK")

    def test_process_failure(self):
        result = self.run_mode("exit2")
        self.assertEqual(result.status, ResultStatus.FAILED)
        self.assertEqual(result.error_code, "NONZERO_EXIT")

    def test_timeout(self):
        result = self.run_mode("sleep", 1, "5")
        self.assertEqual(result.status, ResultStatus.FAILED)
        self.assertEqual(result.error_code, "TIMEOUT")
        self.assertTrue(result.timed_out)


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