# One-time backfill: assign Employee IDs (EMP-####) to users that don't have
# one yet, in account-creation order (oldest first). New users then continue
# the sequence from the highest assigned value.

import re

from django.db import migrations


EMP_RE = re.compile(r"EMP-(\d+)", re.IGNORECASE)


def _num(emp_id):
    m = EMP_RE.fullmatch((emp_id or "").strip())
    return int(m.group(1)) if m else None


def backfill_employee_ids(apps, schema_editor):
    User = apps.get_model("users", "User")
    EmployeeIdSequence = apps.get_model("users", "EmployeeIdSequence")

    # Every EMP-#### number already in use — so backfilled IDs never collide
    # with a value some user was given manually before this feature.
    taken = set()
    for emp_id in User.objects.exclude(employee_id__isnull=True).exclude(
        employee_id=""
    ).values_list("employee_id", flat=True):
        n = _num(emp_id)
        if n is not None:
            taken.add(n)

    seq, _ = EmployeeIdSequence.objects.get_or_create(pk=1)
    # Start above whatever the counter and existing IDs have already reached.
    counter = max(seq.last_value, max(taken) if taken else 0)

    # Users missing an ID, oldest account first (id as a stable tiebreaker).
    missing = (
        User.objects.filter(employee_id__isnull=True)
        | User.objects.filter(employee_id="")
    ).distinct().order_by("date_joined", "id")

    for user in missing:
        counter += 1
        while counter in taken:  # skip any manually-used numbers
            counter += 1
        user.employee_id = f"EMP-{counter:04d}"
        user.save(update_fields=["employee_id"])
        taken.add(counter)

    # New users continue from here.
    seq.last_value = counter
    seq.save(update_fields=["last_value"])


def reverse_noop(apps, schema_editor):
    # Backfilled IDs are real, permanent records — do not strip them on reverse.
    pass


class Migration(migrations.Migration):

    dependencies = [
        ("users", "0008_employeeidsequence"),
    ]

    operations = [
        migrations.RunPython(backfill_employee_ids, reverse_noop),
    ]
