"""FRSME-MEI012 — notify_newly_stalled dispatches to MEL officers + SME admins."""
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.models import SMEHubTrackingRecord
from apps.mel.tracking.services import notify_newly_stalled
from apps.smehub.onboarding.models import EntrepreneurProfile

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


@pytest.fixture
def admin():
    return User.objects.create_user(
        email="adm-sn@example.com", password="x",
        is_superuser=True, is_staff=True, role=UserRole.SYSTEM_ADMIN,
    )


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


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


@pytest.fixture
def entrepreneur(admin):
    user = User.objects.create_user(email="ent-sn@example.com", password="x", role=UserRole.ENTREPRENEUR)
    profile = EntrepreneurProfile.objects.create(user=user, country="UG", organisation="Co")
    profile.verify(by_user=admin)
    profile.save()
    return profile


@pytest.fixture
def stalled_record(entrepreneur):
    record = SMEHubTrackingRecord.objects.create(entrepreneur=entrepreneur, is_stalled=True)
    return record


def test_notify_newly_stalled_calls_bulk_notify(stalled_record, mel_officer, sme_admin):
    """MEL officers and SME admins receive a notification."""
    with patch("apps.smehub._shared.notifications.bulk_notify_smehub") as mock_bulk:
        sent_count = notify_newly_stalled([stalled_record], threshold_days=90)
    assert sent_count >= 2
    args, kwargs = mock_bulk.call_args
    recipients = args[0]
    emails = {u.email for u in recipients}
    assert "mel-sn@example.com" in emails
    assert "sme-sn@example.com" in emails
    assert "90 days" in args[1]


def test_notify_newly_stalled_no_recipients_returns_zero(stalled_record):
    """No MEL officers/admins → no-op, return 0."""
    # Deactivate any MEL officers that might already exist
    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:
        sent = notify_newly_stalled([stalled_record], threshold_days=60)
    assert sent == 0
    mock_bulk.assert_not_called()


def test_notify_newly_stalled_empty_records_short_circuits(mel_officer):
    with patch("apps.smehub._shared.notifications.bulk_notify_smehub") as mock_bulk:
        sent = notify_newly_stalled([], threshold_days=30)
    assert sent == 0
    mock_bulk.assert_not_called()
