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


import yaml
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.data import Instance
from app_data.filestore import tmp_local_filepath
from app_data.forms import DataUploadForm
from app_data.loader import load_broker, load_file_csv, load_file_json, load_file_yaml
from app_data.pipeline import Pipeline
from app_data.schema import Schema
from app_home.log import DEBUG, ERROR, INFO, log


# -------------------------------------------------------------------------
# YAML TEXT EDITOR TOOL (global)
# -------------------------------------------------------------------------
def texteditor(request, classname=None, id=None):

    context = start_view(
        request,
        app="data",
        view="texteditor",
        noauth="app_sirene:private",
        perm="p_data_import",
        noauthz="app_home:private",
    )
    if context["redirect"]:
        return redirect(context["redirect"])
    aaa = context["aaa"]

    rawdata = ""

    # Get existing data or empty
    if request.method == "GET":
        # no id          : => schema from classname
        # id             : => instance

        # Schema
        if not id:
            schema = Schema.from_name(classname)
            try:
                rawdata = schema.to_yaml()
            except Exception:
                pass

        # Instance
        else:
            instance = Instance.from_id(id)
            # instance.print()
            if instance:
                rawdata = instance.to_yaml()

    elif request.method == "POST":
        valid = False
        rawdata = request.POST["rawdata"]
        datalist = None

        #  TODO: sanitize
        pipeline = None
        pipeline_name = request.POST["pipeline"]
        if pipeline_name:
            pipeline = Pipeline.from_name(pipeline_name)

        # Get TextArea
        try:
            datalist = yaml.safe_load(rawdata)
            valid = True
        except Exception as e:
            messages.add_message(request, messages.ERROR, e)

        # File provided ?
        fileform = DataUploadForm(request.POST, request.FILES)

        if fileform.is_valid():
            postfile = request.FILES["file"]

            # filestore tmp file
            filename = tmp_local_filepath()
            with open(filename, "wb+") as destination:
                for chunk in postfile.chunks():
                    destination.write(chunk)

            # if file.multiple_chunks():
            #     messages.add_message(request, messages.ERROR, _("Import failed - file too big"))
            #     log(ERROR, aaa=aaa, app="data", view="import", action="post", status="KO", data=_("Import failed - file too big"))
            #     return redirect("app_data:private")

            if postfile.name.endswith(".csv"):
                datalist = load_file_csv(filename=filename, pipeline_name=pipeline_name)

            elif postfile.name.endswith(".yml") or postfile.name.endswith(".yaml"):
                datalist = load_file_yaml(filename=filename, pipeline_name=pipeline_name)

            elif postfile.name.endswith(".json"):
                datalist = load_file_json(filename=filename, pipeline_name=pipeline_name)

            if type(datalist) is not list:
                messages.add_message(request, messages.ERROR, _("Import failed - invalid file"))
                log(
                    ERROR,
                    aaa=aaa,
                    app="data",
                    view="import",
                    action="file",
                    status="KO",
                    data=f"Content is not a list : {postfile.name}",
                )
                datalist = []
            else:
                log(
                    INFO,
                    aaa=aaa,
                    app="data",
                    view="import",
                    action="file",
                    status="OK",
                    data=f"loaded: {postfile.name}",
                )
                valid = True

        # check mode only
        if request.POST["submit"] == "verify":
            if valid:
                messages.add_message(request, messages.SUCCESS, _("Check ok"))
                log(DEBUG, aaa=aaa, app="data", view="import", action="check", status="OK")
            # else keep editing ...

        # submit
        if request.POST["submit"] == "import":
            if valid:
                count_ok = 0
                count_ko = 0
                for datadict in datalist:
                    if pipeline:
                        status = pipeline.apply(datadict)
                        if status == "discard":
                            continue
                    result = load_broker([datadict], aaa=aaa)
                    if result.get("errors"):
                        count_ko += result.get("count_ko", 0)
                    else:
                        count_ok += result.get("count_ok", 0)

                if count_ko:
                    messages.add_message(
                        request,
                        messages.ERROR,
                        _("Import partial or failed") + f" (ok={count_ok}, ko={count_ko})",
                    )
                    log(
                        DEBUG,
                        aaa=aaa,
                        app="data",
                        view="import",
                        action="import",
                        status="KO",
                        data=f"ok={count_ok} ko={count_ko}",
                    )
                else:
                    messages.add_message(
                        request, messages.SUCCESS, _("Import OK") + f" ({count_ok})"
                    )
                    log(
                        DEBUG,
                        aaa=aaa,
                        app="data",
                        view="import",
                        action="import",
                        status="OK",
                        data=f"imported: {count_ok} objects",
                    )
                return redirect("app_home:private")

    # edit
    context["upload_form"] = DataUploadForm()
    context["rawdata"] = rawdata
    context["pipelines"] = Pipeline.list(is_enabled=True)
    return render(request, "app_data/import.html", context)
