# (c) cavaliba.com  - data/api - importer.py

import json
import yaml
import csv
from io import StringIO


from django.views.decorators.csrf import csrf_exempt


from app_home.log import log, DEBUG, ERROR
from app_home.configuration import get_configuration

from app_user.aaa_api import start_api

from app_data.loader import load_broker
from app_data.pipeline import Pipeline

import app_data.api.helper as helper




def csv_body(request, pipeline=None):

    data = []

    csvdata = request.body.decode("utf-8")

    csv_delimiter = request.GET.get("delimiter", None)
    if not csv_delimiter:
        if pipeline:
            csv_delimiter = pipeline.csv_delimiter
        else:
            csv_delimiter = get_configuration(appname="home", keyname="CSV_DELIMITER")

    # classname
    classname = request.GET.get("schema", None)
    if not classname:
        if pipeline:
            classname = pipeline.classname

    csvfile = StringIO(csvdata)
    csv_reader = csv.DictReader(csvfile, delimiter=csv_delimiter)

    for entry in csv_reader:
        if classname:
            entry["classname"] = classname
        data.append(entry)

    return data


#  ----------------------------------------------------------------------------
# /api/import/
#  ----------------------------------------------------------------------------
@csrf_exempt
def index(request):

    aaa_api = start_api(request, permission="p_data_import")
    if not aaa_api["is_allowed"]:
        return helper.send_denied("not allowed")

    # POST only
    # json or yaml

    if request.method != "POST":
        #return helper.send_denied("invalid method")
        return helper.send_error("missing parameters", 405)


    # API Key read-only ?
    if aaa_api["is_readonly"]:
        return helper.send_denied("API key is read-only")



    # pipeline
    pipeline = None
    pipeline_name = request.GET.get("pipeline", None)
    if pipeline_name:
        pipeline = Pipeline.from_name(pipeline_name)
        if not pipeline:
            log(ERROR, aaa=aaa_api, app="api", view="import", action="POST", status="KO", data=f"invalid pipeline {pipeline_name}")
            return helper.send_error("invalid pipeline", 405)


    datalist = []

    # application/yaml / application/x-yaml / text/x-yaml / text/yaml
    if 'yaml' in request.content_type:
        try:
            datalist = yaml.safe_load(request.body.decode("utf-8"))
        except Exception:
            pass

    # application/json / ...
    elif 'json' in request.content_type: 
        try:
            datalist = json.loads(request.body.decode("utf-8"))
        except Exception:
            pass

    # text/csv
    elif request.content_type == 'text/csv':
        datalist = csv_body(request, pipeline)

    else:
        return helper.send_error("invalid content / content-type", 400)


    if not isinstance(datalist, list):
        datalist = [datalist]


    for datadict in datalist:
        if pipeline:
            status = pipeline.apply(datadict)
        if status != 'discard':
            result = load_broker(datalist=datalist, aaa=aaa_api)

    log(DEBUG, aaa=aaa_api, app="api", view="import", action="POST", status="OK", data="")

    return helper.send_response(request, result, 200)
