"""
Management command: fix_direct_incentive_wallet

Problem:
  Previous logic in process_direct_incentive() split the net payout:
    - (net - repurchase)  → EARNINGS  (main wallet)
    - repurchase          → REPURCHASE (repurchase wallet)

  The repurchase portion (≈5% of gross) is an admin-side deduction component and
  should NEVER have gone to the repurchase wallet. Direct incentive must always
  credit the main (EARNINGS) wallet in full.

Fix applied here:
  1. Find every WalletLedger row with:
       source_type = DIRECT_INCENTIVE
       transaction_type = CREDIT
       wallet_type = REPURCHASE   (these are the wrongly-placed _RP entries)

  2. For each affected user: sum the misrouted amounts.

  3. In a single atomic transaction per user:
       a. Change wallet_type of those ledger rows to EARNINGS.
       b. Add the summed amount to wallet.main_balance.
       c. Subtract the summed amount from wallet.repurchase_balance.

  Use --dry-run to preview without making changes.
"""

from decimal import Decimal

from django.core.management.base import BaseCommand
from django.db import transaction

from apps.business.wallet.models import Wallet, WalletLedger


class Command(BaseCommand):
    help = "Move misrouted DIRECT_INCENTIVE credits from repurchase wallet to main wallet"

    def add_arguments(self, parser):
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Preview affected rows without writing changes",
        )

    def handle(self, *args, **options):
        dry_run = options["dry_run"]

        # All DIRECT_INCENTIVE credits that landed in repurchase wallet
        misrouted_qs = WalletLedger.objects.filter(
            source_type=WalletLedger.SourceType.DIRECT_INCENTIVE,
            transaction_type=WalletLedger.TransactionType.CREDIT,
            wallet_type=WalletLedger.WalletType.REPURCHASE,
        ).select_related("wallet")

        total_rows = misrouted_qs.count()

        if total_rows == 0:
            self.stdout.write(self.style.SUCCESS("No misrouted DIRECT_INCENTIVE entries found. Nothing to fix."))
            return

        self.stdout.write(
            self.style.WARNING(
                f"Found {total_rows} misrouted DIRECT_INCENTIVE ledger row(s) across "
                f"{misrouted_qs.values('user_id').distinct().count()} user(s)."
            )
        )

        if dry_run:
            self.stdout.write(self.style.NOTICE("DRY-RUN — no changes will be written.\n"))

        # Group by user
        # .order_by() clears Meta.ordering so DISTINCT works correctly on a single column
        user_ids = list(misrouted_qs.order_by("user_id").values_list("user_id", flat=True).distinct())

        fixed_users = 0
        fixed_rows = 0
        total_moved = Decimal("0.00")

        for user_id in user_ids:
            user_rows = misrouted_qs.filter(user_id=user_id)
            user_amount = sum(r.amount for r in user_rows)

            self.stdout.write(
                f"  user_id={user_id}  rows={user_rows.count()}  amount={user_amount}"
            )

            if dry_run:
                fixed_users += 1
                fixed_rows += user_rows.count()
                total_moved += user_amount
                continue

            try:
                with transaction.atomic():
                    # Re-fetch inside transaction with lock
                    wallet = Wallet.objects.select_for_update().get(user_id=user_id)

                    # Guard: repurchase balance must cover the move
                    # If repurchase_balance < ledger sum, move only what's available.
                    # The gap means some repurchase funds were already spent; we correct
                    # all ledger entries regardless and cap the wallet adjustment.
                    actual_move = min(user_amount, wallet.repurchase_balance)
                    if actual_move < user_amount:
                        self.stdout.write(
                            self.style.WARNING(
                                f"  PARTIAL user_id={user_id}: ledger_sum={user_amount}, "
                                f"repurchase_balance={wallet.repurchase_balance} "
                                f"– moving {actual_move} (gap of {user_amount - actual_move} "
                                f"already spent from repurchase wallet)"
                            )
                        )

                    # Fix all ledger rows (wallet_type → EARNINGS) regardless
                    user_rows.update(wallet_type=WalletLedger.WalletType.EARNINGS)

                    # Adjust wallet balances by actual available amount
                    wallet.main_balance += actual_move
                    wallet.repurchase_balance -= actual_move
                    wallet.save(update_fields=["main_balance", "repurchase_balance"])

                fixed_users += 1
                fixed_rows += user_rows.count()
                total_moved += user_amount
                self.stdout.write(
                    self.style.SUCCESS(
                        f"  FIXED user_id={user_id}: moved {user_amount} from repurchase → main"
                    )
                )
            except Exception as exc:
                self.stdout.write(
                    self.style.ERROR(f"  ERROR user_id={user_id}: {exc}")
                )

        action = "Would fix" if dry_run else "Fixed"
        self.stdout.write(
            self.style.SUCCESS(
                f"\n{action} {fixed_rows} ledger row(s) across {fixed_users} user(s). "
                f"Total amount moved: {total_moved}"
            )
        )
