from django.shortcuts import redirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.translation import gettext as _

from wagtail import hooks
from wagtail.actions.copy_page import CopyPageAction
from wagtail.actions.create_alias import CreatePageAliasAction
from wagtail.admin import messages
from wagtail.admin.auth import user_has_any_page_permission, user_passes_test
from wagtail.admin.forms.pages import CopyForm
from wagtail.admin.utils import get_valid_next_url_from_request
from wagtail.models import Page


@user_passes_test(user_has_any_page_permission)
def copy(request, page_id):
    page = Page.objects.get(id=page_id)

    # Parent page defaults to parent of source page
    parent_page = page.get_parent()

    # Check if the user has permission to publish subpages on the parent
    can_publish = parent_page.permissions_for_user(request.user).can_publish_subpage()

    form_class = getattr(page.specific_class, "copy_form_class", CopyForm)
    form = form_class(
        request.POST or None, user=request.user, page=page, can_publish=can_publish
    )

    next_url = get_valid_next_url_from_request(request)

    for fn in hooks.get_hooks("before_copy_page"):
        result = fn(request, page)
        if hasattr(result, "status_code"):
            return result

    # Check if user is submitting
    if request.method == "POST":
        # Prefill parent_page in case the form is invalid (as prepopulated value for the form field,
        # because ModelChoiceField seems to not fall back to the user given value)
        parent_page = Page.objects.get(id=request.POST["new_parent_page"])

        if form.is_valid():
            # Receive the parent page (this should never be empty)
            if form.cleaned_data["new_parent_page"]:
                parent_page = form.cleaned_data["new_parent_page"]

            # Re-check if the user has permission to publish subpages on the new parent
            can_publish = parent_page.permissions_for_user(
                request.user
            ).can_publish_subpage()
            keep_live = can_publish and form.cleaned_data.get("publish_copies")

            # Copy the page
            # Note that only users who can publish in the new parent page can create an alias.
            # This is because alias pages must always match their original page's state.
            if can_publish and form.cleaned_data.get("alias"):
                action = CreatePageAliasAction(
                    page.specific,
                    recursive=form.cleaned_data.get("copy_subpages"),
                    parent=parent_page,
                    update_slug=form.cleaned_data["new_slug"],
                    user=request.user,
                )
                new_page = action.execute(skip_permission_checks=True)
            else:
                action = CopyPageAction(
                    page=page,
                    recursive=form.cleaned_data.get("copy_subpages"),
                    to=parent_page,
                    update_attrs={
                        "title": form.cleaned_data["new_title"],
                        "slug": form.cleaned_data["new_slug"],
                    },
                    keep_live=keep_live,
                    user=request.user,
                )
                new_page = action.execute()

            # Give a success message back to the user
            edit_button = messages.button(
                reverse("wagtailadmin_pages:edit", args=(new_page.id,)),
                _("Edit"),
            )
            if form.cleaned_data.get("copy_subpages"):
                messages.success(
                    request,
                    _("Page '%(page_title)s' and %(subpages_count)s subpages copied.")
                    % {
                        "page_title": page.specific_deferred.get_admin_display_title(),
                        "subpages_count": new_page.get_descendants().count(),
                    },
                    buttons=[edit_button],
                )
            else:
                messages.success(
                    request,
                    _("Page '%(page_title)s' copied.")
                    % {"page_title": page.specific_deferred.get_admin_display_title()},
                    buttons=[edit_button],
                )

            for fn in hooks.get_hooks("after_copy_page"):
                result = fn(request, page, new_page)
                if hasattr(result, "status_code"):
                    return result

            # Redirect to explore of parent page
            if next_url:
                return redirect(next_url)
            return redirect("wagtailadmin_explore", parent_page.id)

    return TemplateResponse(
        request,
        "wagtailadmin/pages/copy.html",
        {
            "page": page,
            "form": form,
            "next": next_url,
        },
    )
