from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import IntegrityError

from core.forms import PersonIdentifierForm
from core.models import Person, PersonIdentifier
from core.util import logs
from mixins.views import AbortSave, ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate

log = logs.get_logger(__name__)


class IdentifierPermissionMixin:
    def set_extra_args(self, user):
        self.extra_permission_args = {
            "person__user": user,
            "person__pk": self.kwargs["person"],
        }


class PersonIdentifierList(LoginRequiredMixin, IdentifierPermissionMixin, ObjectList):
    list_template = "partials/identifier-list.html"
    model = PersonIdentifier
    page_title = "Person Identifiers"

    list_url_name = "person_identifiers"
    list_url_args = ["type", "person"]

    submit_url_name = "person_identifier_create"
    submit_url_args = ["type", "person"]


class PersonIdentifierCreate(
    LoginRequiredMixin, IdentifierPermissionMixin, ObjectCreate
):
    model = PersonIdentifier
    form_class = PersonIdentifierForm

    submit_url_name = "person_identifier_create"
    submit_url_args = ["type", "person"]

    def form_valid(self, form):
        """If the form is invalid, render the invalid form."""
        try:
            return super().form_valid(form)
        except IntegrityError as e:
            if "UNIQUE constraint failed" in str(e):
                form.add_error("identifier", "Identifier rule already exists")
                return self.form_invalid(form)
            else:
                raise e

    def pre_save_mutate(self, user, obj):
        try:
            person = Person.objects.get(pk=self.kwargs["person"], user=user)
            obj.person = person
        except Person.DoesNotExist:
            log.error(f"Person {self.kwargs['person']} does not exist")
            raise AbortSave("person does not exist or you don't have access")


class PersonIdentifierUpdate(
    LoginRequiredMixin, IdentifierPermissionMixin, ObjectUpdate
):
    model = PersonIdentifier
    form_class = PersonIdentifierForm

    submit_url_name = "person_identifier_update"
    submit_url_args = ["type", "pk", "person"]


class PersonIdentifierDelete(
    LoginRequiredMixin, IdentifierPermissionMixin, ObjectDelete
):
    model = PersonIdentifier
