from __future__ import annotations

from datetime import datetime, timedelta


def test_is_in_cooldown_handles_none_and_iso_and_datetime():
    from backend.notifications.alert_evaluator import _is_in_cooldown

    assert _is_in_cooldown({"last_triggered_at": None}) is False

    old = (datetime.utcnow() - timedelta(hours=2)).isoformat()
    assert _is_in_cooldown({"last_triggered_at": old, "cooldown_minutes": 30}) is False

    recent_dt = datetime.utcnow()
    assert _is_in_cooldown({"last_triggered_at": recent_dt, "cooldown_minutes": 60}) is True


def test_security_attack_volume_fires_and_logs(monkeypatch):
    import backend.notifications.alert_evaluator as ae

    sent = {"count": 0}

    def fake_send_alert(*, webhook_url, rule, trigger_value, threshold_value, dashboard_base_url=None):
        sent["count"] += 1
        return {"success": True, "status_code": 200, "message": "ok"}

    class FakeStorage:
        def __init__(self):
            self.alert_logs = []
            self.updated = []

        def get_enabled_alert_rules_for_project(self, project: str):
            # Security events pass org slug as project.
            return [
                {
                    "rule_id": "00000000-0000-0000-0000-000000000001",
                    "project": project,
                    "name": "Attack Volume",
                    "alert_type": "attack_volume",
                    "webhook_url": "https://example.invalid/webhook",
                    "cooldown_minutes": 0,
                    "last_triggered_at": None,
                    "config": {"count": 1, "window_minutes": 60},
                    "source_filter": None,
                }
            ]

        def get_attack_count_in_window(self, project: str, window_minutes: int, source_filter=None):
            return 2

        def create_alert_log_entry(self, entry):
            self.alert_logs.append(entry)

        def update_alert_last_triggered(self, rule_id):
            self.updated.append(rule_id)

    storage = FakeStorage()
    monkeypatch.setattr(ae, "get_notification_storage", lambda: storage)
    monkeypatch.setattr(ae, "send_alert", fake_send_alert)

    checks = ae.evaluate_alerts_on_security_event("cascade")
    assert checks >= 1
    assert sent["count"] == 1
    assert storage.alert_logs and storage.alert_logs[0]["delivery_status"] == "sent"
    assert storage.updated


def test_error_rate_does_not_fire_when_in_cooldown(monkeypatch):
    import backend.notifications.alert_evaluator as ae

    sent = {"count": 0}

    def fake_send_alert(*, webhook_url, rule, trigger_value, threshold_value, dashboard_base_url=None):
        sent["count"] += 1
        return {"success": True, "status_code": 200, "message": "ok"}

    class FakeStorage:
        def __init__(self):
            self.alert_logs = []

        def get_enabled_alert_rules_for_project(self, project: str):
            return [
                {
                    "rule_id": "00000000-0000-0000-0000-000000000002",
                    "project": project,
                    "name": "Error Rate",
                    "alert_type": "error_rate",
                    "webhook_url": "https://example.invalid/webhook",
                    "cooldown_minutes": 60,
                    "last_triggered_at": datetime.utcnow().isoformat(),
                    "config": {"threshold": 0.01, "window_minutes": 30},
                }
            ]

        def get_error_rate_in_window(self, project: str, window_minutes: int):
            return {"total_traces": 10, "error_traces": 5, "error_rate": 0.5}

        def create_alert_log_entry(self, entry):
            self.alert_logs.append(entry)

        def update_alert_last_triggered(self, rule_id):
            pass

    storage = FakeStorage()
    monkeypatch.setattr(ae, "get_notification_storage", lambda: storage)
    monkeypatch.setattr(ae, "send_alert", fake_send_alert)

    _ = ae.evaluate_alerts_on_trace_complete("cascade/projectA")
    assert sent["count"] == 0
    assert storage.alert_logs == []

