"""Seed KPI data for the Program Director dashboard demo."""
from __future__ import annotations

import random
from datetime import date, timedelta
from decimal import Decimal

from django.contrib.auth import get_user_model
from django.core.management.base import BaseCommand
from django.utils import timezone

User = get_user_model()

FUNDERS = [
    {
        "name": "Mastercard Foundation",
        "donor_type": "foundation",
        "country": "Canada",
        "amount": Decimal("2500000.00"),
        "currency": "USD",
    },
    {
        "name": "Bill & Melinda Gates Foundation",
        "donor_type": "foundation",
        "country": "United States",
        "amount": Decimal("1800000.00"),
        "currency": "USD",
    },
    {
        "name": "European Union",
        "donor_type": "multilateral",
        "country": "Belgium",
        "amount": Decimal("3200000.00"),
        "currency": "EUR",
    },
]


class Command(BaseCommand):
    help = "Seed Program Director KPI data — funders, funding records, tranches, cancellation requests"

    def add_arguments(self, parser):
        parser.add_argument("--clear", action="store_true", help="Remove previously seeded KPI data")

    def handle(self, *args, **options):
        from apps.rims.grants.models import (
            Application, Award, AwardCancellationRequest, AwardTranche,
            FundingRecord, GrantCall,
        )
        from apps.rims.operations.models import Donor

        if options["clear"]:
            FundingRecord.objects.filter(title__endswith="[seed]").delete()
            Donor.objects.filter(notes="seeded").delete()
            self.stdout.write(self.style.WARNING("Cleared seeded KPI data."))

        # Get the existing call to link to
        call = GrantCall.objects.filter(
            slug="call-for-applications-for-msc-agic-tech"
        ).first()
        if not call:
            self.stdout.write(self.style.ERROR("Call not found — run seed_scholarship_applicants first."))
            return

        # Get a grants manager to assign
        manager = User.objects.filter(role="grants_manager").first()
        finance_officer = User.objects.filter(
            role__in=["finance_officer", "admin"]
        ).first()

        today = date.today()

        for i, funder_data in enumerate(FUNDERS):
            # Create donor
            donor, _ = Donor.objects.get_or_create(
                name=funder_data["name"],
                defaults={
                    "donor_type": funder_data["donor_type"],
                    "country": funder_data["country"],
                    "notes": "seeded",
                },
            )
            self.stdout.write(f"  Donor: {donor.name}")

            # Create funding record
            start = today - timedelta(days=random.randint(180, 400))
            end = today + timedelta(days=random.randint(30, 500))
            fr = FundingRecord.objects.create(
                title=f"{donor.name} — RUFORUM Programme Support {2024 + i} [seed]",
                donor=donor,
                amount=funder_data["amount"],
                currency=funder_data["currency"],
                start_date=start,
                end_date=end,
                status=FundingRecord.Status.APPROVED,
                reporting_financial_frequency=FundingRecord.ReportingFrequency.QUARTERLY,
                grant_manager=manager,
                finance_officer=finance_officer,
                public_grant_id=f"SEED-{2024+i:04d}-{i+1:03d}",
            )
            self.stdout.write(f"  FundingRecord: {fr.title}")

            # Link the call to the first funding record
            if i == 0 and call.funding_record is None:
                call.funding_record = fr
                call.save(update_fields=["funding_record"])
                self.stdout.write(f"  Linked call '{call.title}' to {fr.title}")

            # Seed disbursed tranches on existing awards for this call
            if i == 0:
                awards = Award.objects.filter(
                    application__call=call
                ).exclude(status=Award.Status.CANCELLED)[:8]
                disbursed_count = 0
                for award in awards:
                    # Create a disbursed tranche
                    if not award.tranches.exists():
                        AwardTranche.objects.create(
                            award=award,
                            label="Tuition — Semester 1",
                            amount=Decimal("1500.00"),
                            due_on=today - timedelta(days=random.randint(30, 120)),
                            status=AwardTranche.Status.DISBURSED,
                            disbursed_at=timezone.now() - timedelta(days=random.randint(10, 90)),
                            sort_order=1,
                        )
                        disbursed_count += 1
                self.stdout.write(f"  Seeded {disbursed_count} disbursed tranches")

        # Seed cancellation requests
        awards_for_cancel = Award.objects.filter(
            application__call=call,
            status=Award.Status.ACTIVE,
        ).exclude(cancellation_requests__isnull=False)[:2]

        requester = User.objects.filter(role="grants_manager").first()
        cancel_reasons = [
            "Awardee has withdrawn from the programme due to personal circumstances.",
            "Awardee has failed to meet academic requirements for the scholarship.",
        ]
        created_cancellations = 0
        for award, reason in zip(awards_for_cancel, cancel_reasons):
            AwardCancellationRequest.objects.create(
                award=award,
                status=AwardCancellationRequest.Status.DIRECTOR_REVIEW,
                reason=reason,
                requested_by=requester,
            )
            created_cancellations += 1
        self.stdout.write(f"  Seeded {created_cancellations} cancellation requests")

        # Seed a ready-for-closeout award
        closeout_award = Award.objects.filter(
            application__call=call,
            status=Award.Status.ACTIVE,
        ).last()
        if closeout_award:
            closeout_award.status = Award.Status.READY_FOR_CLOSEOUT
            closeout_award.closeout_ready_at = timezone.now() - timedelta(days=5)
            closeout_award.save(update_fields=["status", "closeout_ready_at"])
            self.stdout.write(f"  Seeded 1 ready-for-closeout award")

        self.stdout.write(self.style.SUCCESS("\nDirector KPI data seeded. Visit /rims/grants/director/"))
