from typing import Any

from django.core.management.base import BaseCommand
from django.db import transaction
from django.db.models import QuerySet
from django.utils.crypto import get_random_string

from core.models import Brand, Category, Product


# noinspection PyProtectedMember
class Command(BaseCommand):
    help = "Rebuild slug field for all slugified instances"

    def reset_em(self, queryset: QuerySet[Any]) -> None:
        total = queryset.count()
        self.stdout.write(f"Starting slug rebuilding for {total} {queryset.model._meta.verbose_name_plural}")
        for idx, instance in enumerate(queryset.iterator(), start=1):
            try:
                while queryset.filter(name=instance.name).exclude(uuid=instance.uuid).count() >= 1:
                    instance.name = f"{instance.name} - {get_random_string(length=3, allowed_chars='0123456789')}"
                    instance.save()
                instance.slug = None
                with transaction.atomic():
                    instance.save(update_fields=["slug"])

                self.stdout.write(
                    self.style.SUCCESS(
                        f"[{idx}/{total}] ({queryset.model._meta.verbose_name_plural} UUID:"
                        f" {instance.pk}) slug set to '{instance.slug}'"
                    )
                )
            except Exception as e:
                self.stderr.write(
                    self.style.ERROR(
                        f"[{idx}/{total}] ({queryset.model._meta.verbose_name_plural}: {instance.name}/{instance.uuid})"
                        f" ERROR: {e}"
                    )
                )

    def handle(self, *args: list[Any], **options: dict[Any, Any]) -> None:
        for queryset in [
            Brand.objects.all(),
            Category.objects.all(),
            Product.objects.all(),
        ]:
            self.reset_em(queryset)

        self.stdout.write(self.style.SUCCESS("Slug rebuild complete."))
