# -*- coding: utf-8 -*-
#
# Copyright (C) 2024 TU Wien.
#
# Invenio-Theme-TUW is free software; you can redistribute it and/or modify
# it under the terms of the MIT License; see LICENSE file for more details.

"""Setup functions to be executed on application startup."""

from flask_limiter import Limiter
from flask_menu import current_menu
from invenio_administration.permissions import administration_permission
from invenio_app.limiter import useragent_and_ip_limit_key
from invenio_base.utils import obj_or_import_string
from invenio_i18n import lazy_gettext as _

from .views import (
    guarded_communities_create,
    guarded_deposit_create,
    guarded_deposit_edit,
    tuw_index,
)


def _get_limiter(app):
    """Get the configured limiter, or initialize it if not available."""
    limiter = app.extensions["invenio-app"].limiter
    if limiter is None:
        limiter = Limiter(
            app,
            key_func=obj_or_import_string(
                app.config.get("RATELIMIT_KEY_FUNC"), default=useragent_and_ip_limit_key
            ),
        )

    return limiter


def override_bp_order(app):
    """Rearrange the order of registered blueprints.

    This ensures that jinja templates are loaded from Theme-TUW rather than other
    modules, which enables overriding of core templates (cf. `flask.render_template()`).
    This operation needs to be performed after all the blueprints have been registered.
    """
    bps = {}
    theme_tuw_bp = None
    for name, bp in app.blueprints.items():
        if name == "invenio_theme_tuw":
            theme_tuw_bp = bp
        else:
            bps[name] = bp

    app.blueprints = {"invenio_theme_tuw": theme_tuw_bp, **bps}


def override_view_functions(app):
    """Override the existing view functions with more access control."""
    app.view_functions["invenio_app_rdm.index"] = tuw_index

    # we have some additional role-based permissions (trusted-user) that decide
    # among other things if people can create records/drafts
    # this is not considered in the original view functions, which is why we
    # currently need to wrap them with our own guards
    app.view_functions["invenio_app_rdm_records.deposit_edit"] = guarded_deposit_edit
    app.view_functions["invenio_app_rdm_records.deposit_create"] = (
        guarded_deposit_create
    )
    app.view_functions["invenio_communities.communities_new"] = (
        guarded_communities_create
    )

    # limit the amount of contact requests that can be made per time period
    # (this needs to be done after the Flask-Limiter extension has been init.)
    if (limiter := _get_limiter(app)) is not None:
        limit_value = app.config.get("THEME_TUW_CONTACT_UPLOADER_RATE_LIMIT", "5/day")
        contact_uploader_view_func = app.view_functions[
            "invenio_theme_tuw.contact_uploader"
        ]
        app.view_functions["invenio_theme_tuw.contact_uploader"] = limiter.limit(
            limit_value, methods=["POST"]
        )(contact_uploader_view_func)


def register_menu_entries(app):
    """Register an admin menu entry for the custom users administration."""
    current_menu.submenu("profile-admin.tuw").register(
        "invenio_theme_tuw.list_user_info",
        _(
            "%(icon)s TUW users administration",
            icon='<i class="users icon"></i>',
        ),
        order=2,
        visible_when=lambda: administration_permission.can(),
    )