from django.templatetags.static import static
from django.utils.html import format_html
from grapple.registry import registry as grapple_registry
from wagtail import hooks
from wagtail.models import Page
from wagtail.search.backends import get_search_backend

from dnscms.rich_text import register_button_link_feature


@hooks.register("register_rich_text_features")
def enable_additional_rich_text_features(features):
    features.default_features.extend(["h5", "h6", "blockquote"])


@hooks.register("register_rich_text_features")
def register_button_link(features):
    register_button_link_feature(features)


@hooks.register("register_schema_query")
def override_search_resolver(query_mixins):
    """
    Override Grapple's `search` resolver. Two fixes vs. the upstream version:
    1. Restrict pages to live + public so drafts and access-restricted pages
       don't leak via the public API.
    2. Run a single search across all `Page` subclasses (instead of iterating
       per-model) so results are ranked by relevance across types rather than
       grouped by content type. Specific instances are fetched in a second
       bulk query and reordered to match the search ranking.

    Documents and images are intentionally not searched. The upstream resolver
    includes them, but the frontend search page only renders Page types and
    discards everything else, so iterating those indexes is wasted work.
    """
    if not grapple_registry.class_models:
        return

    class SearchOverrideMixin:
        def resolve_search(self, info, **kwargs):
            query = kwargs.get("query")
            if not query:
                return None
            s = get_search_backend()
            ranked = list(s.search(query, Page.objects.live().public()))
            if not ranked:
                return []
            ids = [p.id for p in ranked]
            specific_map = {p.id: p for p in Page.objects.filter(id__in=ids).specific()}
            return [specific_map[i] for i in ids if i in specific_map]

    query_mixins.insert(0, SearchOverrideMixin)


@hooks.register("construct_page_action_menu")
def make_publish_default_action(menu_items, request, context):
    for index, item in enumerate(menu_items):
        if item.name == "action-publish":
            menu_items.pop(index)
            menu_items.insert(0, item)
            break


@hooks.register("insert_editor_js")
def editor_js():
    return format_html('<script src="{}"></script>', static("js/page-editor.js"))
