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

from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt

import app_data.api.helper as helper
from app_data.api.aaa import start_api
from app_data.pipeline import Pipeline
from app_data.tasks import submit_pipeline
from app_home.log import DEBUG, log


def _pipeline_to_dict(p):
    return {
        "id": p.id,
        "keyname": p.keyname,
        "run_permission": p.run_permission,
    }


#  ----------------------------------------------------------------------------
# GET /api/pipelines/
#  ----------------------------------------------------------------------------
@csrf_exempt
def pipeline_list(request):

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

    if request.method != "GET":
        return helper.send_error("method not allowed", 405)

    instances = Pipeline.list()
    pipelines = [_pipeline_to_dict(Pipeline.from_instance(i)) for i in instances]

    log(
        DEBUG,
        aaa=aaa_api,
        app="api",
        view="pipeline_list",
        action="GET",
        status="OK",
        data=f"count={len(pipelines)}",
    )

    reply = {
        "count": len(pipelines),
        "pipelines": pipelines,
    }
    return helper.send_response(request, reply, 200)


# permission: p_pipeline_run


#  ----------------------------------------------------------------------------
# POST /api/pipelines/<name>/
# POST /api/pipelines/<id>/
# ?schema=SCHEMANAME,user,...   (comma-separated, required)
# &dryrun=false                 (optional, default: false)
#  ----------------------------------------------------------------------------
@csrf_exempt
def pipeline(request, id=None, key=None):

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

    if request.method != "POST":
        return helper.send_error("method not allowed", 405)

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

    schema_param = request.GET.get("schema", "").strip()
    dryrun_param = request.GET.get("dryrun", "false").strip().lower()
    dryrun = dryrun_param in ("true", "1", "yes")

    if not schema_param:
        return helper.send_error("missing required parameter: schema", 400)

    schema_names = [s.strip() for s in schema_param.split(",") if s.strip()]
    if not schema_names:
        return helper.send_error("missing required parameter: schema", 400)

    if id is not None:
        p = Pipeline.from_id(id)
    elif key:
        p = Pipeline.from_name(key)
    else:
        return helper.send_error("missing pipeline identifier", 400)

    if not p:
        return helper.send_not_found("pipeline not found")

    owner_id = str(aaa_api["user"].id) if aaa_api.get("user") else "system"

    # call async task (submit) , immediate return
    handle, err = submit_pipeline(
        pipeline_name=p.keyname,
        schema_names=schema_names,
        dryrun=dryrun,
        aaa=aaa_api,
        owner_type="api",
        owner_id=owner_id,
    )
    if not handle:
        return helper.send_error(err or "failed to submit task", 400)

    log(
        DEBUG,
        aaa=aaa_api,
        app="api",
        view="pipeline",
        action="POST",
        status="OK",
        data=f"pipeline={p.keyname} schema={schema_names} dryrun={dryrun} handle={handle}",
    )

    task_url = request.build_absolute_uri(reverse("api:api_task_detail", args=[handle]))
    reply = {
        "pipeline": p.keyname,
        "dryrun": dryrun,
        "handle": handle,
        "task_url": task_url,
    }
    return helper.send_response(request, reply, 202)
