# Paste this into: python manage.py shell
import re, sys, os
from django.db import transaction
from accounts.models import State, District
from users.models import CustomUser
from commissions.models import CommissionSplit

os.makedirs('/tmp/comm_fix', exist_ok=True)
logpath = '/tmp/comm_fix/changes_log.txt'
log = open(logpath, 'w', encoding='utf8')

isnum = re.compile(r'^\s*\d+\s*$')

def safe_int(s):
    try:
        return int(str(s).strip())
    except:
        return None

def fix_user_states_and_districts(dry_run=False):
    users_state_ids = CustomUser.objects.filter(state__regex=r'^\s*\d+\s*$')
    users_district_ids = CustomUser.objects.filter(district__regex=r'^\s*\d+\s*$')
    users_qs = (users_state_ids | users_district_ids).distinct()
    log.write(f"Found {users_qs.count()} users with numeric state/district\n")
    print(f"Found {users_qs.count()} users with numeric state/district")
    changed = 0
    errors = []

    for u in users_qs:
        orig_state = u.state
        orig_dist = u.district
        changed_flag = False

        # fix state if numeric
        if orig_state and isnum.match(orig_state):
            sid = safe_int(orig_state)
            try:
                st = State.objects.get(pk=sid)
                new_state = st.name
                log.write(f"User {u.id} ({u.mobile_number}): state {orig_state} -> {new_state}\n")
                if not dry_run:
                    u.state = new_state
                changed_flag = True
            except State.DoesNotExist:
                err = f"User {u.id}: State id {sid} not found"
                print(err)
                log.write(err + "\n")
                errors.append(err)

        # fix district if numeric
        if orig_dist and isnum.match(orig_dist):
            did = safe_int(orig_dist)
            try:
                d = District.objects.get(pk=did)
                new_dist = d.name
                log.write(f"User {u.id} ({u.mobile_number}): district {orig_dist} -> {new_dist}\n")
                if not dry_run:
                    u.district = new_dist
                changed_flag = True
            except District.DoesNotExist:
                err = f"User {u.id}: District id {did} not found"
                print(err)
                log.write(err + "\n")
                errors.append(err)

        if changed_flag and not dry_run:
            u.save(update_fields=['state','district'])
            changed += 1

    return changed, errors

def fix_commissions_states_and_districts(dry_run=False):
    # CommissionSplit fields are strings (per your earlier code), so use regex filter
    cs_state_ids = CommissionSplit.objects.filter(state__regex=r'^\s*\d+\s*$')
    cs_district_ids = CommissionSplit.objects.filter(district__regex=r'^\s*\d+\s*$')
    cs_qs = (cs_state_ids | cs_district_ids).distinct()
    log.write(f"Found {cs_qs.count()} CommissionSplit rows with numeric state/district\n")
    print(f"Found {cs_qs.count()} CommissionSplit rows with numeric state/district")
    changed = 0
    errors = []

    for c in cs_qs:
        orig_state = c.state
        orig_dist = c.district
        changed_flag = False

        if orig_state and isnum.match(orig_state):
            sid = safe_int(orig_state)
            try:
                st = State.objects.get(pk=sid)
                new_state = st.name
                log.write(f"Commission {c.id}: state {orig_state} -> {new_state}\n")
                if not dry_run:
                    c.state = new_state
                changed_flag = True
            except State.DoesNotExist:
                err = f"Commission {c.id}: State id {sid} not found"
                print(err); log.write(err + "\n"); errors.append(err)

        if orig_dist and isnum.match(orig_dist):
            did = safe_int(orig_dist)
            try:
                d = District.objects.get(pk=did)
                new_dist = d.name
                log.write(f"Commission {c.id}: district {orig_dist} -> {new_dist}\n")
                if not dry_run:
                    c.district = new_dist
                changed_flag = True
            except District.DoesNotExist:
                err = f"Commission {c.id}: District id {did} not found"
                print(err); log.write(err + "\n"); errors.append(err)

        if changed_flag and not dry_run:
            c.save(update_fields=['state','district'])
            changed += 1

    return changed, errors

# ===== run in a transaction (optional) =====
print("=== DRY RUN: see /tmp/comm_fix/changes_log.txt for proposed changes ===")
log.write("=== DRY RUN ===\n")
changed_users, user_errors = fix_user_states_and_districts(dry_run=True)
changed_comm, comm_errors = fix_commissions_states_and_districts(dry_run=True)
log.write(f"DRY RUN summary: users_to_change={changed_users}, commissions_to_change={changed_comm}\n")
log.flush()
print(f"Dry run complete. Users to change: {changed_users}, Commissions to change: {changed_comm}")
print("Review /tmp/comm_fix/changes_log.txt now. If it looks good, set do_apply=True and run again to apply changes.")

# To apply changes, set do_apply = True and re-run these fix functions inside a transaction:
do_apply = False

if do_apply:
    with transaction.atomic():
        log.write("=== APPLYING CHANGES ===\n")
        changed_users, user_errors = fix_user_states_and_districts(dry_run=False)
        changed_comm, comm_errors = fix_commissions_states_and_districts(dry_run=False)
        log.write(f"APPLY summary: users_changed={changed_users}, commissions_changed={changed_comm}\n")
        print(f"Applied changes. Users changed: {changed_users}, Commissions changed: {changed_comm}")

log.close()

