# app_user - permission_views.py
# (c) cavaliba.com

from app_data.permissions import has_iam_export_permission
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 django.contrib import messages
from django.shortcuts import redirect, render
from django.utils.translation import gettext as _

from .aaa import start_view
from .forms import PermissionForm
from .models import SirenePermission
from .permission import (
    permission_create,
    permission_delete,
    permission_get_by_id,
    permission_search,
    permission_update,
    permission_yaml_response,
)


# ----------------------------------------------------------
# PERMISSION list
# ----------------------------------------------------------
def list(request):
    '''  display permission list'''

    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

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

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

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

    # Export (full dataset, not paginated)
    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_user: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_user: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)

    # Paginated query
    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")

    # Pagination context
    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_user/permission_list.html', context)


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

    context = start_view(request, app="iam", view="permission_edit", noauth="app_home:index",
        perm="p_permission_update", noauthz="app_user: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_user: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_user: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_user: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_user: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_user/permission_edit.html', context)


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

    context = start_view(request, app="iam", view="permission_delete", noauth="app_home:index",
        perm="p_permission_delete", noauthz="app_user: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_user: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_user:permission_list")
