import logging
from http.client import BAD_REQUEST
from os import environ
from pathlib import Path

from aiohttp import ClientSession

from lisa.globalfit.framework.pipelinerunner.workflow import (
    WorkflowBackendDetails,
    WorkflowResult,
    WorkflowSpec,
)

logger = logging.getLogger(__name__)

NAMESPACE = "argo"


async def submit_workflow(wf: WorkflowSpec, opts: WorkflowBackendDetails) -> None:
    body = {
        "resourceKind": "workflowtemplate",
        "resourceName": wf.resource,
        "submitOptions": {"parameters": [f"{k}={v}" for k, v in wf.parameters.items()]},
    }
    async with ClientSession(
        headers={"Authorization": f"Bearer {get_token()}"}
    ) as client:
        async with client.post(
            f"{opts.url}/api/v1/workflows/{NAMESPACE}/submit", json=body
        ) as request:
            response = await request.json()

    if request.status == BAD_REQUEST:
        raise ValueError(response)

    logger.debug(response)
    workflow_name = response["metadata"]["name"]
    logger.info(f"submitted workflow {workflow_name}")


async def get_workflow_info(wf: WorkflowResult) -> dict:
    async with ClientSession(
        headers={"Authorization": f"Bearer {get_token()}"}
    ) as client:
        async with client.get(
            f"{wf.opts.url}/api/v1/workflows/{NAMESPACE}/{wf.name}"
        ) as request:
            response = await request.json()

    if request.status == BAD_REQUEST:
        raise ValueError(response)

    return response


async def get_workflow_workdir(wf: WorkflowResult) -> Path:
    data = await get_workflow_info(wf)
    params = [
        p["value"]
        for p in data["spec"]["arguments"]["parameters"]
        if p["name"] == "workdir"
    ]
    if not params:
        raise ValueError(f"could not find workdir for workflow {data}")
    return Path(params[0])


def get_token() -> str:
    try:
        return environ["ARGO_TOKEN"]
    except KeyError as err:
        raise KeyError("ARGO_TOKEN is not set") from err
