"""Tests for configurable RAG thresholds (Phase 1)."""
from __future__ import annotations

from datetime import date
from decimal import Decimal

import pytest

from apps.mel.indicators.models import (
    Indicator,
    IndicatorFrequency,
    IndicatorTarget,
    LogFrame,
    LogFrameLevel,
    LogFrameRow,
    RagStatus,
    RagThreshold,
)
from apps.mel.indicators.services import (
    calculate_progress,
    get_rag_thresholds,
    record_data_point,
)

pytestmark = pytest.mark.django_db


def _build(logframe_slug="rag-lf", green=None, amber=None):
    lf = LogFrame.objects.create(name=f"LF-{logframe_slug}", slug=logframe_slug)
    if green is not None and amber is not None:
        RagThreshold.objects.create(logframe=lf, green_min=green, amber_min=amber)
    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"ind-{logframe_slug}",
        name="Ind",
        data_source="manual",
        unit="count",
        calculation_method="Count of qualifying events.",
        frequency=IndicatorFrequency.MONTHLY,
    )
    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("10"),
    )
    return lf, ind


def test_get_rag_thresholds_falls_back_to_settings_default():
    lf, _ = _build(logframe_slug="rag-fallback")
    green, amber = get_rag_thresholds(lf)
    assert green == 85.0
    assert amber == 60.0


def test_get_rag_thresholds_reads_per_logframe_override():
    lf, _ = _build(logframe_slug="rag-override", green=Decimal("90"), amber=Decimal("70"))
    green, amber = get_rag_thresholds(lf)
    assert green == 90.0
    assert amber == 70.0


def test_calculate_progress_uses_per_logframe_override():
    """At 80% of target: default thresholds → AMBER; tighter thresholds (90/70) → still AMBER;
    looser thresholds (70/40) → GREEN."""
    _, ind_default = _build(logframe_slug="rag-default-2")
    record_data_point(
        indicator=ind_default,
        value=8,
        period_label="2026-04",
        source_module="t",
        source_event="t",
        source_object_id="a",
        auto_verify=True,
    )
    p = calculate_progress(ind_default, "2026-04")
    assert p["percent"] == pytest.approx(80.0)
    assert p["rag"] == RagStatus.AMBER

    _, ind_tight = _build(logframe_slug="rag-tight", green=Decimal("90"), amber=Decimal("70"))
    record_data_point(
        indicator=ind_tight,
        value=8,
        period_label="2026-04",
        source_module="t",
        source_event="t",
        source_object_id="b",
        auto_verify=True,
    )
    assert calculate_progress(ind_tight, "2026-04")["rag"] == RagStatus.AMBER

    _, ind_loose = _build(logframe_slug="rag-loose", green=Decimal("70"), amber=Decimal("40"))
    record_data_point(
        indicator=ind_loose,
        value=8,
        period_label="2026-04",
        source_module="t",
        source_event="t",
        source_object_id="c",
        auto_verify=True,
    )
    assert calculate_progress(ind_loose, "2026-04")["rag"] == RagStatus.GREEN


def test_rag_threshold_rejects_green_below_amber():
    from django.core.exceptions import ValidationError

    lf = LogFrame.objects.create(name="LF-bad", slug="rag-bad")
    bad = RagThreshold(logframe=lf, green_min=Decimal("50"), amber_min=Decimal("60"))
    with pytest.raises(ValidationError):
        bad.full_clean()
