package com.cmvr.test.service;

import cmvr.msgs.Agv;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.model.biohead.EdgeFacialExpressionVO;
import com.cmvr.edge.client.model.hlc.EdgeTouchVO;
import com.cmvr.edge.client.service.EdgeBioHeadService;
import com.cmvr.edge.client.service.EdgeCameraService;
import com.cmvr.edge.client.service.EdgeHlcService;
import com.cmvr.edge.client.service.EdgeMicrophoneService;
import com.cmvr.edge.client.service.EdgeSpeakerService;
import com.cmvr.edge.client.service.EdgeAgvService;
import com.cmvr.edge.client.service.EdgeArmService;
import com.cmvr.device.service.InspectionAlertListenService;
import com.cmvr.llm.service.LLMAiAgentPlatformService;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.operator.edge.EdgeManualInspectionOperateService;
import com.cmvr.test.flow.runtime.operator.llm.InspectionMeterRecognizeOperateService;
import com.cmvr.test.model.vo.FlowActionRequestVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class FlowActionExecutorService {
    private final EdgeCameraService edgeCameraService;
    private final EdgeBioHeadService edgeBioHeadService;
    private final EdgeMicrophoneService edgeMicrophoneService;
    private final EdgeSpeakerService edgeSpeakerService;
    private final EdgeHlcService edgeHlcService;
    private final LLMAiAgentPlatformService llmAiAgentPlatformService;
    private final EdgeAgvService edgeAgvService;
    private final InspectionAlertListenService inspectionAlertListenService;
    private final EdgeArmService edgeArmService;
    private final EdgeManualInspectionOperateService edgeManualInspectionOperateService;
    private final InspectionMeterRecognizeOperateService inspectionMeterRecognizeOperateService;

    public String actionExecute(FlowActionRequestVO req) {

        ActionEnum action = ActionEnum.fromAction(req.getAction());

        if (ObjUtil.isEmpty(action)) {
            throw new GlobalException("不存在此行为!");
        }

        switch (action.getOperate()) {
            case "EDGE":
                return executeEdgeAction(action, req);

            case "LLM":
                return executeLLMAction(action, req);

            default:
                throw new GlobalException("仅设备和大模型 Action 可调用!");
        }
    }

    private String executeEdgeAction(ActionEnum action, FlowActionRequestVO req) {
        JSONObject payload = req.getPayload();
        String terminalId = payload.getString("terminalId");
        String deviceId = payload.getString("deviceId");

        // 巡检报警监听组件只需要终端ID和事件类型，不需要设备ID。
        if (ActionEnum.INSPECTION_ALERT_LISTEN_START.equals(action)
                || ActionEnum.INSPECTION_ALERT_LISTEN_STOP.equals(action)) {
            return executeInspectionAlertAction(action, payload);
        }
        if (ActionEnum.INSPECTION_MANUAL_REVIEW_CREATE.equals(action)) {
            TaskNodeExecuteMessage message = buildSingleNodeMessage(action, payload);
            return edgeManualInspectionOperateService.execute(message).getOutputParams().toJSONString();
        }

        if (StrUtil.isEmpty(terminalId) || StrUtil.isEmpty(deviceId)) {
            throw new GlobalException("EDGE 类型动作必须提供 terminalId 和 deviceId");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(terminalId);
        edgeCommonVO.setDeviceId(deviceId);
        switch (action) {
            // ==== 相机 ====
            case CAMERA_START:
                return edgeCameraService.start(edgeCommonVO);
            case CAMERA_STOP:
                return edgeCameraService.stop(edgeCommonVO);
            case CAMERA_GETRGBIMAGE:
                return edgeCameraService.getRGBImage(edgeCommonVO);
            case CAMERA_RECORDING_START:
                return edgeCameraService.startRecording(edgeCommonVO);
            case CAMERA_RECORDING_STOP:
                return edgeCameraService.stopRecording(edgeCommonVO);

            // ==== 麦克风 ====
            case MICROPHONE_START:
                return edgeMicrophoneService.startRecord(edgeCommonVO);
            case MICROPHONE_STOP:
                return edgeMicrophoneService.stopRecord(edgeCommonVO);

            // ==== 触控 ====
            case TOUCH:
                EdgeTouchVO edgeTouchVO = payload.to(EdgeTouchVO.class);
                return edgeHlcService.touch(edgeTouchVO);

            // ==== 机械臂 ====
            case ARM_MOVE_TO_POINT:
                return executeArmMoveToPoint(edgeCommonVO, payload);

            // ==== 语料 ====
            case VI_PLAY_CORPUS:
                String audioPath = payload.getString("audioPath");
                return edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);

            // ==== 头部 ====
            case BIO_HEAD_SPEAK_START:
                return edgeBioHeadService.speakStart(edgeCommonVO);
            case BIO_HEAD_SPEAK_STOP:
                return edgeBioHeadService.speakStop(edgeCommonVO);
            case BIO_HEAD_SPECIAL_EXPRESSION:
                EdgeFacialExpressionVO edgeFacialExpressionVO = payload.to(EdgeFacialExpressionVO.class);
                edgeFacialExpressionVO.setTerminalId(terminalId);
                edgeFacialExpressionVO.setDeviceId(deviceId);
                return edgeBioHeadService.setExpression(edgeFacialExpressionVO);

            // ==== AGV ====
            case AGV_MOVE_TO_POINT: {
                log.info("执行AGV移动到指定位置操作");
                
                // 从payload中获取机器人ID和坐标信息
                String deviceId1 = payload.getString("deviceId");
                if (StrUtil.isEmpty(deviceId1)) {
                    throw new GlobalException("机器人ID(deviceId)不能为空");
                }
                
                Double x = payload.getDouble("x");
                Double y = payload.getDouble("y");
                Double theta = payload.getDouble("theta");
                
                // 参数验证
                if (x == null || y == null) {
                    throw new GlobalException("X和Y坐标不能为空");
                }
                
                // 构建目标位姿
                Agv.AgvPose2d pose = Agv.AgvPose2d.newBuilder()
                    .setX(x)
                    .setY(y)
                    .setTheta(theta != null ? theta : 0.0)
                    .build();
                
                // 直接调用边缘端AGV服务
                edgeAgvService.navigateToPose(edgeCommonVO, pose);
                
                log.info("AGV移动任务下发成功");
                
                // 返回结果字符串
                return "AGV移动任务下发成功";
            }

            default:
                throw new UnsupportedOperationException("未实现的 EDGE Action: " + action.name());
        }
    }

    private String executeArmMoveToPoint(EdgeCommonVO edgeCommonVO, JSONObject payload) {
        Double x = payload.getDouble("x");
        Double y = payload.getDouble("y");
        Double z = payload.getDouble("z");
        Double rx = payload.getDouble("rx");
        Double ry = payload.getDouble("ry");
        Double rz = payload.getDouble("rz");
        String frame = payload.getString("frame");
        Double velocity = payload.getDouble("velocity");
        Double acceleration = payload.getDouble("acceleration");
        Double blendRadius = payload.getDouble("blendRadius");

        if (x == null || y == null || z == null) {
            throw new GlobalException("X、Y、Z坐标不能为空");
        }
        if (rx == null || ry == null || rz == null) {
            throw new GlobalException("RX、RY、RZ旋转角度不能为空");
        }

        // 单节点执行和正式工作流保持一致：先开启力矩，再下发笛卡尔直线运动。
        edgeArmService.torqueOn(edgeCommonVO);
        edgeArmService.moveL(
                edgeCommonVO,
                x,
                y,
                z,
                rx,
                ry,
                rz,
                frame,
                velocity,
                acceleration,
                blendRadius
        );
        return "机械臂末端运动任务下发成功";
    }

    private String executeInspectionAlertAction(ActionEnum action, JSONObject payload) {
        String terminalId = payload.getString("terminalId");
        java.util.List<String> types = resolveInspectionAlertEventTypes(payload);

        InspectionAlertListenService.ListenState state;
        if (ActionEnum.INSPECTION_ALERT_LISTEN_START.equals(action)) {
            state = inspectionAlertListenService.startListen(terminalId, types);
        } else {
            state = inspectionAlertListenService.stopListen(terminalId, types);
        }
        return JSONObject.toJSONString(state);
    }

    private java.util.List<String> resolveInspectionAlertEventTypes(JSONObject payload) {
        java.util.List<String> types = new java.util.ArrayList<>();
        Object eventTypes = payload.get("eventTypes");

        if (eventTypes instanceof Iterable) {
            for (Object item : (Iterable<?>) eventTypes) {
                if (item != null) {
                    types.add(String.valueOf(item));
                }
            }
        } else if (eventTypes != null) {
            addInspectionAlertEventTypes(types, String.valueOf(eventTypes));
        }

        addInspectionAlertEventTypes(types, payload.getString("eventType"));
        return types;
    }

    private void addInspectionAlertEventTypes(java.util.List<String> types, String value) {
        if (StrUtil.isBlank(value)) {
            return;
        }
        for (String item : value.split(",")) {
            types.add(item.trim());
        }
    }

    private String executeLLMAction(ActionEnum action, FlowActionRequestVO req) {
        log.info("LLM 执行动作: {}", action);

        switch (action) {
            case TOUCH_COORDINATES:
                return "LLM 触控坐标 OK";
            case INTENT_RECOGNITION:
                return "LLM 意图识别 OK";
            case GENERATE_ADVANCED_AUDIO:
                return "LLM 高级音频生成 OK";
            case AI_AGENT_PLATFORM:
                return llmAiAgentPlatformService.query(action.getAction(), req.getPayload().getJSONObject("config").getString("text"), req.getPayload().getJSONObject("config").getString("apiKey"), req.getPayload().getBoolean("invokeTts"), req.getPayload().getJSONObject("tts")).toString();
            case INSPECTION_METER_RECOGNIZE:
                return inspectionMeterRecognizeOperateService.execute(
                        buildSingleNodeMessage(action, req.getPayload())).getOutputParams().toJSONString();
            default:
                throw new UnsupportedOperationException("未实现的 LLM Action: " + action);
        }
    }

    private TaskNodeExecuteMessage buildSingleNodeMessage(ActionEnum action, JSONObject payload) {
        TaskNodeExecuteMessage message = new TaskNodeExecuteMessage();
        message.setAction(action);
        message.setInputParams(payload == null ? new JSONObject() : payload);
        return message;
    }
}

