from decimal import Decimal

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.purchase import PurchaseItem
from shop_management.views.data.stock import normalize_currency_code, resolve_shop_currency


class Command(BaseCommand):
    help = (
        "Repair destination stock rows that still point at another branch's "
        "Currency after stock transfers, so Total Stock Value by currency is correct."
    )

    def add_arguments(self, parser):
        parser.add_argument(
            "--shop",
            type=int,
            help="Only repair stocks for this destination shop id.",
        )
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Show what would change without writing.",
        )

    def handle(self, *args, **options):
        shop_id = options.get("shop")
        dry_run = options.get("dry_run")

        stocks = (
            Stock.objects.filter(
                is_deleted=False,
                purchase_item__isnull=False,
            )
            .select_related(
                "shop",
                "purchase_item",
                "purchase_item__currency",
                "purchase_item__purchase",
                "purchase_item__purchase__currency",
                "purchase_item__product",
            )
            .order_by("shop_id", "id")
        )
        if shop_id:
            stocks = stocks.filter(shop_id=shop_id)

        repaired = 0
        skipped = 0

        for stock in stocks.iterator():
            currency = stock.currency
            if not currency:
                skipped += 1
                continue
            if currency.shop_id == stock.shop_id:
                skipped += 1
                continue

            local_currency = resolve_shop_currency(
                stock.shop_id,
                currency,
                user=stock.created_by,
                create=True,
            )
            if not local_currency or local_currency.id == currency.id:
                skipped += 1
                continue

            self.stdout.write(
                f"Stock #{stock.id} ({stock.shop.name}): "
                f"{currency.title}#{currency.id} (shop {currency.shop_id}) -> "
                f"{local_currency.title}#{local_currency.id}"
            )

            if dry_run:
                repaired += 1
                continue

            with transaction.atomic():
                purchase_item = PurchaseItem.objects.select_for_update().filter(
                    pk=stock.purchase_item_id
                ).first()
                if not purchase_item:
                    skipped += 1
                    continue
                purchase_item.currency = local_currency
                purchase_item.save(update_fields=["currency", "updated_at"])
                purchase = purchase_item.purchase
                if purchase and (
                    purchase.currency_id is None
                    or purchase.currency.shop_id != stock.shop_id
                ):
                    purchase.currency = local_currency
                    purchase.save(update_fields=["currency", "updated_at"])
            repaired += 1

        # Report valuation for repaired shops (helpful after live repairs).
        summary_shops = (
            {shop_id}
            if shop_id
            else set(
                Stock.objects.filter(is_deleted=False, quantity__gt=0).values_list(
                    "shop_id", flat=True
                )
            )
        )
        for sid in sorted(summary_shops):
            totals = {}
            qty_total = Decimal("0")
            for stock in Stock.objects.filter(
                shop_id=sid,
                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
                price = Decimal(str(stock.average_buy_price or 0))
                totals[code] = totals.get(code, Decimal("0")) + qty * price
            value_text = ", ".join(
                f"{amount.quantize(Decimal('0.01'))} {code}"
                for code, amount in sorted(totals.items())
            ) or "0"
            self.stdout.write(
                self.style.NOTICE(
                    f"Shop {sid} valuation check: qty={qty_total} value=[{value_text}]"
                )
            )

        action = "Would repair" if dry_run else "Repaired"
        self.stdout.write(
            self.style.SUCCESS(f"{action} {repaired} stock row(s); skipped {skipped}.")
        )
