# (c) cavaliba.com - IAM - group_views.py

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

from app_home.log import log, DEBUG, INFO, WARNING, ERROR, CRITICAL
from app_home.configuration import get_configuration
from .aaa import start_view

from app_user.models import SireneGroup
from app_user.forms import GroupForm
from app_user.forms import GroupUploadForm
from app_user.group import group_csv_response
from app_user.group import group_json_response
from app_user.group import group_yaml_response
from app_user.group import group_get_by_id
from app_user.group import group_get_by_name
from app_user.group import group_delete
from app_user.group import group_update
from app_user.group import group_create   # or update
from app_user.group import group_get_form
from app_user.group import group_get_subgroups
from app_user.group import group_get_users
from app_user.group import group_autogroup_update

from app_data.permissions import has_group_read_permission
from app_data.permissions import has_group_update_permission
from app_data.permissions import has_group_create_permission
from app_data.permissions import has_group_delete_permission

from app_data.revision import revision_add_raw
from app_data.revision import revision_get

# TODO: check per-group permissions

# ----------------------------------------------------------
# GROUPS
# ----------------------------------------------------------    

def list(request):
    ''' display group list '''


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

    # bigset or not
    count = SireneGroup.objects.filter(is_role=False).count()
    context["count"] = count

    # bigset_size = int(get_configuration("data","DATA_BIGSET_SIZE"))
    # bigset = True
    # context["bigset"] = bigset
    
    groups = SireneGroup.objects\
        .filter(is_role=False)\
        .prefetch_related("users")\
        .prefetch_related("subgroups")\
        .order_by('keyname')


    output = request.GET.get("o","")
    if output != "":

        if 'p_group_export' not in aaa["perms"]:
            log(WARNING, aaa=aaa, app="iam", view="group_list", action="export", status="FAIL", data=_("Not allowed")) 
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            return redirect("app_sirene:private")

        export_max = int(get_configuration("data","EXPORT_INTERACTIVE_MAX_SIZE"))
        if count > export_max:
            log(ERROR, aaa=aaa, app="group", view="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:group_list")

        if output == "csv":
            log(INFO, aaa=aaa, app="iam", view="group_list", action="export_csv", status="OK", data="")
            response = group_csv_response(groups)
            return response   

        elif output == "json":
            log(INFO, aaa=aaa, app="iam", view="group_list", action="export_json", status="OK", data="")
            response = group_json_response(groups)
            return response   

        elif output == "yaml":
            log(INFO, aaa=aaa, app="iam", view="group_list", action="export_yaml", status="OK", data="")
            response = group_yaml_response(groups)
            return response   


    context["groups"] = groups
    context["upload_form"] = GroupUploadForm()

    return render(request, 'app_user/group_list.html', context)



# --------------------------------------------
# detail
# --------------------------------------------

def detail(request, id=None):
    ''' display group detail '''

    context = start_view(request, app="iam", view="group_detail", 
        noauth="app_user:private", perm="p_group_read", noauthz="app_user:private")
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    group = group_get_by_id(id)
    if not isinstance(group, SireneGroup):
        messages.add_message(request, messages.ERROR, _("Not found"))
        log(WARNING, aaa=aaa, app="iam", view="group", action="detail", status="KO", data=_("Not found") )
        return redirect("app_user:group_list")

    if not has_group_read_permission(aaa=aaa):
        messages.add_message(request, messages.ERROR, _("Not allowed"))
        log(WARNING, aaa=aaa, app="iam", view="group", action="detail", status="KO", data=_("Not allowed") )
        return redirect("app_user:group_list")

    # c = group_autogroup_update()
    # update autogroup_users (don't wait for periodic task)
    group_autogroup_update([group])

    # main group object
    context["group"] = group

    subgroups = group_get_subgroups(group, done=[])    
    tmp = group.subgroups.all()
    subgroups_indirect = [i for i in subgroups if i not in tmp]
    context["subgroups_indirect"] = subgroups_indirect

    context["users_direct"] = group_get_users(group, direct=True, computed=False, subgroups=False)
    context["users_computed"] = group_get_users(group, direct=False, computed=True, subgroups=False)
    context["users_indirect"] = group_get_users(group, direct=False, computed=False, subgroups=True)

    # revisions - V3.23
    context['revisions'] = revision_get(classname="_group", keyname=group.keyname)


    # can use YAML Editor ?
    if 'p_data_import' in aaa['perms']:
        context['ui_texteditor'] = True
        
    return render(request, 'app_user/group_detail.html', context)

# --------------------------------------------
# edit
# --------------------------------------------
def edit(request, id=None):
    ''' usergroup  edit form'''

    context = start_view(request, app="iam", view="group.edit", 
        noauth="app_user:private", perm="p_group_update", noauthz="app_sirene:index")
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    group = None

    if id:
        group = group_get_by_id(id)
        if not group:
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            log(WARNING, aaa=aaa, app="iam", view="group", action="edit", status="KO", data=_("Not allowed") )
            return redirect("app_user:group_list")
        if not has_group_update_permission(aaa=aaa):
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            log(WARNING, aaa=aaa, app="iam", view="group", action="edit", status="KO", data=_("Not allowed") )
            return redirect("app_user:group_list")
    else:
        if not has_group_create_permission(aaa=aaa):
        #if "p_group_create" not in aaa["perms"]:
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            log(WARNING, aaa=aaa, app="iam", view="group", action="create", status="KO", data=_("Not allowed") )
            return redirect("app_user:group_list")


    if request.method == "POST":

        form = GroupForm(request.POST)

        if form.is_valid():
            
            # data + add users (outside managed django form)
            data = form.cleaned_data
            users = request.POST.getlist("users",default=[])
            data["users"] = users

            action = "edit"
            # update
            if group:
                group, err = group_update(group, data)

            # create                
            else:   
                group, err = group_create(data)
                action = "create"
              
            if err:
                messages.add_message(request, messages.ERROR, _("Failed to save group"))
                log(ERROR, aaa=aaa, app="iam", view="group", action="save", status="KO", data=_("Failed to save group"))

            else:
                revision_add_raw(aaa=aaa, classname="_group", keyname=group.keyname, action=action)
                messages.add_message(request, messages.SUCCESS, _("Group saved") )
                log(INFO, aaa=aaa, app="iam", view="group", action="save", status="OK", data=f"saved: {group.keyname}")


            return redirect("app_user:group_detail", group.id)

        else:
            # error, keep editing
            messages.add_message(request, messages.ERROR, _("Invalid group form") )
            log(DEBUG, aaa=aaa, app="usiamr", view="group", action="save", status="KO", data=_("Invalid group form"))
            # add out of form users attribute
            context["users"] = []
            users = request.POST.getlist("users",default=[])
            for i in users:
                item = { "key":i, "display":i, "selected":True}
                context["users"].append(item)
    # GET
    else:
        if group:
            form = group_get_form(group)
            context["users"] = []
            #users = group.users.all()
            users = group_get_users(group, subgroups=False, computed=False)

            for i in users:
                item = { "key":i.login, "display":i.displayname , "selected":True}
                context["users"].append(item)

        else: 
            context["users"] = []
            form = group_get_form()


    context["form"] = form
    if group:
        context["group"] = group

    return render(request, 'app_user/group_edit.html', context)


# --------------------------------------------
# delete
# --------------------------------------------
def delete(request, id):
    ''' delete user Group '''

    context = start_view(request, app="iam", view="group_delete", 
        noauth="app_user:private", perm="p_group_delete", noauthz="app_sirene:index")
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    # TODO : check perms / security groups

    gobj = group_get_by_id(id)

    if not gobj:
        log(ERROR, aaa=aaa, app="iam", view="group_delete", action="find", status="FAIL", data=_("Group not found"))
        messages.add_message(request, messages.ERROR, _("Group not found"))
        return redirect("app_user:group_list")
    else:
        if not has_group_delete_permission(aaa=aaa):
            messages.add_message(request, messages.ERROR, _("Not allowed"))
            log(WARNING, aaa=aaa, app="iam", view="group", action="permission", status="KO", data=_("Not allowed") )
            return redirect("app_user:group_list")


    if request.method == "POST":

        group, err = group_delete(gobj)

        if err:
            log(ERROR, aaa=aaa, app="iam", view="group_delete", action="delete", status="FAIL", data=_("Failed to delete group") )
            messages.add_message(request, messages.ERROR, _("Failed to delete group"))
        else:
            revision_add_raw(aaa=aaa, classname="_group", keyname=group.keyname, action="delete")
            messages.add_message(request, messages.SUCCESS, _("Group deleted ") )
            log(INFO, aaa=aaa, app="iam", view="group_delete", action="delete", status="OK", data=f"deleted: {group.keyname}" )


    return redirect("app_user:group_list")


