"""Ergebnisprüfung: Secrets schwärzen und markieren, Ausgabelimit, strukturierte Flags."""
import secrets
import string
import unittest

from aria_router.gateway import Handling
from aria_router.result_check import TRUNCATION_MARK, check_output

from tests.helpers import GatewayTestCase, GuardedSubprocessRunner, deep_merge, fake_codex_template


def fake_bot_token() -> str:
    alphabet = string.ascii_letters + string.digits
    return "".join(secrets.choice(string.digits) for _ in range(9)) + ":" + "".join(
        secrets.choice(alphabet) for _ in range(35))


class ResultCheckTests(unittest.TestCase):
    def test_secret_redacted_and_marked(self):
        token = fake_bot_token()
        checked = check_output(f"Dein Token: {token} fertig", max_chars=1000)
        self.assertNotIn(token, checked.text)
        self.assertIn("[GESCHWÄRZT:secret.telegram_bot_token]", checked.text)
        self.assertEqual(checked.redactions, ("secret.telegram_bot_token",))
        self.assertIn("REDACTED", checked.flags)

    def test_multiple_secret_types(self):
        key = "sk-" + secrets.token_hex(16)
        pem = "-----BEGIN " + "PRIVATE KEY-----\nabc\n-----END " + "PRIVATE KEY-----"
        text = f"a {key} b {pem} c password=hunter2hunter2"
        checked = check_output(text, max_chars=1000)
        self.assertNotIn(key, checked.text)
        self.assertNotIn("BEGIN PRIVATE KEY", checked.text)
        self.assertNotIn("hunter2hunter2", checked.text)
        self.assertEqual(set(checked.redactions),
                         {"secret.openai_key", "secret.private_key_block", "secret.assignment"})

    def test_token_in_bot_url_redacted(self):
        token = "123456789:" + "B" * 34 + "-"
        checked = check_output(f"Fehler bei https://api.telegram.org/bot{token}/sendMessage", max_chars=1000)
        self.assertNotIn(token, checked.text)
        self.assertNotIn("B" * 34, checked.text)
        self.assertEqual(checked.redactions, ("secret.telegram_bot_token",))

    def test_truncation_marked(self):
        checked = check_output("x" * 20000, max_chars=100)
        self.assertTrue(checked.truncated)
        self.assertEqual(checked.text, "x" * 100 + TRUNCATION_MARK)
        self.assertIn("OUTPUT_TRUNCATED", checked.flags)

    def test_redact_before_truncate(self):
        token = fake_bot_token()
        checked = check_output("A" * 95 + token, max_chars=100)
        self.assertNotIn(token[:10], checked.text)

    def test_clean_output_unchanged(self):
        checked = check_output("Alles gut.", max_chars=100)
        self.assertEqual((checked.text, checked.redactions, checked.truncated), ("Alles gut.", (), False))


class GatewayResultCheckTests(GatewayTestCase):
    def gateway_with_fake(self, mode, *extra, config=None):
        overrides = deep_merge({"codex": {"command_template": fake_codex_template(mode, *extra)}}, config or {})
        return self.gateway(overrides, codex_runner=GuardedSubprocessRunner(self.root / "work"))

    def test_gateway_redacts_codex_output(self):
        gateway = self.gateway_with_fake("secret")
        result = gateway.handle(self.request(1, "#public zeig mir was"))
        self.assertEqual(result.handling, Handling.REPLY)
        self.assertIn("[GESCHWÄRZT:secret.telegram_bot_token]", result.reply_text)
        self.assertIn("REDACTED", result.flags)
        outcome = [r for r in self.log_records(gateway) if r["phase"] == "outcome"][-1]
        self.assertEqual(outcome["redactions"], ["secret.telegram_bot_token"])

    def test_gateway_truncates_long_output(self):
        gateway = self.gateway_with_fake("big_answer", "20000", config={"limits": {"max_reply_chars": 1000}})
        result = gateway.handle(self.request(2, "#public lang"))
        self.assertIn("OUTPUT_TRUNCATED", result.flags)
        self.assertEqual(len(result.reply_text), 1000 + len(TRUNCATION_MARK))

    def test_gateway_runner_output_limit_is_failure(self):
        gateway = self.gateway_with_fake("flood", "100000", config={"codex": {"max_output_bytes": 1000}})
        result = gateway.handle(self.request(3, "#public viel"))
        self.assertEqual((result.handling, result.code), (Handling.FAILED, "OUTPUT_LIMIT"))


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