"""G20 — Cross-system report sections.

Verifies that ``build_rims_funding_summary``, ``build_rep_completions_summary``,
and ``build_repository_outputs_summary`` lazily query their upstream apps and
return structured dicts ready for the report template.
"""
from __future__ import annotations

from datetime import date, timedelta
from decimal import Decimal

import pytest
from django.contrib.auth import get_user_model
from django.utils import timezone

from apps.core.authentication.models import Institution
from apps.mel.indicators.models import LogFrame
from apps.mel.reports.builders import (
    build_consolidated_data,
    build_rep_completions_summary,
    build_repository_outputs_summary,
    build_rims_funding_summary,
)
from apps.rims.finance.models import Budget, BudgetLine
from apps.rims.grants.models import Application, Award, GrantCall

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


@pytest.fixture
def applicant(db):
    inst = Institution.objects.create(name="G20 Inst", country="UG", is_member=True)
    user = User.objects.create_user(email="g20@example.com", password="x")
    user.institution = inst
    user.save()
    return user, inst


def _make_award(applicant_user, institution, *, programme_title="G20 prog", grant_id="G20-001"):
    call = GrantCall.objects.create(
        title=programme_title,
        slug=f"call-{grant_id.lower()}",
        opens_at=date.today() - timedelta(days=30),
        closes_at=date.today() + timedelta(days=30),
        status=GrantCall.Status.PUBLISHED,
    )
    app = Application.objects.create(
        call=call, applicant=applicant_user, institution=institution,
    )
    award = Award.objects.create(
        application=app,
        amount=Decimal("5000"),
        currency="USD",
        activation_date=date.today() - timedelta(days=10),
        project_end_date=date.today() + timedelta(days=180),
        status=Award.Status.ACTIVE,
    )
    budget = Budget.objects.create(
        award=award, name=f"{grant_id} budget", currency="USD", status=Budget.Status.APPROVED,
    )
    BudgetLine.objects.create(
        budget=budget, label="Personnel",
        category=BudgetLine.Category.PERSONNEL, amount=Decimal("3000"),
    )
    return award


def test_build_rims_funding_summary_aggregates_awards(applicant):
    user, inst = applicant
    _make_award(user, inst, grant_id="G20-A")
    _make_award(user, inst, grant_id="G20-B")
    out = build_rims_funding_summary(logframe=None)
    assert out["installed"] is True
    assert out["awards_count"] == 2
    assert out["active_count"] == 2
    assert out["closed_count"] == 0
    assert len(out["rows"]) == 2


def test_build_rep_completions_summary_returns_structure():
    # We don't depend on REP being installed in this test — accept either
    # installed=True/False, but ensure the return shape is valid.
    out = build_rep_completions_summary(logframe=None)
    assert "installed" in out
    if out["installed"]:
        assert "rows" in out
        assert "total_completions" in out


def test_build_repository_outputs_summary_returns_structure():
    out = build_repository_outputs_summary(logframe=None)
    assert "installed" in out
    if out["installed"]:
        assert "rows" in out
        assert "total" in out


def test_consolidated_data_includes_new_g20_sections(applicant):
    user, inst = applicant
    _make_award(user, inst, grant_id="G20-CONS")
    lf = LogFrame.objects.create(name="LF G20", slug="lf-g20")
    today = date.today()
    data = build_consolidated_data(
        logframe=lf,
        period_label="2026Q2",
        period_start=today - timedelta(days=30),
        period_end=today,
        sections=[
            "rims_funding_summary",
            "rep_completions_summary",
            "repository_outputs_summary",
        ],
    )
    assert "rims_funding_summary" in data
    assert "rep_completions_summary" in data
    assert "repository_outputs_summary" in data
    # Funding section is installed (we created an award above).
    assert data["rims_funding_summary"]["installed"] is True
    assert data["rims_funding_summary"]["awards_count"] >= 1
