# (c) cavaliba.com - data - views_iam_permission.py

import re

from django.contrib import messages
from django.shortcuts import redirect, render
from django.utils.translation import gettext as _

from app_data.aaa import start_view
from app_data.forms_iam import PermissionForm
from app_data.permissions import (
    has_iam_export_permission,
    permission_create,
    permission_delete,
    permission_get_by_id,
    permission_search,
    permission_update,
    permission_yaml_response,
)
from app_data.revision import revision_add_raw
from app_home.configuration import get_configuration
from app_home.log import DEBUG, ERROR, INFO, WARNING, log
from app_user.models import SirenePermission


# ----------------------------------------------------------
def list(request):

    context = start_view(
        request,
        app="iam",
        view="permission_list",
        noauth="app_home:index",
        perm="p_permission_read",
        noauthz="app_sirene:index",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    bigset_size = int(get_configuration("data", "DATA_BIGSET_SIZE"))
    count = SirenePermission.objects.count()
    context["count"] = count
    context["bigset"] = True

    query = ""
    if request.method == "POST":
        if request.POST.get("query"):
            query = request.POST.get("query")
            m = re.compile(r"[a-zA-Z0-9()_/.-]*$")
            if not m.match(query):
                query = ""
    context["query"] = query

    try:
        size = int(request.GET.get("size", bigset_size))
        page = int(request.GET.get("page", 1))
    except Exception:
        return redirect("app_data:permission_list")

    if page < 1 or size > 10000 or size < 1:
        return redirect("app_data:permission_list")

    output = request.GET.get("o", "")
    if output != "":
        if not has_iam_export_permission(aaa=aaa):
            log(
                WARNING,
                aaa=aaa,
                app="iam",
                view="permission_list",
                action="export",
                status="FAIL",
                data=_("Not allowed"),
            )
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            return redirect("app_data:permission_list")
        export_max = int(get_configuration("data", "EXPORT_INTERACTIVE_MAX_SIZE"))
        if count > export_max:
            log(
                ERROR,
                aaa=aaa,
                app="iam",
                view="permission_list",
                action="export",
                status="KO",
                data="Export too big",
            )
            messages.add_message(
                request, messages.ERROR, _("Export too large for interactive export.")
            )
            return redirect("app_data:permission_list")
        permissions_all = SirenePermission.objects.all().order_by("keyname")
        if output == "yaml":
            log(
                INFO,
                aaa=aaa,
                app="iam",
                view="permission_list",
                action="export_yaml",
                status="OK",
                data="",
            )
            return permission_yaml_response(permissions_all)

    permissions = permission_search(query=query, page=page, size=size)

    log(
        DEBUG,
        aaa=aaa,
        app="iam",
        view="permission_list",
        action="get",
        status="OK",
        data=f"{count} permissions",
    )

    context["size"] = size
    context["page"] = page
    page_last = int(count / size) + 1
    context["page_prev"] = max(page - 1, 1)
    context["page_first"] = page == 1
    context["page_current"] = 1 < page < page_last
    context["page_last"] = page_last
    context["page_last_active"] = page >= page_last
    context["page_next"] = min(page + 1, page_last)

    context["permissions"] = permissions
    return render(request, "app_data/iam/permission_list.html", context)


# ----------------------------------------------------------
def edit(request, pid=None):

    context = start_view(
        request,
        app="iam",
        view="permission_edit",
        noauth="app_home:index",
        perm="p_permission_update",
        noauthz="app_data:permission_list",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    permission = None

    if pid:
        permission = permission_get_by_id(pid)
        if not permission:
            messages.add_message(request, messages.ERROR, _("Not found"))
            log(
                WARNING,
                aaa=aaa,
                app="iam",
                view="permission_edit",
                action="edit",
                status="KO",
                data=_("Not found"),
            )
            return redirect("app_data:permission_list")
        if permission.is_builtin:
            messages.add_message(
                request, messages.ERROR, _("Built-in permissions cannot be edited")
            )
            log(
                WARNING,
                aaa=aaa,
                app="iam",
                view="permission_edit",
                action="edit",
                status="KO",
                data="builtin",
            )
            return redirect("app_data:permission_list")
    else:
        if "p_permission_create" not in aaa["perms"]:
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            log(
                WARNING,
                aaa=aaa,
                app="iam",
                view="permission_edit",
                action="create",
                status="KO",
                data=_("Not allowed"),
            )
            return redirect("app_data:permission_list")

    if request.method == "POST":
        form = PermissionForm(request.POST)
        if form.is_valid():
            action = "edit"
            if permission:
                permission, err = permission_update(permission, form.cleaned_data)
            else:
                permission, err = permission_create(form.cleaned_data)
                action = "create"
            if permission:
                revision_add_raw(
                    aaa=aaa,
                    classname="_permission",
                    keyname=permission.keyname,
                    displayname=permission.displayname,
                    action=action,
                )
                messages.add_message(
                    request, messages.SUCCESS, _("Permission saved: ") + permission.keyname
                )
                log(
                    INFO,
                    aaa=aaa,
                    app="iam",
                    view="permission_edit",
                    action="save",
                    status="OK",
                    data=permission.keyname,
                )
            else:
                messages.add_message(request, messages.ERROR, _("Failed to save permission"))
                log(
                    WARNING,
                    aaa=aaa,
                    app="iam",
                    view="permission_edit",
                    action="save",
                    status="KO",
                    data="",
                )
            return redirect("app_data:permission_list")
        else:
            messages.add_message(request, messages.ERROR, _("Invalid permission form"))
    else:
        if permission:
            form = PermissionForm(
                initial={
                    "keyname": permission.keyname,
                    "displayname": permission.displayname,
                    "description": permission.description,
                }
            )
        else:
            form = PermissionForm()

    context["form"] = form
    if permission:
        context["permission"] = permission
    return render(request, "app_data/iam/permission_edit.html", context)


# ----------------------------------------------------------
def delete(request, pid):

    context = start_view(
        request,
        app="iam",
        view="permission_delete",
        noauth="app_home:index",
        perm="p_permission_delete",
        noauthz="app_data:permission_list",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    permission = permission_get_by_id(pid)
    if not permission:
        messages.add_message(request, messages.ERROR, _("Not found"))
        return redirect("app_data:permission_list")

    if request.method == "POST":
        keyname = permission.keyname
        displayname = permission.displayname
        obj, err = permission_delete(permission)
        if err:
            messages.add_message(request, messages.ERROR, _("Failed to delete permission"))
            log(
                ERROR,
                aaa=aaa,
                app="iam",
                view="permission_delete",
                action="delete",
                status="KO",
                data=err,
            )
        else:
            revision_add_raw(
                aaa=aaa,
                classname="_permission",
                keyname=keyname,
                displayname=displayname,
                action="delete",
            )
            messages.add_message(request, messages.SUCCESS, _("Permission deleted"))
            log(
                INFO,
                aaa=aaa,
                app="iam",
                view="permission_delete",
                action="delete",
                status="OK",
                data=keyname,
            )

    return redirect("app_data:permission_list")
