"""Slice C · MEL feed-handler critical-feed alerts (FRSME-MEI007).

Asserts that ``_alert_mel_officers`` dispatches a bulk notification when
called for any of the 6 critical feeds.
"""
from __future__ import annotations

from unittest.mock import patch

import pytest
from django.contrib.auth import get_user_model

from apps.core.permissions.roles import UserRole
from apps.mel.tracking import smehub_receivers

User = get_user_model()
pytestmark = pytest.mark.django_db


@pytest.fixture
def mel_officer():
    return User.objects.create_user(
        email="mel-cfa@example.com", password="x", role=UserRole.MEL_OFFICER, is_active=True,
    )


@pytest.fixture
def sme_admin():
    return User.objects.create_user(
        email="sme-cfa@example.com", password="x", role=UserRole.SME_ADMIN, is_active=True,
    )


@pytest.mark.parametrize("signal_name", sorted(smehub_receivers.CRITICAL_FEEDS))
def test_each_critical_feed_alerts_mel_officers(signal_name, mel_officer, sme_admin):
    """Every CRITICAL_FEEDS entry triggers a notification to MEL officers / admins."""
    with patch("apps.smehub._shared.notifications.bulk_notify_smehub") as mock_bulk:
        smehub_receivers._alert_mel_officers(signal_name, RuntimeError("simulated handler crash"))
    assert mock_bulk.called, f"No bulk notification for {signal_name}"
    args, kwargs = mock_bulk.call_args
    recipients = args[0]
    emails = {u.email for u in recipients}
    assert "mel-cfa@example.com" in emails
    assert "sme-cfa@example.com" in emails
    assert signal_name in args[1]
    assert "RuntimeError" in args[1]


def test_alert_is_best_effort_swallows_errors(mel_officer):
    """If bulk_notify_smehub itself raises, _alert_mel_officers must not propagate."""
    with patch(
        "apps.smehub._shared.notifications.bulk_notify_smehub",
        side_effect=Exception("notify broken"),
    ):
        # Should not raise.
        smehub_receivers._alert_mel_officers(
            "smehub_baseline_initialised", RuntimeError("crash"),
        )


def test_alert_skips_when_no_recipients():
    """No active MEL officers or admins → no-op (no bulk_notify call)."""
    User.objects.filter(role__in=("mel_officer", "sme_admin", "admin", "system_admin")).delete()
    with patch("apps.smehub._shared.notifications.bulk_notify_smehub") as mock_bulk:
        smehub_receivers._alert_mel_officers(
            "smehub_funding_secured", RuntimeError("crash"),
        )
    mock_bulk.assert_not_called()
