"""
Management command: normalise_phone_numbers

Converts all borrower phone numbers stored in 07xxxxxxxxx or 2547xxxxxxxxx
format to the canonical +2547xxxxxxxxx form.

Usage:
    python manage.py normalise_phone_numbers          # dry-run (shows what would change)
    python manage.py normalise_phone_numbers --apply  # actually update the DB
"""

from django.core.management.base import BaseCommand
from users.models import CustomUser


def _normalise(phone: str) -> str:
    """
    Return the +254XXXXXXXXX form for any Kenyan mobile number,
    or the original if it can't be converted.
    Handles 07x (Safaricom/Telkom/Equitel) and 01x (Airtel/Faiba).
    """
    p = phone.strip()
    if p.startswith('NOPHONE-') or p.startswith('+254'):
        return p  # already correct / placeholder
    if p.startswith('0') and len(p) == 10:
        return '+254' + p[1:]
    if p.startswith('254') and len(p) == 12:
        return '+' + p
    return p  # unknown format — leave alone


class Command(BaseCommand):
    help = 'Normalise borrower phone numbers to +254XXXXXXXXX format'

    def add_arguments(self, parser):
        parser.add_argument(
            '--apply',
            action='store_true',
            default=False,
            help='Apply changes (default is dry-run)',
        )

    def handle(self, *args, **options):
        apply = options['apply']
        qs = CustomUser.objects.filter(role='borrower').exclude(
            phone_number__startswith='+254'
        ).exclude(
            phone_number__startswith='NOPHONE-'
        )

        changed = []
        skipped = []

        for user in qs:
            normalised = _normalise(user.phone_number)
            if normalised != user.phone_number:
                changed.append((user.id, user.get_full_name(), user.phone_number, normalised))
            else:
                skipped.append((user.id, user.phone_number))

        if not changed:
            self.stdout.write(self.style.SUCCESS('All phone numbers already in correct format — nothing to do.'))
            return

        self.stdout.write(f'\n{"DRY RUN — " if not apply else ""}Found {len(changed)} phone number(s) to normalise:\n')
        for uid, name, old, new in changed:
            self.stdout.write(f'  {name} ({uid}): {old}  →  {new}')

        if skipped:
            self.stdout.write(f'\n{len(skipped)} phone(s) could not be auto-converted (unknown format):')
            for uid, phone in skipped:
                self.stdout.write(f'  {uid}: {phone!r}')

        if not apply:
            self.stdout.write(
                self.style.WARNING(
                    '\nThis was a dry run. Run with --apply to save changes.'
                )
            )
            return

        # Apply updates — bypass .save() to avoid any side effects, use bulk_update
        for uid, name, old, new in changed:
            CustomUser.objects.filter(id=uid).update(phone_number=new, username=new)
            self.stdout.write(f'  Updated: {name}: {old} → {new}')

        self.stdout.write(self.style.SUCCESS(f'\nDone. {len(changed)} phone number(s) normalised.'))
