from django.core.exceptions import PermissionDenied

from wagtail.log_actions import log


class DeletePagePermissionError(PermissionDenied):
    """
    Raised when the page delete cannot be performed due to insufficient permissions.
    """

    pass


class DeletePageAction:
    def __init__(self, page, user):
        self.page = page
        self.user = user

    def check(self, skip_permission_checks=False):
        if (
            self.user
            and not skip_permission_checks
            and not self.page.permissions_for_user(self.user).can_delete()
        ):
            raise DeletePagePermissionError(
                "You do not have permission to delete this page."
            )

    def _delete_page(self, page, *args, **kwargs):
        from wagtail.models import Page

        # Ensure that deletion always happens on an instance of Page, not a specific subclass. This
        # works around a bug in treebeard <= 3.0 where calling SpecificPage.delete() fails to delete
        # child pages that are not instances of SpecificPage
        if type(page) is Page:
            for child in page.get_descendants().specific().iterator():
                self.log_deletion(child)
            self.log_deletion(page.specific)

            # this is a Page instance, so carry on as we were
            return super(Page, page).delete(*args, **kwargs)
        else:
            # retrieve an actual Page instance and delete that instead of page
            return DeletePageAction(
                Page.objects.get(id=page.id), user=self.user
            ).execute(*args, **kwargs)

    def execute(self, *args, skip_permission_checks=False, **kwargs):
        self.check(skip_permission_checks=skip_permission_checks)

        return self._delete_page(self.page, *args, **kwargs)

    def log_deletion(self, page):
        log(
            instance=page,
            action="wagtail.delete",
            user=self.user,
            deleted=True,
        )
