"""
Reverse ONE undo_source_transfer_reset pass (when Kabul went too low).

Current too-low example: ~9312023 AFG / 52843 USD
Target:                ~9612861 AFG / 63044 USD

  python manage.py redo_source_transfer_reset --shop=2 --dry-run
  python manage.py redo_source_transfer_reset --shop=2

Run ONCE only, then stop and check.
"""

from collections import defaultdict
from decimal import Decimal, ROUND_HALF_UP

from django.core.management.base import BaseCommand
from django.db import transaction

from shop_management.models.data.stock import Stock
from shop_management.models.data.stock_transfer import StockTransfer
from shop_management.views.data.stock import normalize_currency_code


TWOPLACES = Decimal("0.01")


def _shop_summary(shop_id):
    totals = {}
    qty_total = Decimal("0")
    for stock in Stock.objects.filter(
        shop_id=shop_id,
        is_deleted=False,
        quantity__gt=0,
        purchase_item__isnull=False,
        purchase_item__is_deleted=False,
        purchase_item__purchase__is_deleted=False,
    ).select_related(
        "purchase_item",
        "purchase_item__currency",
        "purchase_item__purchase__currency",
    ):
        qty = Decimal(str(stock.quantity or 0))
        qty_total += qty
        code = normalize_currency_code(stock.currency.title if stock.currency else "")
        if not code:
            continue
        totals[code] = totals.get(code, Decimal("0")) + qty * Decimal(
            str(stock.average_buy_price or 0)
        )
    return qty_total, {
        code: amount.quantize(TWOPLACES) for code, amount in sorted(totals.items())
    }


def _fmt(values):
    return ", ".join(f"{a} {c}" for c, a in values.items()) or "0"


class Command(BaseCommand):
    help = "Re-apply one source reset pass after undo went too far."

    def add_arguments(self, parser):
        parser.add_argument("--shop", type=int, required=True)
        parser.add_argument("--dry-run", action="store_true")

    def handle(self, *args, **options):
        shop_id = options["shop"]
        dry_run = options["dry_run"]

        qty, before = _shop_summary(shop_id)
        self.stdout.write(self.style.NOTICE(f"BEFORE: qty={qty} value=[{_fmt(before)}]"))

        outgoing = (
            StockTransfer.objects.filter(
                status=StockTransfer.Status.ACCEPTED,
                supplier_branch_id=shop_id,
                source_stock__isnull=False,
                source_stock__is_deleted=False,
            )
            .select_related("source_stock", "product")
            .order_by("source_stock_id", "id")
        )
        by_source = defaultdict(list)
        for t in outgoing:
            by_source[t.source_stock_id].append(t)

        fixed = 0
        for _sid, rows in by_source.items():
            stock = rows[0].source_stock
            if not stock:
                continue

            transferred_qty = Decimal("0")
            transfer_amount = Decimal("0")
            for t in rows:
                qty_t = Decimal(str(t.transfer_quantity or 0))
                transferred_qty += qty_t
                transfer_amount += qty_t * Decimal(str(t.sale_price or 0))

            remaining_qty = Decimal(str(stock.quantity or 0))
            if transferred_qty <= 0:
                continue
            pre_qty = remaining_qty + transferred_qty
            if pre_qty <= 0:
                continue

            old_avg = Decimal(str(stock.average_buy_price or 0))
            # Same as old --reset-source: A' = (R*C + T)/(R+Q)
            new_avg = (
                (remaining_qty * old_avg + transfer_amount) / pre_qty
            ).quantize(TWOPLACES, rounding=ROUND_HALF_UP)
            if new_avg == old_avg:
                continue

            name = (
                stock.purchase_item.product.name
                if stock.purchase_item and stock.purchase_item.product
                else "?"
            )
            self.stdout.write(f"Stock #{stock.id} {name}: avg {old_avg} -> {new_avg}")
            fixed += 1
            if dry_run:
                continue
            with transaction.atomic():
                locked = Stock.objects.select_for_update().filter(pk=stock.id).first()
                if not locked:
                    continue
                locked.average_buy_price = new_avg
                locked.save(update_fields=["average_buy_price", "updated_at"])

        if not dry_run:
            qty2, after = _shop_summary(shop_id)
            self.stdout.write(self.style.NOTICE(f"AFTER: qty={qty2} value=[{_fmt(after)}]"))
        self.stdout.write(
            self.style.SUCCESS(
                f"{'Would fix' if dry_run else 'Fixed'} {fixed} row(s)."
            )
        )
        self.stdout.write(
            "Goal ≈ 9612861 AFG / 63044 USD. Run this ONCE only, then stop."
        )
