package com.cmvr.test.flow.runtime.operator.edge.ti;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.config.properties.MinioProperties;
import com.cmvr.common.core.minio.MinioService;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.common.utils.http.CallAPIUtil;
import com.cmvr.llm.config.APIProperties;
import com.cmvr.llm.config.AgentConfig;
import com.cmvr.llm.util.LargeModelFileUploadUtil;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import com.cmvr.test.flow.runtime.operator.edge.EdgeOperateService;
import com.cmvr.test.service.ex.ExTiVehicleFunctionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class TiTouchOperateService implements EdgeOperateService {

    private final ExTiVehicleFunctionService exTiVehicleFunctionService;
    private final MinioService minioService;
    private final MinioProperties minioProps;
    private final APIProperties apiProperties;

    // 设置运动模式
    public static final List<String> DRIVE_MODE_PATH = Arrays.asList("主页", "设置", "驾驶模式", "运动模式");

    // 打开空调
    public static final List<String> OPEN_AC_PATH = Arrays.asList("主页", "空调", "打开");

    // 所有路径集合
    public static final List<List<String>> ALL_PATHS =
            Arrays.asList(
                    OPEN_AC_PATH,
                    DRIVE_MODE_PATH
            );

    @Override
    public boolean supports(ActionEnum action) {
        return action.name().startsWith("TI_");
    }

    @Override
    public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
        ActionEnum action = message.getAction();
        JSONObject inputParams = message.getInputParams();

        JSONObject output = new JSONObject();


        switch (action) {
            case TI_PATH_SEARCH: {
                // 当前界面
                String currentLocation = inputParams.getString("currentLocation");
                Long vehicleConfigId = inputParams.getLong("vehicleConfigId");
                String clickFunction = inputParams.getString("funcId");
                // 查询功能
                JSONObject funcObj = exTiVehicleFunctionService.findNextClickToFunction(vehicleConfigId, currentLocation, clickFunction);
                // 输出
                output.put("nextLocation", funcObj.get("nextLocation"));
                output.put("isEnd", funcObj.get("isEnd"));
                output.put("iconUrl", funcObj.get("iconUrl"));
                break;
            }
            case TI_TOUCH_COORDINATES: {
                // 页面图片(相机)
                String imageUrl = inputParams.getString("imageUrl");
                String pageImageUrl = uploadImageFromMinio(imageUrl);

                // icon图片
                String iconUrl = inputParams.getString("iconUrl");
                String iconImageUrl = uploadImageFromMinio(iconUrl);

                // 获取触控坐标
                String touchCoordinates = getTouchCoordinates(pageImageUrl, iconImageUrl);

                output.put("touchCoordinates", touchCoordinates);

                break;
            }
            default:
                throw new GlobalException("不支持的触控操作类型: " + action);
        }

        return TaskNodeExecuteResult.success(output);
    }

    private JSONObject getFuncObj(List<Integer> iterations, JSONObject inputParams) {
        JSONArray funcIds = inputParams.getJSONArray("funcId");
        int index = iterations.get(0) - 1;
        Long funcId = funcIds.toJavaList(Long.class).get(index);
        return exTiVehicleFunctionService.queryById(funcId);
    }

    public String test(String imageUrl,String iconUrl) {
        String pageImageUrl = uploadImageFromMinio(imageUrl);

        // icon图片
        String iconImageUrl = uploadImageFromMinio(iconUrl);

        // 获取触控坐标
        return getTouchCoordinates(pageImageUrl, iconImageUrl);
    }

    private String getTouchCoordinates(String pageImageUrl, String iconImageUrl) {
        AgentConfig agentConfig = apiProperties.getAgentConfig(ActionEnum.TI_TOUCH_COORDINATES.getAction());
        Map<String, String> params = new HashMap<>();
        params.put("input_image", pageImageUrl);
        params.put("icon_image", iconImageUrl);

        Map<String, String> headers = new HashMap<>();
        headers.put("Apikey", agentConfig.getAppKey());

        Map<String, String> body = new HashMap<>();
        body.put("AppKey", agentConfig.getAppKey());
        body.put("AppID", agentConfig.getAppId());
        body.put("InputData", JSON.toJSONString(params));
        body.put("UserID", "18888888888");
        String response = CallAPIUtil.doPostJson(apiProperties.getWorkFlowUrl(), headers, body);
        JSONObject resObject1 = JSON.parseObject(response);
        if (resObject1.containsKey("runId")) {
            String processId = resObject1.getString("runId");
            return queryResultByRunId(processId, agentConfig);
        } else {
            throw new GlobalException("未获取到 runId，响应内容：" + response);
        }
    }

    /**
     * 根据 MinIO 文件访问地址上传到商道，返回商道文件地址
     */
    private String uploadImageFromMinio(String url) {
        try {
            String bucketName = minioProps.getBucketName();
            String prefix = StrPool.SLASH + bucketName + StrPool.SLASH;

            String objectName = StrUtil.removePrefix(
                    url,
                    StrUtil.subBefore(url, prefix, true) + prefix
            );

            File imageFile = minioService.getFile(bucketName, objectName);
            byte[] imageBytes = FileUtil.readBytes(imageFile);

            return LargeModelFileUploadUtil.uploadFile(imageBytes);
        } catch (Exception e) {
            log.error("上传 MinIO 文件到商道失败，url={}", url, e);
            throw new GlobalException("图片上传失败");
        }
    }

    private String queryResultByRunId(String processId, AgentConfig agentConfig) {
        Map<String, String> headers = new HashMap<>();
        headers.put("Apikey", agentConfig.getAppKey());

        Map<String, String> body = new HashMap<>();
        body.put("AppKey", agentConfig.getAppKey());
        body.put("AppID", agentConfig.getAppId());
        body.put("RunID", processId);
        body.put("UserID", "18888888888");


        String responseBody;
        JSONObject endNode;
        int failCount = 0;
        int maxFail = 40;

        while (true) {
            responseBody = CallAPIUtil.doPostJson(apiProperties.getQueryResultUrl(), headers, body);
            JSONObject jsonObject = JSON.parseObject(responseBody);

            String status = jsonObject.getString("status");
            if ("success".equals(status)) {
                JSONObject nodes = jsonObject.getJSONObject("nodes");
                if (nodes == null) {
                    throw new GlobalException("响应中 nodes 为空：" + responseBody);
                }

                endNode = findEndNode(nodes);
                if (endNode != null) {
                    break;
                } else {
                    throw new GlobalException("未找到 nodeType=end 的节点：" + nodes);
                }
            } else if ("failed".equals(status)) {
                // 如果失败
                throw new GlobalException(responseBody);
            } else {
                // 处理其他状态码
                failCount++;
                if (failCount > maxFail) {
                    throw new GlobalException("达到最大重试次数，API状态仍未成功：" + status);
                }
            }

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new GlobalException("轮询被中断");
            }
        }

        // 解析 output 内容并清洗
        JSONObject output = endNode.getJSONObject("output");
        String res = output.getString("content");
        if (StrUtil.isEmpty(res)) {
            throw new GlobalException("未找到坐标内容");
        }
        return res;
    }

    /**
     * 从 nodes 中提取 nodeType=end 的节点
     */
    private JSONObject findEndNode(JSONObject nodes) {
        for (Map.Entry<String, Object> entry : nodes.entrySet()) {
            JSONObject node = (JSONObject) entry.getValue();
            if ("end".equalsIgnoreCase(node.getString("nodeType"))) {
                return node;
            }
        }
        return null;
    }
}
