from decimal import Decimal, ROUND_HALF_UP
from datetime import timedelta

from django.db import transaction
from django.db.models import Sum
from django.utils import timezone

from admin_panel.models import Investment, Scheme
from admin_panel.services import daily_investor_soft_debit, diamond_interest_till_date
from .models import AgentInvestmentShare, AgentLedgerEntry


def money(value):
    return Decimal(value or 0).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)


def generate_daily_agent_ledger(entry_date=None):
    """Create one daily SOFT_DEBIT per assigned Agent investment share.

    The Agent earns a percentage of the investor's daily accrued profit only.
    Principal is never included in the Agent commission calculation.
    """
    entry_date = entry_date or timezone.localdate()
    created = []
    shares = AgentInvestmentShare.objects.filter(
        investment__deleted_at__isnull=True,
        investment__status=Investment.Status.ACTIVE,
        effective_from__lte=entry_date,
    ).select_related("agent", "investment", "investment__investor", "investment__business", "investment__scheme")

    for share in shares:
        inv = share.investment
        if inv.investment_date > entry_date:
            continue
        if inv.maturity_date and entry_date > inv.maturity_date:
            continue

        # Platinum begins on the first actual contribution date.
        if inv.scheme.category == Scheme.Categories.PLATINUM:
            first = inv.recurring_contributions.filter(
                contribution_date__lte=entry_date,
                deleted_at__isnull=True,
            ).order_by("contribution_date").first()
            if not first:
                continue
            start_date = max(first.contribution_date, share.effective_from)
        else:
            start_date = max(inv.investment_date, share.effective_from)

        if entry_date < start_date:
            continue

        exists = AgentLedgerEntry.objects.filter(
            investment=inv,
            entry_date=entry_date,
            entry_type=AgentLedgerEntry.EntryTypes.SOFT_DEBIT,
        ).exists()
        if exists:
            continue

        # The same daily accrual basis used by the existing investor ledger.
        daily_profit = daily_investor_soft_debit(inv, entry_date)
        commission = money(daily_profit * Decimal(share.profit_percentage) / Decimal("100"))
        if commission <= 0:
            continue

        entry = AgentLedgerEntry.objects.create(
            agent=share.agent,
            investment=inv,
            investor=inv.investor,
            business=inv.business,
            entry_date=entry_date,
            entry_type=AgentLedgerEntry.EntryTypes.SOFT_DEBIT,
            amount=commission,
            profit_percentage=share.profit_percentage,
            description=f"Agent profit share: {share.profit_percentage}% of daily investor return.",
            reference=f"AGENT-{share.agent_id}-INV-{inv.pk}-{entry_date}",
        )
        created.append(entry.pk)
    return created
