from decimal import Decimal
import django.db.models.deletion
from django.db import migrations, models


def _classify_title(title):
    raw = str(title or "").strip()
    if not raw:
        return "AFN"
    normalized = "".join(ch for ch in raw.lower() if ch.isalnum())
    if normalized in {"usd", "usdollar", "usddollar", "unitedstatesdollar", "dollar"} or "دالر" in raw or "$" in raw:
        return "USD"
    return "AFN"


def migrate_existing_opening_balances_and_payments(apps, schema_editor):
    Customer = apps.get_model("shop_management", "Customer")
    Supplier = apps.get_model("shop_management", "Supplier")
    FinancialOpeningBalance = apps.get_model("shop_management", "FinancialOpeningBalance")
    SupplierBalancePayment = apps.get_model("shop_management", "SupplierBalancePayment")

    for customer in Customer.objects.select_related("opening_balance_currency").all():
        legacy_ob = Decimal(str(customer.opening_balance or 0))
        curr_title = customer.opening_balance_currency.title if customer.opening_balance_currency_id else "AFN"
        code = _classify_title(curr_title)

        posted_fobs = FinancialOpeningBalance.objects.filter(
            customer_id=customer.id, status="POSTED"
        ).select_related("currency")

        afn_fob_total = Decimal("0")
        usd_fob_total = Decimal("0")
        for fob in posted_fobs:
            fob_code = _classify_title(fob.currency.title if fob.currency_id else "AFN")
            fob_amt = Decimal(str(fob.amount or 0))
            if fob_code == "USD":
                usd_fob_total += fob_amt
            else:
                afn_fob_total += fob_amt

        orig_afn = Decimal(str(customer.opening_balance_afn or 0))
        orig_usd = Decimal(str(customer.opening_balance_usd or 0))
        paid_afn = Decimal(str(customer.opening_balance_afn_paid or 0))
        paid_usd = Decimal(str(customer.opening_balance_usd_paid or 0))

        if orig_afn == 0 and orig_usd == 0:
            if code == "USD":
                if usd_fob_total > legacy_ob:
                    orig_usd = usd_fob_total
                    paid_usd = usd_fob_total - max(Decimal("0"), legacy_ob)
                elif legacy_ob > 0:
                    orig_usd = legacy_ob
            else:
                if afn_fob_total > legacy_ob:
                    orig_afn = afn_fob_total
                    paid_afn = afn_fob_total - max(Decimal("0"), legacy_ob)
                elif legacy_ob > 0:
                    orig_afn = legacy_ob

        if (
            orig_afn != Decimal(str(customer.opening_balance_afn or 0))
            or orig_usd != Decimal(str(customer.opening_balance_usd or 0))
            or paid_afn != Decimal(str(customer.opening_balance_afn_paid or 0))
            or paid_usd != Decimal(str(customer.opening_balance_usd_paid or 0))
        ):
            customer.opening_balance_afn = orig_afn
            customer.opening_balance_usd = orig_usd
            customer.opening_balance_afn_paid = paid_afn
            customer.opening_balance_usd_paid = paid_usd
            customer.save(
                update_fields=[
                    "opening_balance_afn",
                    "opening_balance_usd",
                    "opening_balance_afn_paid",
                    "opening_balance_usd_paid",
                ]
            )

    for supplier in Supplier.objects.select_related("opening_balance_currency").all():
        legacy_ob = Decimal(str(supplier.opening_balance or 0))
        curr_title = supplier.opening_balance_currency.title if supplier.opening_balance_currency_id else "AFN"
        code = _classify_title(curr_title)

        posted_fobs = FinancialOpeningBalance.objects.filter(
            supplier_id=supplier.id, status="POSTED"
        ).select_related("currency")

        afn_fob_total = Decimal("0")
        usd_fob_total = Decimal("0")
        for fob in posted_fobs:
            fob_code = _classify_title(fob.currency.title if fob.currency_id else "AFN")
            fob_amt = Decimal(str(fob.amount or 0))
            if fob_code == "USD":
                usd_fob_total += fob_amt
            else:
                afn_fob_total += fob_amt

        orig_afn = Decimal(str(supplier.opening_balance_afn or 0))
        orig_usd = Decimal(str(supplier.opening_balance_usd or 0))
        paid_afn = Decimal(str(supplier.opening_balance_afn_paid or 0))
        paid_usd = Decimal(str(supplier.opening_balance_usd_paid or 0))

        if orig_afn == 0 and orig_usd == 0:
            if code == "USD":
                if usd_fob_total > legacy_ob:
                    orig_usd = usd_fob_total
                    paid_usd = usd_fob_total - max(Decimal("0"), legacy_ob)
                elif legacy_ob > 0:
                    orig_usd = legacy_ob
            else:
                if afn_fob_total > legacy_ob:
                    orig_afn = afn_fob_total
                    paid_afn = afn_fob_total - max(Decimal("0"), legacy_ob)
                elif legacy_ob > 0:
                    orig_afn = legacy_ob

        if (
            orig_afn != Decimal(str(supplier.opening_balance_afn or 0))
            or orig_usd != Decimal(str(supplier.opening_balance_usd or 0))
            or paid_afn != Decimal(str(supplier.opening_balance_afn_paid or 0))
            or paid_usd != Decimal(str(supplier.opening_balance_usd_paid or 0))
        ):
            supplier.opening_balance_afn = orig_afn
            supplier.opening_balance_usd = orig_usd
            supplier.opening_balance_afn_paid = paid_afn
            supplier.opening_balance_usd_paid = paid_usd
            supplier.save(
                update_fields=[
                    "opening_balance_afn",
                    "opening_balance_usd",
                    "opening_balance_afn_paid",
                    "opening_balance_usd_paid",
                ]
            )

    for sbp in SupplierBalancePayment.objects.filter(settlement_currency__isnull=True):
        sbp.settlement_currency_id = sbp.currency_id
        sbp.settlement_exchange_rate = Decimal("1")
        sbp.settlement_amount = sbp.amount or Decimal("0")
        sbp.save(
            update_fields=[
                "settlement_currency_id",
                "settlement_exchange_rate",
                "settlement_amount",
            ]
        )


class Migration(migrations.Migration):

    dependencies = [
        ("shop_management", "0109_companysetting_logo"),
    ]

    operations = [
        migrations.AddField(
            model_name="customer",
            name="opening_balance_afn",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="customer",
            name="opening_balance_usd",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="customer",
            name="opening_balance_afn_paid",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="customer",
            name="opening_balance_usd_paid",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="supplier",
            name="opening_balance_afn",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="supplier",
            name="opening_balance_usd",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="supplier",
            name="opening_balance_afn_paid",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="supplier",
            name="opening_balance_usd_paid",
            field=models.DecimalField(
                blank=True, decimal_places=2, default=Decimal("0"), max_digits=14
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="secondary_exchange_rate",
            field=models.DecimalField(
                blank=True,
                decimal_places=6,
                help_text="Exchange rate used when cascading payment surplus into secondary debt currency.",
                max_digits=20,
                null=True,
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="allocated_to_afn",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Total AFN debt settled by this payment.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="allocated_to_usd",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Total USD debt settled by this payment.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="allocated_to_opening_afn",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Portion of this payment applied to AFN opening balance.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="allocated_to_opening_usd",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Portion of this payment applied to USD opening balance.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="settlement_currency",
            field=models.ForeignKey(
                blank=True,
                help_text="Currency of the supplier debt reduced by this payment.",
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="supplier_balance_payment_settlements",
                to="shop_management.currency",
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="settlement_exchange_rate",
            field=models.DecimalField(decimal_places=6, default=1, max_digits=20),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="settlement_amount",
            field=models.DecimalField(decimal_places=2, default=0, max_digits=18),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="secondary_exchange_rate",
            field=models.DecimalField(
                blank=True,
                decimal_places=6,
                help_text="Exchange rate used when cascading payment surplus into secondary debt currency.",
                max_digits=20,
                null=True,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="allocated_to_afn",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Total AFN debt settled by this payment.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="allocated_to_usd",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Total USD debt settled by this payment.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="allocated_to_opening_afn",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Portion of this payment applied to AFN opening balance.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="allocated_to_opening_usd",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Portion of this payment applied to USD opening balance.",
                max_digits=18,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="unallocated_amount",
            field=models.DecimalField(
                decimal_places=2,
                default=Decimal("0"),
                help_text="Overpayment or surplus credited with supplier for future purchases.",
                max_digits=18,
            ),
        ),
        migrations.RunPython(
            migrate_existing_opening_balances_and_payments,
            migrations.RunPython.noop,
        ),
    ]

