import csv

from django import forms
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.urls import URLPattern, path
from typing_extensions import override


class BulkUserCSVForm(forms.Form):
    """Form class for uploading a CSV file of users for bulk registration."""

    csv_file = forms.FileField(label="CSV File")


class MyUserAdmin(UserAdmin):
    """Custom ModelAdmin class for the User model, with support for bulk registration via CSV."""

    change_list_template = "entities/users_changelist.html"

    @override
    def get_urls(self) -> list[URLPattern]:
        return [
            path(r"bulk-register", self.bulk_register),
            *super().get_urls(),
        ]

    def bulk_register(self, request: WSGIRequest) -> HttpResponse:
        """Controller function to bulk register users from a CSV file."""
        if request.method == "GET":
            form = BulkUserCSVForm()
            return render(request, "entities/users_bulk_register.html", {"form": form})
        if request.method != "POST":
            raise

        form = BulkUserCSVForm(request.POST, request.FILES)
        if not form.is_valid():
            return render(request, "entities/users_bulk_register.html", {"form": form})

        csv_file = form.cleaned_data["csv_file"]
        decoded_file = csv_file.read().decode("utf-8").splitlines()
        reader = csv.DictReader(decoded_file)

        success_count = 0
        already_registered = []
        for row in reader:
            try:
                username = row["username"]
                email = row["email"]
                password = row["password"]
            except KeyError:
                self.message_user(request, "Invalid CSV file", level="ERROR")
                return render(request, "entities/users_bulk_register.html", {"form": form})

            if not User.objects.filter(username=username).exists():
                User.objects.create_user(username=username, email=email, password=password)
                success_count += 1
            else:
                already_registered.append(username)

        if len(already_registered) > 0:
            self.message_user(
                request,
                f"Registered {success_count} users. Skipped already registered users: {', '.join(already_registered)}",
                level="WARNING",
            )
        elif success_count > 0:
            self.message_user(request, f"Successfully registered {success_count} users.")
        else:
            self.message_user(request, "No users were registered (CSV file was empty).", level="WARNING")

        return redirect(".")


admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
