"""End-to-end: record a datapoint → signal fires → RED RAG → Notification row created.

Verifies the Phase 1 alert backbone (FRMFL012).
"""
from __future__ import annotations

from datetime import date
from decimal import Decimal

import pytest
from django.contrib.auth import get_user_model

from apps.core.notifications.models import Notification
from apps.mel.indicators.models import (
    Indicator,
    IndicatorFrequency,
    IndicatorTarget,
    LogFrame,
    LogFrameLevel,
    LogFrameRow,
)
from apps.mel.indicators.services import record_data_point

# transaction=True so Django commits and fires on_commit callbacks
# (the signal → RAG re-score → alert dispatch chain).
pytestmark = pytest.mark.django_db(transaction=True)

User = get_user_model()


def _build_with_owners(*, slug: str):
    owner = User.objects.create_user(email=f"owner-{slug}@example.com", password="x")
    officer = User.objects.create_user(email=f"officer-{slug}@example.com", password="x")

    lf = LogFrame.objects.create(name=f"Alerts LF {slug}", slug=f"alerts-lf-{slug}", owner=owner)
    impact = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.IMPACT, title="I")
    outcome = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTCOME, title="O", parent=impact)
    output = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTPUT, title="P", parent=outcome)
    ind = Indicator.objects.create(
        logframe_row=output,
        code=f"alerts-ind-{slug}",
        name="Alerts indicator",
        data_source="m",
        unit="count",
        calculation_method="Count of events.",
        frequency=IndicatorFrequency.MONTHLY,
        responsible=officer,
    )
    IndicatorTarget.objects.create(
        indicator=ind,
        period_label="2026-04",
        period_start=date(2026, 4, 1),
        period_end=date(2026, 4, 30),
        baseline_value=Decimal("0"),
        target_value=Decimal("100"),
    )
    return lf, ind, officer, owner


def test_red_rag_dispatches_notifications_to_responsible_and_owner():
    lf, ind, officer, owner = _build_with_owners(slug="red")

    # 40% of target → RED under defaults.
    record_data_point(
        indicator=ind,
        value=40,
        period_label="2026-04",
        source_module="m",
        source_event="e",
        source_object_id="red-1",
        auto_verify=True,
    )

    notifs = Notification.objects.filter(verb=Notification.Verb.MEL_INDICATOR_OFF_TRACK)
    recipients = set(notifs.values_list("recipient_id", flat=True))

    assert len(recipients) == 2
    assert officer.pk in recipients
    assert owner.pk in recipients
    message = notifs.first().message
    assert "alerts-ind-red" in message
    assert "off track" in message.lower()


def test_green_rag_does_not_dispatch_alert():
    lf, ind, officer, owner = _build_with_owners(slug="green")

    # 95% of target → GREEN under defaults.
    record_data_point(
        indicator=ind,
        value=95,
        period_label="2026-04",
        source_module="m",
        source_event="e",
        source_object_id="green-1",
        auto_verify=True,
    )

    assert not Notification.objects.filter(verb=Notification.Verb.MEL_INDICATOR_OFF_TRACK).exists()


def test_amber_rag_does_not_dispatch_alert():
    """AMBER is a watch-list state, not an alert state (plan: alerts fire on RED only)."""
    lf, ind, officer, owner = _build_with_owners(slug="amber")

    # 70% of target → AMBER under defaults.
    record_data_point(
        indicator=ind,
        value=70,
        period_label="2026-04",
        source_module="m",
        source_event="e",
        source_object_id="amber-1",
        auto_verify=True,
    )

    assert not Notification.objects.filter(verb=Notification.Verb.MEL_INDICATOR_OFF_TRACK).exists()
