# (c) cavaliba.com - home - home.py

import os
import yaml

from app_home.cavaliba import CAVALIBA_VERSION
import app_home.cache as cache

from .configuration import sync_configuration
from .configuration_default import CONFIGURATION_DEFAULT

from app_home.models import DashboardApp

from app_user.permission import permission_all_keynames
from app_user.permission import bootstrap_permissions

from app_data.loader import load_broker
from app_data.schema import Schema

# --------------------------------------------
# Cavaliba Apps
# --------------------------------------------

def get_cavaliba_apps():

    reply = []

    appnames = [i for i in CONFIGURATION_DEFAULT]
    for appname in appnames:
        appobj = DashboardApp.objects.filter(keyname=appname).first()
        if appobj:
            reply.append(appobj)

    return reply



def get_app_by_name(appname):
    app = DashboardApp.objects.filter(keyname=appname).first()
    return app



def get_applist(aaa=None):
    '''  UI Home / Private ; filter: enabled + perm = True'''

    apps = DashboardApp.objects.all().prefetch_related("permission").order_by("order")

    reply = []

    for app in apps:

        if not app.is_enabled:
            continue

        app.is_allowed = False
        try:
            if app.permission.keyname in aaa["perms"]:
                app.is_allowed = True
        except Exception as e:
            print(e)

        reply.append(app)
    return reply


def get_sidebar(aaa=None):
    '''  CTX Processor : sidebar entries ; filter: enabled + perm = True'''

    entries = DashboardApp.objects.all().prefetch_related("permission").order_by("order")

    reply = []

    for entry in entries:

        if not entry.is_enabled:
            continue

        entry.is_allowed = False
        try:
            if entry.permission.keyname in aaa["perms"]:
                entry.is_allowed = True
        except Exception:
            pass

        reply.append(entry)

    return reply


# --------------------------------------------
# Patch / Migration
# --------------------------------------------

def apply_data_patch(verbose=True):

    aaa = {}
    aaa["perms"] = permission_all_keynames()

    # V3.20.0 - create Schema  _options {}
    try:
        schemas = Schema.listall()
        for schema in schemas:
            schema.save()
            if verbose:
                print("Patch 3.20 - UPDATE schema OK: ", schema.classname)
    except Exception as e:
        print("Patch 3.20 - UPDATE schema FAILED : ", e)


    # V3.21.0 -  update APIKEy schema, add role
    try:
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: _apikey
              roles:
                order: 80
                displayname: Roles
                dataformat: role
                cardinal_max: 0
            ''')
        #aaa = {'perms':['p_data_admin']}
        _ = load_broker(datalist=datalist, aaa=aaa)
        if verbose:
            print("Patch 3.21 - UPDATE schema API Key with role - OK")
    except Exception as e:
        print("Patch 3.21 - UPDATE schema API Key with role - FAILED:", e)


    # v3.26 - add sms_content field in Sirene schema(s)
    try:
        datalist = yaml.safe_load('''
            - classname: _schema
              keyname: sirene_template
              sms_content:
                    displayname: SMS Content
                    page: SMS Content
                    order: 402
                    dataformat: text

            - classname: _schema
              keyname: sirene_message
              sms_content:
                    displayname: SMS Content
                    page: SMS Content
                    order: 402
                    dataformat: text
            ''')

        _ = load_broker(datalist=datalist, aaa=aaa)
        if verbose:
            print("Patch 3.26 - UPDATE schema sirene - sms_content - OK")
    except Exception as e:
        print("Patch 3.21 - UPDATE schema sirene - sms_content - FAILED:", e)

# --------------------------------------------
# built-in conf setup
# --------------------------------------------
# - sync configuration in DB
# - load (init) built-in perms, class, schema, objects, user, greoup, role
# - apply patch to datamodel and more


def cavaliba_init(verbose=False):

    # purge shared cache
    cache.clear()
    if verbose:
        print('INIT - shared cache cleared')

    if verbose:
        print(f"Cavaliba Version: {CAVALIBA_VERSION}")

    # patch schema upgrade
    apply_data_patch(verbose=verbose)

    # configuration in DB
    sync_configuration(verbose=verbose)

    # load YAML ; build file list ordered

    if verbose:
        print("INIT LOADER - builtin:init")

    cavaliba_init_content("init", verbose=verbose)

    # demo
    content = os.environ.get("CAVALIBA_INIT_CONTENT", default="init")
    if content == "demo":
        if verbose:
            print('INIT LOADER - builtin:demo')
        cavaliba_init_content("demo", verbose=verbose)


# --------------------------------------------
# built-in - init selected content
# --------------------------------------------
def cavaliba_init_content(content="default", verbose=False):

    # purge shared cache
    cache.clear()
    if verbose:
        print('INIT CONTENT - shared cache cleared')


    INITDIR = f"/app/builtin/{content}/"
    ordered = []

    for item in os.scandir(INITDIR):
        if item.is_file(follow_symlinks=False):
            if item.path not in ordered:
                if item.path.endswith('.yaml'):
                    ordered.append(item.path)
    ordered.sort()

    content_permission = []

    content_other = []

    for filename in ordered:

        with open(filename) as f:
            try:
                content = yaml.load(f, Loader=yaml.SafeLoader)
                if verbose:
                    print(f'INIT CONTENT - {filename}')
            except Exception as e:
                print(f"SKIP - YAML syntax error in {filename} : ", e)
                continue

        if not content:
            continue

        for datadict in content:

            if datadict["classname"] == "_permission":
                content_permission.append(datadict)

            else:
                content_other.append(datadict)

    # Permissions first
    bootstrap_permissions(content_permission)

    # Other objects
    aaa = {}
    aaa["perms"] = permission_all_keynames()
    _ = load_broker(datalist=content_other, aaa=aaa)
