"""Ehemals TelegramDryRunRouter (zweiter Entscheidungspfad am Gateway vorbei).
Der Dry-Run ist jetzt Gateway.shadow(): derselbe Entscheidungsweg wie
handle(), aber ohne Ausführung. Begründete Vertragsänderungen in
docs/AENDERUNGEN.md (UNKNOWN geht nach Status quo an Claude, unbekannte
Befehle laufen als Nachricht durch die Policy)."""
import unittest

from aria_router.gateway import Handling

from tests.helpers import GROUP_ID, OTHER_ID, GatewayTestCase, photo


class TelegramDryRunTests(GatewayTestCase):
    def setUp(self):
        super().setUp()
        self.router = self.gateway({"backends": {"codex": {"quality": 75}, "claude": {"quality": 75}}})

    def shadow(self, message_id, text, **kwargs):
        return self.router.shadow(self.request(message_id, text, **kwargs))

    def test_unapproved_user_never_routed(self):
        result = self.shadow(1, '#public hello', sender_id=OTHER_ID)
        self.assertEqual(result.planned_handling, Handling.DROP.value)
        self.assertEqual(result.code, "NOT_AUTHORIZED")

    def test_groups_not_routed(self):
        result = self.shadow(2, '#public hello', chat_id=GROUP_ID, chat_type='group')
        self.assertEqual(result.planned_handling, Handling.DROP.value)

    def test_default_privacy_fail_closed(self):
        result = self.shadow(3, 'hi')
        self.assertEqual(result.privacy, 'unknown')
        self.assertNotEqual(result.backend, 'codex')
        strict = self.gateway({"privacy": {"matrix": {"codex": ["public"], "claude": ["public"]},
                                           "claude_status_quo_confidential": False}})
        blocked = strict.shadow(self.request(30, 'hi'))
        self.assertEqual((blocked.planned_handling, blocked.backend), (Handling.BLOCKED.value, None))

    def test_codex_tie(self):
        r = self.shadow(4, '#public analyze')
        self.assertEqual((r.handling, r.backend, r.delivered), (Handling.SHADOW_DECISION, 'codex', False))

    def test_manual_claude(self):
        self.assertEqual(self.shadow(5, '/claude').planned_handling, Handling.REPLY.value)
        r = self.shadow(6, '#public analyze')
        self.assertEqual(r.backend, 'claude')

    def test_manual_never_overrides_privacy(self):
        router = self.gateway({"privacy": {"claude_status_quo_confidential": False}})
        router.shadow(self.request(7, '/claude'))
        result = router.shadow(self.request(8, 'Kundendaten BMW'))
        self.assertEqual(result.planned_handling, Handling.BLOCKED.value)

    def test_auto_resets(self):
        self.shadow(9, '/claude')
        self.shadow(10, '/auto')
        self.assertEqual(self.shadow(11, '#public hello').backend, 'codex')

    def test_status_preserves_pairing_command(self):
        r = self.shadow(12, '/status')
        self.assertEqual(r.planned_handling, Handling.NOT_INTERCEPTED.value)

    def test_unknown_command_passes_to_existing_plugin(self):
        r = self.shadow(13, '/something')
        self.assertEqual(r.planned_handling, Handling.FORWARD_TO_CLAUDE_CHANNEL.value)
        self.assertEqual(r.backend, 'claude')

    def test_attachment_denied(self):
        r = self.shadow(14, '#public photo', attachments=[photo()])
        self.assertNotEqual(r.backend, 'codex')
        self.assertEqual(r.privacy, 'unknown')

    def test_duplicate_inbound_not_processed_twice(self):
        self.shadow(15, 'hello')
        self.assertEqual(self.shadow(15, 'hello').code, 'DUPLICATE_MESSAGE')

    def test_unavailable_model_denied(self):
        router = self.gateway({"backends": {"claude": {"enabled": False}}}, adapter_factories={"codex": None})
        result = router.shadow(self.request(16, '#public hello'))
        self.assertEqual(result.planned_handling, Handling.BLOCKED.value)

    def test_no_worker_called_or_network_used(self):
        result = self.shadow(17, '#public hello')
        self.assertFalse(result.delivered)
        self.assertEqual(self.router.adapters["codex"].runner.calls, [])
        self.assertEqual(self.sink.delivered, [])


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