"""
Repair destination purchases created by Payment-ON stock transfers that are
missing the "Transfer from …" supplier (so Purchase Remained / Dashboard
Purchase Unpaid stay at 0).

Also fixes orphan no-supplier purchases that match a Payment-ON transfer
by date + product + qty when target_stock links are broken.

Example:

  python manage.py repair_transfer_purchase_suppliers --shop-name "Badakhshan Branch" --dry-run
  python manage.py repair_transfer_purchase_suppliers --shop-name "Badakhshan Branch"
"""

from decimal import Decimal

from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import Q

from shop_management.models.data.purchase import Purchase, PurchaseItem
from shop_management.models.data.shop import Shop
from shop_management.models.data.stock_transfer import StockTransfer
from shop_management.models.data.supplier import Supplier


class Command(BaseCommand):
    help = (
        "Attach missing 'Transfer from <source>' suppliers to Payment-ON "
        "transfer purchases so Purchase Unpaid / Remained show correctly."
    )

    def add_arguments(self, parser):
        parser.add_argument("--shop", type=int, help="Destination shop id")
        parser.add_argument("--shop-name", type=str, help="Destination shop name")
        parser.add_argument("--dry-run", action="store_true")

    def handle(self, *args, **options):
        shop = self._resolve_shop(options)
        if not shop:
            return

        dry_run = options["dry_run"]
        fixed = 0
        skipped = 0
        self.stdout.write(self.style.MIGRATE_HEADING(f"=== {shop.name} (id={shop.id}) ==="))

        transfers = (
            StockTransfer.objects.filter(
                customer_branch=shop,
                status=StockTransfer.Status.ACCEPTED,
                show_payment_button=True,
            )
            .select_related(
                "supplier_branch",
                "product",
                "target_stock",
                "target_stock__purchase_item",
                "target_stock__purchase_item__purchase",
                "target_stock__purchase_item__purchase__supplier",
            )
            .order_by("id")
        )

        for transfer in transfers:
            purchase = self._resolve_purchase(transfer, shop)
            if not purchase:
                skipped += 1
                self.stdout.write(
                    f"  SKIP {transfer.transfer_id}: no destination purchase found"
                )
                continue

            source_name = (
                transfer.supplier_branch.name if transfer.supplier_branch else "Unknown"
            )
            wanted_name = f"Transfer from {source_name}"
            current_name = purchase.supplier.name if purchase.supplier else "-"

            needs_supplier = not purchase.supplier_id or not str(
                current_name
            ).strip().lower().startswith("transfer from ")
            needs_amount_reset = Decimal(str(purchase.amount or 0)) != Decimal("0")

            if not needs_supplier and not needs_amount_reset:
                skipped += 1
                continue

            self.stdout.write(
                f"  {'Would fix' if dry_run else 'Fix'} {transfer.transfer_id}: "
                f"purchase#{purchase.id} supplier '{current_name}' -> '{wanted_name}' "
                f"amount {purchase.amount} -> 0 "
                f"(items={purchase.purchase_items.count()}, total={purchase.total_price})"
            )
            fixed += 1
            if dry_run:
                continue

            with transaction.atomic():
                supplier, _ = Supplier.objects.get_or_create(
                    shop_id=shop.id,
                    name=wanted_name,
                    defaults={"created_by": transfer.created_by},
                )
                update_fields = []
                if purchase.supplier_id != supplier.id:
                    purchase.supplier = supplier
                    update_fields.append("supplier")
                if needs_amount_reset:
                    purchase.amount = 0
                    update_fields.append("amount")
                if update_fields:
                    purchase.save(update_fields=update_fields + ["updated_at"])

        extra = 0
        qs = Purchase.objects.filter(
            shop=shop,
            is_deleted=False,
            supplier__name__istartswith="Transfer from ",
        ).exclude(amount=0)
        for purchase in qs:
            self.stdout.write(
                f"  {'Would clear' if dry_run else 'Clear'} discount amount on "
                f"purchase#{purchase.id} ({purchase.supplier.name}): {purchase.amount} -> 0"
            )
            extra += 1
            if dry_run:
                continue
            purchase.amount = 0
            purchase.save(update_fields=["amount", "updated_at"])

        self.stdout.write(
            self.style.SUCCESS(
                f"{'Would fix' if dry_run else 'Fixed'} {fixed} transfer purchase(s); "
                f"cleared amount on {extra}; skipped {skipped}."
            )
        )
        self.stdout.write(
            "Refresh Purchase List + Dashboard. "
            "Dashboard Paid/Unpaid should now match Purchase List totals."
        )

    def _resolve_purchase(self, transfer, shop):
        target = transfer.target_stock
        purchase_item = target.purchase_item if target else None
        if purchase_item and purchase_item.purchase_id:
            return purchase_item.purchase

        qty = int(transfer.transfer_quantity or 0)
        product_id = transfer.product_id
        transfer_date = transfer.transfer_date or transfer.accepted_date
        if not product_id or qty <= 0:
            return None

        items = (
            PurchaseItem.objects.filter(
                purchase__shop=shop,
                purchase__is_deleted=False,
                is_deleted=False,
                product_id=product_id,
                quantity=qty,
            )
            .filter(
                Q(purchase__supplier__isnull=True)
                | Q(purchase__supplier__name__istartswith="Transfer from ")
            )
            .select_related("purchase", "purchase__supplier")
            .order_by("-id")
        )
        if transfer_date:
            dated = items.filter(purchase__purchase_date=transfer_date)
            if dated.exists():
                items = dated
        match = items.first()
        return match.purchase if match else None

    def _resolve_shop(self, options):
        shop_id = options.get("shop")
        shop_name = (options.get("shop_name") or "").strip()
        if shop_id:
            shop = Shop.objects.filter(pk=shop_id).first()
        elif shop_name:
            shop = Shop.objects.filter(name__iexact=shop_name).first()
            if not shop:
                shop = Shop.objects.filter(name__icontains=shop_name).first()
        else:
            self.stderr.write(self.style.ERROR("Use --shop or --shop-name"))
            return None
        if not shop:
            self.stderr.write(self.style.ERROR("Shop not found."))
            return None
        return shop
