# Generated by Django 5.2.1 on 2026-10-20 08:41

import django.db.models.deletion
from decimal import Decimal
from django.conf import settings
from django.db import migrations, models


def forward_audit_unknown_currencies(apps, schema_editor):
    """
    Strictly read-only audit pass to detect and report customer and supplier records with
    ambiguous, unknown, or unclassified opening balance currencies.

    CRITICAL SAFETY GUARANTEES:
    - This migration operation does NOT mutate any data in the database.
    - It does NOT silently assign unknown currencies to AFN or USD.
    - Any affected historical records must be remediated manually by an administrator.
    """
    import sys
    Customer = apps.get_model("shop_management", "Customer")
    Supplier = apps.get_model("shop_management", "Supplier")

    def classify_code(curr):
        if not curr:
            return None
        title = (getattr(curr, "title", "") or "").strip().upper()
        name = (getattr(curr, "name", "") or "").strip().upper()
        symbol = (getattr(curr, "symbol", "") or "").strip().upper()
        for token in (title, name, symbol):
            if token in ("AFN", "AFGHANI", "؋", "AF"):
                return "AFN"
            if token in ("USD", "DOLLAR", "$"):
                return "USD"
        return None

    ambiguous_customers = []
    ambiguous_suppliers = []

    # Audit Customers with historical opening_balance > 0
    for c in Customer.objects.filter(opening_balance__gt=0).select_related("opening_balance_currency"):
        curr = c.opening_balance_currency
        code = classify_code(curr)
        if code is None:
            ambiguous_customers.append({
                "id": c.id,
                "name": c.name,
                "opening_balance": c.opening_balance,
                "currency_id": c.opening_balance_currency_id,
                "currency_title": getattr(curr, "title", None) if curr else None,
            })

    # Audit Suppliers with historical opening_balance > 0
    for s in Supplier.objects.filter(opening_balance__gt=0).select_related("opening_balance_currency"):
        curr = s.opening_balance_currency
        code = classify_code(curr)
        if code is None:
            ambiguous_suppliers.append({
                "id": s.id,
                "name": s.name,
                "opening_balance": s.opening_balance,
                "currency_id": s.opening_balance_currency_id,
                "currency_title": getattr(curr, "title", None) if curr else None,
            })

    if ambiguous_customers or ambiguous_suppliers:
        lines = [
            "\n" + "=" * 80,
            "AUDIT NOTICE: Records with ambiguous/unclassified opening balance currencies.",
            "IMPORTANT: NO records were modified. Historical data is strictly preserved.",
            "SAFE REMEDIATION: Administrators must manually review each flagged entity and",
            "set opening_balance_afn or opening_balance_usd explicitly.",
            "-" * 80,
        ]
        if ambiguous_customers:
            lines.append(f"Ambiguous Customers ({len(ambiguous_customers)} found):")
            for ac in ambiguous_customers:
                lines.append(f"  - Customer #{ac['id']} ({ac['name']}): balance={ac['opening_balance']}, currency_id={ac['currency_id']}, title={ac['currency_title']}")
        if ambiguous_suppliers:
            lines.append(f"Ambiguous Suppliers ({len(ambiguous_suppliers)} found):")
            for asupp in ambiguous_suppliers:
                lines.append(f"  - Supplier #{asupp['id']} ({asupp['name']}): balance={asupp['opening_balance']}, currency_id={asupp['currency_id']}, title={asupp['currency_title']}")
        lines.append("=" * 80 + "\n")
        sys.stdout.write("\n".join(lines) + "\n")

    return {
        "ambiguous_customers": ambiguous_customers,
        "ambiguous_suppliers": ambiguous_suppliers,
    }


class Migration(migrations.Migration):

    dependencies = [
        (
            "shop_management",
            "0110_dual_currency_opening_balances_and_supplier_settlement",
        ),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.AddField(
            model_name="customerbalancepayment",
            name="client_reference_id",
            field=models.CharField(
                blank=True, db_index=True, max_length=100, null=True
            ),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="is_void",
            field=models.BooleanField(db_index=True, default=False),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="void_reason",
            field=models.TextField(blank=True, default=""),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="voided_at",
            field=models.DateTimeField(blank=True, null=True),
        ),
        migrations.AddField(
            model_name="customerbalancepayment",
            name="voided_by",
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="customer_balance_payments_voided",
                to=settings.AUTH_USER_MODEL,
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="client_reference_id",
            field=models.CharField(
                blank=True, db_index=True, max_length=100, null=True
            ),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="is_void",
            field=models.BooleanField(db_index=True, default=False),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="void_reason",
            field=models.TextField(blank=True, default=""),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="voided_at",
            field=models.DateTimeField(blank=True, null=True),
        ),
        migrations.AddField(
            model_name="supplierbalancepayment",
            name="voided_by",
            field=models.ForeignKey(
                blank=True,
                null=True,
                on_delete=django.db.models.deletion.PROTECT,
                related_name="supplier_balance_payments_voided",
                to=settings.AUTH_USER_MODEL,
            ),
        ),
        migrations.CreateModel(
            name="CustomerBalancePaymentAllocation",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True, null=True)),
                ("updated_at", models.DateTimeField(auto_now=True, null=True)),
                (
                    "target_type",
                    models.CharField(
                        choices=[
                            ("OPENING_BALANCE", "Opening Balance"),
                            ("SALE", "Sale"),
                            ("DEBTOR_LOAN", "Debtor Loan"),
                        ],
                        max_length=30,
                    ),
                ),
                ("target_id", models.PositiveIntegerField(blank=True, null=True)),
                (
                    "allocated_amount",
                    models.DecimalField(decimal_places=2, max_digits=18),
                ),
                (
                    "exchange_rate",
                    models.DecimalField(
                        decimal_places=6, default=Decimal("1"), max_digits=20
                    ),
                ),
                ("is_reversed", models.BooleanField(default=False)),
                (
                    "created_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="%(class)s_created",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "payment",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="allocations",
                        to="shop_management.customerbalancepayment",
                    ),
                ),
                (
                    "target_currency",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.PROTECT,
                        related_name="+",
                        to="shop_management.currency",
                    ),
                ),
            ],
            options={
                "ordering": ["id"],
            },
        ),
        migrations.CreateModel(
            name="SupplierBalancePaymentAllocation",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name="ID",
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True, null=True)),
                ("updated_at", models.DateTimeField(auto_now=True, null=True)),
                (
                    "target_type",
                    models.CharField(
                        choices=[
                            ("OPENING_BALANCE", "Opening Balance"),
                            ("PURCHASE", "Purchase"),
                        ],
                        max_length=30,
                    ),
                ),
                ("target_id", models.PositiveIntegerField(blank=True, null=True)),
                (
                    "allocated_amount",
                    models.DecimalField(decimal_places=2, max_digits=18),
                ),
                (
                    "exchange_rate",
                    models.DecimalField(
                        decimal_places=6, default=Decimal("1"), max_digits=20
                    ),
                ),
                ("is_reversed", models.BooleanField(default=False)),
                (
                    "created_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="%(class)s_created",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "payment",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="allocations",
                        to="shop_management.supplierbalancepayment",
                    ),
                ),
                (
                    "target_currency",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.PROTECT,
                        related_name="+",
                        to="shop_management.currency",
                    ),
                ),
            ],
            options={
                "ordering": ["id"],
            },
        ),
        migrations.RunPython(forward_audit_unknown_currencies, migrations.RunPython.noop),
    ]
