import importlib
import json
import queue
import unittest
from unittest import mock


class WebhookTests(unittest.TestCase):
    def test_webhook_firing_payload_maps_to_event(self):
        mod = importlib.import_module("agent_guard.events.webhook")
        q = queue.Queue()
        body = json.dumps({
            "alerts": [
                {
                    "status": "firing",
                    "labels": {"severity": "critical", "remediation": "kill", "alertname": "mem_exhaustion_eta_crit"},
                    "annotations": {"summary": "Memory exhaustion ETA below 90s"},
                    "panelURL": "http://127.0.0.1:3000/d/system-monitor-overview?viewPanel=14",
                    "dashboardURL": "http://127.0.0.1:3000/d/system-monitor-overview",
                    "generatorURL": "http://127.0.0.1:9090/graph",
                    "valueString": "A=42",
                }
            ]
        })
        status = mod.handle_payload(q, body.encode("utf-8"))
        self.assertEqual(status, 202)
        event = q.get(timeout=2)
        self.assertEqual(event.tier, "critical")
        self.assertEqual(event.source, "grafana")
        self.assertEqual(event.reason, "Memory exhaustion ETA below 90s")
        self.assertEqual(event.info_url, "http://127.0.0.1:3000/d/system-monitor-overview?viewPanel=14")
        self.assertEqual(event.remediation, "kill")

    def test_webhook_resolved_payload_is_ignored(self):
        mod = importlib.import_module("agent_guard.events.webhook")
        q = queue.Queue()
        body = json.dumps({"alerts": [{"status": "resolved", "labels": {"severity": "warning"}}]})
        status = mod.handle_payload(q, body.encode("utf-8"))
        self.assertEqual(status, 202)
        self.assertTrue(q.empty())

    def test_webhook_malformed_payload_returns_400_and_thread_keeps_serving(self):
        mod = importlib.import_module("agent_guard.events.webhook")
        q = queue.Queue()
        good = json.dumps({"alerts": [{"status": "firing", "labels": {"severity": "warning", "alertname": "tmpfs_junk_warn"}}]})
        with mock.patch.object(mod, "journal_send") as journal_send:
            status_bad = mod.handle_payload(q, b"{")
            self.assertEqual(status_bad, 400)
            status = mod.handle_payload(q, good.encode("utf-8"))
            self.assertEqual(status, 202)
            event = q.get(timeout=2)
        journal_send.assert_called()
        self.assertEqual(event.source, "grafana")

    def test_webhook_refuses_non_loopback_bind(self):
        mod = importlib.import_module("agent_guard.events.webhook")
        with self.assertRaises(ValueError):
            mod.make_server(queue.Queue(), host="0.0.0.0", port=9099)
        with mock.patch("agent_guard.events.webhook.ThreadingHTTPServer", return_value=object()) as server_cls:
            server = mod.make_server(queue.Queue(), host="127.0.0.1", port=9099)
        self.assertIsNotNone(server)
        self.assertEqual(server_cls.call_args.args[0], ("127.0.0.1", 9099))


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