# Generated by Django 5.2.14 on 2026-05-26 08:49

import datetime
from tqdm import tqdm

from django.db import migrations


def set_creation_date(apps, schema_editor):
    """Set the creation_date field for existing StockItem entries."""

    StockItem = apps.get_model('stock', 'StockItem')
    StockItemTracking = apps.get_model('stock', 'StockItemTracking')

    # First pass - find all StockHistoryCode.CREATED entries
    # Note: As of 2026-05-26, the relevant status codes were:
    # CREATED = 1

    creation_entries = StockItemTracking.objects.filter(tracking_type=1)

    items_to_update = []

    def process_item(item):
        """Process a StockItem entry for update.
        
        As we are iterating over a potentially large number of StockItem entries,
        we periodically write updates to the database in batches to avoid memory issues.
        """
        nonlocal items_to_update

        items_to_update.append(item)

        if len(items_to_update) >= 250:
            StockItem.objects.bulk_update(items_to_update, ['creation_date'])
            items_to_update = []

    if creation_entries.count() > 0:
        progress = tqdm(total=creation_entries.count(), desc='stock.0121: Setting creation_date for StockItem entries')


        for entry in creation_entries:
            item = StockItem.objects.filter(pk=entry.item_id).first()
            if item and item.creation_date is None:
                item.creation_date = entry.date
                process_item(item)

            progress.update(1)

        progress.close()

    # Next: Find any StockItem entries that have a null creation_date
    items = StockItem.objects.filter(creation_date__isnull=True)

    if items.count() > 0:

        progress = tqdm(total=items.count(), desc='stock.0121: Setting creation_date for remaining StockItem entries')

        for item in items:
            # Source the creation_date from the stock item
            earliest_entry = StockItemTracking.objects.filter(item_id=item.pk).order_by('date').first()

            # Gather potential datetime sources for the creation_date field
            utc = datetime.timezone.utc

            def make_aware(dt):
                """Ensure a datetime is UTC-aware for safe cross-type comparison."""
                return dt.replace(tzinfo=utc) if dt.tzinfo is None else dt.astimezone(utc)

            raw_options = [
                item.updated,
                datetime.datetime(item.stocktake_date.year, item.stocktake_date.month, item.stocktake_date.day, tzinfo=utc) if item.stocktake_date else None,
                earliest_entry.date if earliest_entry else None,
            ]
            date_options = [make_aware(d) for d in raw_options if d is not None]

            if date_options:
                item.creation_date = min(date_options)
                process_item(item)

            progress.update(1)

    # Update the remaining items
    StockItem.objects.bulk_update(items_to_update, ['creation_date'], batch_size=250)


class Migration(migrations.Migration):
    """This migration extracts the 'creation_date' field for each StockItem entry.
    
    - If a CREATED entry exists in the StockItemTracking table, this is used as the source for the creation_date field.
    - If no CREATED entry exists, the creation_date is sourced from the earliest of the following
        - The 'updated' field of the StockItem entry
        - The 'stocktake_date' field of the StockItem entry (converted to a datetime)
        - The earliest entry in the StockItemTracking table for that item
    """

    dependencies = [
        ("stock", "0120_stockitem_creation_date"),
    ]

    operations = [
        migrations.RunPython(set_creation_date, reverse_code=migrations.RunPython.noop),
    ]
