"""Ehemals SecureOrchestrator (Policy als beliebiger Callable, Digest ohne
Bindung an Job/Backend/Ablauf). Neuer Vertrag: Gateway.handle() + HMAC-Clearance."""
import json
import unittest

from aria_router.adapter_contract import ResultStatus
from aria_router.adapters import MockAdapter
from aria_router.config import ConfigurationError
from aria_router.gateway import Handling
from aria_router.runner import MockRunner, RunResult

from tests.helpers import AdapterHarness, GatewayTestCase


class SecureTests(GatewayTestCase):
    def setUp(self):
        super().setUp()
        self.codex = None
        self.claude = None

    def factories(self, codex_output=None, codex_fail=None):
        def codex(verifier):
            self.codex = MockAdapter(verifier, "codex", output=codex_output, fail_code=codex_fail)
            return self.codex

        def claude(verifier):
            self.claude = MockAdapter(verifier, "claude", output="OK")
            return self.claude
        return {"codex": codex, "claude": claude}

    def run_with(self, text, config=None, **factory_args):
        gateway = self.gateway(config, adapter_factories=self.factories(**factory_args))
        return gateway.handle(self.request(1, text))

    def test_codex_tie(self):
        r = self.run_with("#public hello", codex_output="OK")
        self.assertEqual((r.status, r.backend, r.reply_text), ("completed", "codex", "OK"))
        self.assertEqual(self.claude.calls, 0)

    def test_no_policy(self):
        r = self.run_with("hello", {"privacy": {"matrix": {"codex": [], "claude": []},
                                                "claude_status_quo_confidential": False}})
        self.assertEqual(r.handling, Handling.BLOCKED)
        self.assertEqual(r.code, "PRIVACY_DENIED")
        self.assertEqual(self.codex.calls, 0)

    def test_context_mismatch(self):
        harness = AdapterHarness(self.root / "h")
        adapter = MockAdapter(harness.verifier, "codex")
        job = harness.job("#public hello")
        other = harness.job("#public hello world")
        r = adapter.execute(harness.clear(adapter, other), job)
        self.assertEqual(r.error_code, "CONTEXT_DIGEST_MISMATCH")
        self.assertEqual(adapter.calls, 0)

    def test_confidential(self):
        r = self.run_with("/codex Vertrag mit BMW")
        self.assertEqual(r.status, "blocked")
        self.assertEqual(r.code, "MANUAL_CHOICE_NOT_PERMITTED")
        self.assertEqual(self.codex.calls, 0)

    def test_manual_claude(self):
        r = self.run_with("/claude #public hello")
        self.assertEqual(r.backend, "claude")

    def test_policy_only_claude(self):
        r = self.run_with("#public hello", {"privacy": {"matrix": {"codex": [],
                                                                    "claude": ["public", "internal", "unknown"]}}})
        self.assertEqual(r.backend, "claude")

    def test_adapter_mismatch(self):
        with self.assertRaises(ConfigurationError) as ctx:
            self.gateway(adapter_factories={"codex": lambda verifier: MockAdapter(verifier, "claude")})
        self.assertEqual(str(ctx.exception), "ADAPTER_MISMATCH")

    def test_failed_result(self):
        r = self.run_with("#public hello", codex_fail="MODEL_FAILED")
        self.assertEqual(r.status, "failed")
        self.assertEqual(r.handling, Handling.FAILED)

    def test_tool_event(self):
        tool = ("\n".join(json.dumps(e) for e in (
            {"type": "turn.started"},
            {"type": "item.started", "item": {"type": "command_execution", "command": "id"}},
            {"type": "turn.completed"},
        )) + "\n").encode()
        gateway = self.gateway(codex_runner=MockRunner(lambda spec: RunResult(True, exit_code=0, stdout=tool)))
        r = gateway.handle(self.request(2, "#public hello"))
        self.assertEqual((r.status, r.code), ("failed", "TOOL_EVENT_SEEN"))

    def test_policy_exception(self):
        class BrokenMemory:
            def snippets_for(self, request, backend):
                raise RuntimeError("no")
        gateway = self.gateway(adapter_factories=self.factories(), memory_provider=BrokenMemory())
        r = gateway.handle(self.request(3, "#public hello"))
        self.assertEqual(r.code, "MEMORY_PROVIDER_ERROR")
        self.assertEqual(self.codex.calls, 0)


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