# Generated by Django 5.2.12 on 2026-03-30 10:01

from decimal import Decimal

from django.db import migrations, models

from InvenTree.helpers import normalize


def set_default_raw_amount(apps, schema_editor):
    """Initialize the 'raw_amount' field for existing BomItem records."""
    BomItem = apps.get_model("part", "BomItem")

    to_update = []
    updated_count = 0

    # Run BulkUpdate in batches to avoid memory issues with large datasets
    BATCH_SIZE = 100

    N_BOM_ITEMS = BomItem.objects.count()

    def add_bom_item(item):
        nonlocal to_update
        nonlocal updated_count

        to_update.append(item)

        if len(to_update) >= BATCH_SIZE:
            BomItem.objects.bulk_update(to_update, ["raw_amount"])
            updated_count += len(to_update)
            to_update = []

    for item in BomItem.objects.all():
        item.raw_amount = str(normalize(Decimal(item.quantity)))
        add_bom_item(item)

    # Handle any remaining items that were not updated in the loop
    if len(to_update) > 0:
        BomItem.objects.bulk_update(to_update, ["raw_amount"])
        updated_count += len(to_update)

    assert updated_count == N_BOM_ITEMS, f"Expected to update {N_BOM_ITEMS} BomItem records, but updated {updated_count} records instead."

    assert BomItem.objects.filter(raw_amount="").count() == 0, "There are BomItem records with an empty 'raw_amount' field after migration."

    if updated_count > 0:
        print(f"Initialized 'raw_amount' field for {updated_count} BomItem records.")


class Migration(migrations.Migration):
    """Run a set of data and schema migrations to add a new 'raw_amount' field to the BomItem model.

    1. Add a new 'raw_amount' field to the BomItem model, which is a CharField that can store a raw amount of sub-part consumed to produce one part. This field can be used to store fractional amounts or amounts with associated units (e.g. '10 hours', '5 kg', etc.).
    2. Run a data migration to initialize the 'raw_amount' field for existing BomItem records, by copying the value from the existing 'quantity' field and converting it to a string.
    3. Mark the 'raw_amount' field as blank=False, now that the quantity values have been copied across
    """

    dependencies = [
        ("part", "0148_auto_20260427_2233"),
    ]

    operations = [
        migrations.AddField(
            model_name="bomitem",
            name="raw_amount",
            field=models.CharField(
                blank=True,
                null=False,
                help_text="Amount of sub-part consumed to produce one part",
                max_length=25,
                verbose_name="Amount",
            ),
        ),
        migrations.RunPython(set_default_raw_amount, reverse_code=migrations.RunPython.noop),
        migrations.AlterField(
            model_name="bomitem",
            name="raw_amount",
            field=models.CharField(
                blank=False,
                null=False,
                help_text="Amount of sub-part consumed to produce one part",
                max_length=25,
                verbose_name="Amount",
            ),
        ),
    ]
