from datetime import date
from decimal import Decimal

import pytest
from django.core.exceptions import ValidationError

from apps.mel.indicators.models import (
    IndicatorFrequency,
    IndicatorTarget,
    LogFrame,
    LogFrameLevel,
    LogFrameRow,
    Indicator,
)

pytestmark = pytest.mark.django_db


def _seed_hierarchy():
    lf = LogFrame.objects.create(name="Test LF", slug="test-lf")
    impact = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.IMPACT, title="Impact A")
    outcome = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTCOME, title="Outcome A", parent=impact)
    output = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.OUTPUT, title="Output A", parent=outcome)
    return lf, impact, outcome, output


def test_impact_row_cannot_have_parent():
    lf = LogFrame.objects.create(name="LF", slug="lf")
    impact = LogFrameRow.objects.create(logframe=lf, level=LogFrameLevel.IMPACT, title="Impact")
    # A second impact cannot point at the first.
    bad = LogFrameRow(logframe=lf, level=LogFrameLevel.IMPACT, title="Impact 2", parent=impact)
    with pytest.raises(ValidationError):
        bad.full_clean()


def test_non_impact_row_requires_parent():
    lf = LogFrame.objects.create(name="LF", slug="lf")
    orphan = LogFrameRow(logframe=lf, level=LogFrameLevel.OUTPUT, title="Dangling output")
    with pytest.raises(ValidationError):
        orphan.full_clean()


def test_parent_level_must_be_higher_in_chain():
    _, _, outcome, output = _seed_hierarchy()
    # Trying to set an Output as the parent of an Outcome should fail.
    outcome.parent = output
    with pytest.raises(ValidationError):
        outcome.full_clean()


def test_indicator_target_baseline_required_before_target():
    _, _, _, output = _seed_hierarchy()
    ind = Indicator.objects.create(
        logframe_row=output,
        code="x-001",
        name="X",
        data_source="ds",
        frequency=IndicatorFrequency.MONTHLY,
    )
    t = IndicatorTarget(
        indicator=ind,
        period_label="2026-Q1",
        period_start=date(2026, 1, 1),
        period_end=date(2026, 3, 31),
        baseline_value=None,
        target_value=Decimal("100"),
    )
    with pytest.raises(ValidationError):
        t.full_clean()
