"""Tests for DataPoint verify/reject workflow (fills FRMFL014–017 gap)."""
from __future__ import annotations

from datetime import date
from decimal import Decimal

import pytest
from django.contrib.auth import get_user_model

from apps.mel.indicators.models import (
    DataPoint,
    Indicator,
    IndicatorFrequency,
    IndicatorTarget,
    LogFrame,
    LogFrameLevel,
    LogFrameRow,
)
from apps.mel.indicators.services import (
    record_data_point,
    reject_datapoint,
    verify_datapoint,
)

pytestmark = pytest.mark.django_db

User = get_user_model()


def _mk_indicator():
    lf = LogFrame.objects.create(name="LF-V", slug="lf-verify")
    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="verify-ind",
        name="I",
        data_source="m",
        unit="count",
        calculation_method="Count.",
        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 ind


def test_verify_datapoint_transitions_status_and_stamps_verifier():
    ind = _mk_indicator()
    reviewer = User.objects.create_user(email="r@example.com", password="x")
    result = record_data_point(
        indicator=ind,
        value=3,
        period_label="2026-04",
        auto_verify=False,
        source_module="m",
        source_event="e",
        source_object_id="a",
    )
    assert result.data_point.status == DataPoint.Status.PENDING

    verified = verify_datapoint(result.data_point.pk, verified_by=reviewer)

    assert verified.status == DataPoint.Status.VERIFIED
    assert verified.verified_by_id == reviewer.pk
    assert verified.verified_at is not None


def test_reject_datapoint_records_reason_and_rejector():
    ind = _mk_indicator()
    reviewer = User.objects.create_user(email="r2@example.com", password="x")
    result = record_data_point(
        indicator=ind,
        value=7,
        period_label="2026-04",
        auto_verify=False,
        source_module="m",
        source_event="e",
        source_object_id="b",
    )

    rejected = reject_datapoint(
        result.data_point.pk, rejected_by=reviewer, reason="Evidence missing",
    )

    assert rejected.status == DataPoint.Status.REJECTED
    assert rejected.verified_by_id == reviewer.pk
    assert "[Rejected] Evidence missing" in rejected.qualitative_note


def test_verify_is_idempotent():
    ind = _mk_indicator()
    reviewer = User.objects.create_user(email="r3@example.com", password="x")
    result = record_data_point(
        indicator=ind,
        value=3,
        period_label="2026-04",
        auto_verify=False,
        source_module="m",
        source_event="e",
        source_object_id="a",
    )
    first = verify_datapoint(result.data_point.pk, verified_by=reviewer)
    second_time = first.verified_at
    # Second verify should be a no-op (same timestamp preserved).
    again = verify_datapoint(result.data_point.pk, verified_by=reviewer)
    assert again.verified_at == second_time
