import copy
import os
import random
import re

from awe.oss import get_file_content
from awe.types.common import Payload
from awe.util.logging import logger
from awe.util.tongyi import translate as tongyi_translate
from awe.util.workflow_assets import build_array_node, build_image_node
from awe.util.util import get_remote_json

TEXT_PARAM_TYPES = {"STRING", "TEXT"}
NUMBER_PARAM_TYPES = {"INT", "FLOAT", "NUMBER"}


def contains_chinese(check_str):
    return bool(re.search('[\u4e00-\u9fff]', check_str))


def translate(text):
    logger.info(f"translate text: {text}")
    if contains_chinese(text):
        logger.info(f"contains chinese, use tongyi translate: {text}")
        return tongyi_translate(text)
    logger.info(f"not contains chinese, use origin text: {text}")
    return text


def get_remote_workflow_from_oss(workflow_code):
    env = os.getenv("ENV")
    appname = os.getenv("APPNAME")
    file_path = f"ai-workflow-engine/workflows/{env}/{appname}/{workflow_code}.json"
    return get_file_content(file_path)


def get_workflow_data(payload: Payload):
    task_id = payload.get("taskId")
    workflow_data = payload.get("workflow")
    if workflow_data is None:
        workflow_url = payload.get("workflowUrl")
        if workflow_url is not None:
            workflow_data = get_remote_json(workflow_url)
    if workflow_data is None:
        workflow_code = payload.get("workflowCode")
        if workflow_code is not None:
            workflow_data = get_remote_workflow_from_oss(workflow_code)
    if workflow_data is None:
        logger.error(f"get workflow data failed, task_id: {task_id}")
        return None
    logger.info(f"workflow_data: {workflow_data}")
    return workflow_data


def build_workflow(workflow_data, params=None):
    if params is None:
        params = workflow_data.get("params")

    logger.info(f"workflow_data: {workflow_data}")
    logger.info(f"params: {params}")

    content_tpl = copy.deepcopy(workflow_data.get("contentTpl"))
    param_tpl = workflow_data.get("paramTpl")
    params = params or workflow_data.get("params")
    logger.info(f"workflow params: {params}")
    if params is None:
        logger.error("workflow params is None, just return content_tpl")
        return content_tpl
    if param_tpl is None:
        logger.error("workflow paramTpl is None, just return content_tpl")
        return content_tpl

    for key in param_tpl:
        param_node = param_tpl.get(f"{key}")
        node_id = param_node.get("nodeId")
        param_key = param_node.get("paramKey")
        param_type = param_node.get("paramType")
        param = params.get(f"{key}")
        node = content_tpl.get(f"{node_id}")
        if node is None:
            logger.error(f"node {node_id} is None, skip it.")
            continue
        inputs = node.get("inputs")
        normalized_param_type = str(param_type).upper() if param_type is not None else None
        if normalized_param_type == "RANDOM":
            if inputs[f"{param_key}"] is None:
                inputs[f"{param_key}"] = random.randint(0, 1125899906842624)
            continue

        if param is None:
            logger.warning(f"param {key} is None")
            continue
        node = build_workflow_node(key, param_node, params, node, node_id)
        content_tpl[f"{node_id}"] = node

    return content_tpl


def build_workflow_node(key, param_node, params, node, node_id):
    inputs = node.get("inputs")
    param = params.get(f"{key}")
    param_key = param_node.get("paramKey")
    param_type = param_node.get("paramType")
    enable_translate = param_node.get("enableTranslate")
    if param_type is None:
        logger.error(f"[WorkflowUtil] paramType is None, skip it, node_id: {node_id}, key: {key}")
        return node

    normalized_param_type = param_type.upper()
    logger.info(f"[WorkflowUtil] param_type: {normalized_param_type}")
    if normalized_param_type in TEXT_PARAM_TYPES:
        inputs[f"{param_key}"] = translate(param) if enable_translate == "Y" else param
    elif normalized_param_type == "IMAGE":
        build_image_node(param, inputs, node, node_id)
    elif normalized_param_type in NUMBER_PARAM_TYPES:
        inputs[f"{param_key}"] = param
    elif normalized_param_type == "ARRAY":
        build_array_node(key, param_key, param_node, param, inputs)
    else:
        logger.warning(f"[WorkflowUtil] paramType not support: {normalized_param_type}")

    node["inputs"] = inputs
    return node
