from decimal import Decimal

from django.core.management.base import BaseCommand

from apps.business.rewards.models import DistributorLevelProgress
from apps.business.schemes.models import OpportunityBundleLevel
from apps.business.wallet.models import Wallet, WalletLedger


class Command(BaseCommand):
    help = "Backfill sample LEVEL_REWARD claimed ledger entries for seeded data"

    def add_arguments(self, parser):
        parser.add_argument("--every", type=int, default=4, help="Claim one entry for every Nth distributor")
        parser.add_argument("--batch-size", type=int, default=2000)

    def handle(self, *args, **options):
        every = max(1, options["every"])
        batch_size = options["batch_size"]

        # Index opportunity_bundle levels once: opportunity_bundle_id -> payable levels in ascending order
        payable_level_map = {}
        levels = OpportunityBundleLevel.objects.order_by("opportunity_bundle_id", "level_number").values(
            "opportunity_bundle_id", "level_number", "reward_amount"
        )
        for lv in levels:
            amount = Decimal(lv["reward_amount"] or 0)
            if amount <= 0:
                continue
            payable_level_map.setdefault(lv["opportunity_bundle_id"], []).append((lv["level_number"], amount))

        progresses = (
            DistributorLevelProgress.objects
            .select_related("distributor__product__opportunity_bundle")
            .filter(distributor__user__email__endswith="@truewave.test", current_level__gt=0)
            .order_by("distributor_id")
        )

        rows = []
        total = 0
        wallet_map = {}

        for idx, p in enumerate(progresses.iterator(chunk_size=batch_size)):
            if idx % every != 0:
                continue

            dist = p.distributor
            opportunity_bundle_id = dist.product.opportunity_bundle_id if dist.product else None
            if not opportunity_bundle_id:
                continue

            payable = payable_level_map.get(opportunity_bundle_id, [])
            if not payable:
                continue

            target = next((t for t in payable if t[0] <= p.current_level), None)
            if not target:
                continue

            level_no, amount = target
            ref_id = f"LEVEL_REWARD_{dist.id}_{level_no}"
            if WalletLedger.objects.filter(reference_id=ref_id, source_type=WalletLedger.SourceType.LEVEL_REWARD).exists():
                continue

            wallet_id = wallet_map.get(dist.user_id)
            if not wallet_id:
                wallet, _ = Wallet.objects.get_or_create(user_id=dist.user_id)
                wallet_id = wallet.id
                wallet_map[dist.user_id] = wallet_id

            rows.append(
                WalletLedger(
                    user_id=dist.user_id,
                    wallet_id=wallet_id,
                    transaction_type=WalletLedger.TransactionType.CREDIT,
                    wallet_type=WalletLedger.WalletType.EARNINGS,
                    source_type=WalletLedger.SourceType.LEVEL_REWARD,
                    amount=amount,
                    reference_id=ref_id,
                )
            )

            if len(rows) >= batch_size:
                WalletLedger.objects.bulk_create(rows, batch_size=batch_size, ignore_conflicts=True)
                total += len(rows)
                rows = []

        if rows:
            WalletLedger.objects.bulk_create(rows, batch_size=batch_size, ignore_conflicts=True)
            total += len(rows)

        self.stdout.write(self.style.SUCCESS(f"Backfilled LEVEL_REWARD claims: {total}"))
