from typing import List
from django.contrib.auth.mixins import UserPassesTestMixin

from django.contrib.auth.models import User
from django.db import models

class SuperuserRequiredMixin(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.is_superuser

class CheckCanEditMixin():
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context["can_edit"] = self.object.check_user_can_edit(self.request.user)

        return context
    


class QuestionMixin():

    def get_app_name(self):
        raise NotImplementedError("You must implement get_app_name in the derived class")

    def get_base_template(self):
        return f"{self.get_app_name()}/base.html"

    def get_link_headers(self):
        return f"{self.get_app_name()}/question_link_header.html"

class AuthorMixin():
    """Mixin class for models that have authors
    
    requires an author many to many field to be defined on the derived class
    
    """
    author = models.ManyToManyField(User)  # Corrected typing

    def get_author_objects(self) -> List[User]:  # Updated type hint
        """Returns list of author objects"""
        authors = [i for i in self.author.all()]
        return authors

    def get_authors(self):
        """Returns a comma separated text list of authors as usernames.

        """
        authors = ", ".join([i.username for i in self.author.all()])
        if not authors:
            return "None"
        return authors

    def add_authors(self, users : List[User]):
        """Add an author to the object"""
        self.author.add(*users)

    def add_author(self, user: User):
        """Add an author to the object"""
        self.author.add(user)

    def remove_author(self, user: User):
        """Remove an author from the object"""
        self.author.remove(user)

    def is_author(self, user: User) -> bool:
        """Returns True if the user is an author of the object"""
        if user.is_superuser:
            return True

        return self.author.filter(id=user.id).exists()

    def get_author_display(self):
        return ", ".join([i.username for i in self.get_author_objects()])


class UserConfigurablePaginationMixin:
    default_per_page = 25
    allowed_per_page = [25, 50, 100, 250, 500]

    def get_table_pagination(self, table):
        try:
            per_page = int(self.request.GET.get("per_page", self.default_per_page))
            if per_page not in self.allowed_per_page:
                per_page = self.default_per_page
        except (TypeError, ValueError):
            per_page = self.default_per_page
        return {"per_page": per_page}

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["page_sizes"] = [25, 50, 100, 250, 500]
        return context