package com.multictrl.common.utils.kmz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.multictrl.common.constant.BusinessConstant;
import com.multictrl.common.constant.SetActionParams;
import com.multictrl.modules.business.dto.RouteDTO;
import com.multictrl.modules.business.dto.RouteWaypointDTO;
import com.multictrl.modules.business.dto.WaypointActionDTO;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Xml生成工具
 *
 * @author Sdy
 * @since 1.0.0 2026/4/21
 */
public class XmlUtils {

    /**
     * 添加航点航线missionConfig节点（任务信息）
     */
    public static void addMissionConfigElement(Element dc, RouteDTO route) {
        //创建missionConfig节点（任务信息）
        Element missionConfig = dc.addElement("wpml:missionConfig");
        missionConfig.addElement("wpml:flyToWaylineMode").setText(route.getFlyToWaylineMode());
        missionConfig.addElement("wpml:finishAction").setText(route.getFinishAction());
        missionConfig.addElement("wpml:exitOnRCLost").setText(route.getExitOnRcLost());
        if ("executeLostAction".equals(route.getExitOnRcLost())) {
            missionConfig.addElement("wpml:executeRCLostAction").setText(route.getExecuteRcLostAction());
        }
        missionConfig.addElement("wpml:takeOffSecurityHeight").setText(route.getTakeoffSecurityHeight() + "");
        missionConfig.addElement("wpml:globalTransitionalSpeed").setText(route.getGlobalTransitionalSpeed() + "");
        missionConfig.addElement("wpml:globalRTHHeight").setText(route.getGlobalRthHeight() + "");

        //todo飞行器信息/负载信息
        Element droneInfo = missionConfig.addElement("wpml:droneInfo");
        /*droneInfo.addElement("wpml:droneEnumValue").setText(uavModel.getType());
        droneInfo.addElement("wpml:droneSubEnumValue").setText(uavModel.getSubType());*/

        Element payloadInfo = missionConfig.addElement("wpml:payloadInfo");
        /*payloadInfo.addElement("wpml:payloadEnumValue").setText(type);
        payloadInfo.addElement("wpml:payloadSubEnumValue").setText("0");
        payloadInfo.addElement("wpml:payloadPositionIndex").setText("0");*/
    }

    /**
     * 获取航点动作
     */
    public static Map<Integer, List<WaypointActionDTO>> getWaypointActionMap(List<RouteWaypointDTO> waypointList) {
        Map<Integer, List<WaypointActionDTO>> maps = new HashMap<>();
        for (RouteWaypointDTO waypoint : waypointList) {
            List<WaypointActionDTO> actionList = waypoint.getWaypointActionList();
            if (CollectionUtil.isEmpty(actionList)) {
                actionList = Lists.newArrayList();
            }
            maps.put(waypoint.getWaypointSort(), actionList);
        }

        return maps;
    }

    /**
     * 添加转弯模式/偏航模式
     */
    public static void addWaypointTurnMode(Element placemark, RouteWaypointDTO waypoint) {
        Element waypointHeadingParam = placemark.addElement("wpml:waypointHeadingParam");
        waypointHeadingParam.addElement("wpml:waypointHeadingMode").setText(waypoint.getWaypointHeadingMode());
//            waypointHeadingParam.addElement("wpml:waypointHeadingAngle").setText("0");
        if (StrUtil.isNotBlank(waypoint.getWaypointHeadingAngle())) {
            waypointHeadingParam.addElement("wpml:waypointHeadingAngle").setText(waypoint.getWaypointHeadingAngle());
        }
//            waypointHeadingParam.addElement("wpml:waypointPoiPoint").setText("0.000000,0.000000,0.000000");
        if (StrUtil.isNotBlank(waypoint.getWaypointPoiPoint())) {
            waypointHeadingParam.addElement("wpml:waypointPoiPoint").setText(waypoint.getWaypointPoiPoint());
        }
        waypointHeadingParam.addElement("wpml:waypointHeadingPathMode").setText(waypoint.getWaypointHeadingPathMode());
        Element waypointTurnParam = placemark.addElement("wpml:waypointTurnParam");
        waypointTurnParam.addElement("wpml:waypointTurnMode").setText(waypoint.getWaypointTruningMode());
        if (StrUtil.isNotBlank(waypoint.getWaypointTurnDampingDist())) {
            waypointTurnParam.addElement("wpml:waypointTurnDampingDist").setText(waypoint.getWaypointTurnDampingDist());
        }
        placemark.addElement("wpml:useStraightLine").setText("1");
    }

    /**
     * 添加航点动作
     *
     * @param placemark 元素
     * @param waypoint  点位
     */
    public static void addWaypointAction(Element placemark, RouteWaypointDTO waypoint, Map<Integer, List<WaypointActionDTO>> maps) {
        List<WaypointActionDTO> actionList = waypoint.getWaypointActionList();
        List<WaypointActionDTO> reachPoint = Lists.newArrayList();
        List<WaypointActionDTO> otherAction = Lists.newArrayList();

        for (WaypointActionDTO actionDTO : actionList) {
            String actionType = actionDTO.getActionType();
            if (BusinessConstant.EQUAL_TIME_TAKE_PHOTO_FLAG.equals(actionType) ||
                    BusinessConstant.EQUAL_DISTANCE_TAKE_PHOTO_FLAG.equals(actionType) || BusinessConstant.FINISH_TAKE_PHOTO_FLAG.equals(actionType)) {
                otherAction.add(actionDTO);
            } else {
                reachPoint.add(actionDTO);
            }
        }

        if (CollectionUtil.isNotEmpty(reachPoint)) {
            Element actionGroup = placemark.addElement("wpml:actionGroup");
            actionGroup.addElement("wpml:actionGroupId").setText(getNextGlobalActionGroupId(actionGroup) + "");
            actionGroup.addElement("wpml:actionGroupStartIndex").setText(waypoint.getWaypointSort() + "");
            actionGroup.addElement("wpml:actionGroupEndIndex").setText(waypoint.getWaypointSort() + "");
            actionGroup.addElement("wpml:actionGroupMode").setText("sequence");
            Element actionTrigger = actionGroup.addElement("wpml:actionTrigger");
            actionTrigger.addElement("wpml:actionTriggerType").setText(BusinessConstant.DEFAULT_ACTION_TRIGGER_TYPE);

            for (int j = 0; j < reachPoint.size(); j++) {
                WaypointActionDTO actionDTO = reachPoint.get(j);
                Element action = actionGroup.addElement("wpml:action");
                action.addElement("wpml:actionId").setText(j + "");
                action.addElement("wpml:actionActuatorFunc").setText(StrUtil.splitTrim(actionDTO.getActionType(), "_").get(0));
                Element actionActuatorFuncParam = action.addElement("wpml:actionActuatorFuncParam");
                actionDTO.setWaypointOrder(waypoint.getWaypointSort() + "");
                SetActionParams.executeAction(actionDTO, actionActuatorFuncParam);
            }
        }

        //等时等距处理
        if (CollectionUtil.isNotEmpty(otherAction)) {
            addEqualTimeEqualDistanceTakePhotoAction(placemark, waypoint, otherAction, maps);
        }
    }

    /**
     * 查找下一个可用的 actionGroupId（从0开始递增）
     *
     * @param element 节点
     * @return 下一个可用的 actionGroupId 值
     */
    private static int getNextGlobalActionGroupId(Element element) {
        Element rootElement = element.getDocument().getRootElement();
        int maxId = -1;

        List<Element> actionGroups = rootElement.elements("wpml:actionGroup");
        for (Element actionGroup : actionGroups) {
            List<Element> existingElements = actionGroup.elements("wpml:actionGroupId");

            for (Element e : existingElements) {
                try {
                    int id = Integer.parseInt(e.getText());
                    if (id > maxId) {
                        maxId = id;
                    }
                } catch (NumberFormatException ignored) {
                }
            }
        }

        return maxId + 1; // 返回下一个可用 ID
    }

    /**
     * 等时等距拍照
     */
    private static void addEqualTimeEqualDistanceTakePhotoAction(Element placemark, RouteWaypointDTO waypoint
            , List<WaypointActionDTO> otherAction, Map<Integer, List<WaypointActionDTO>> maps) {
        for (int i = 0; i < otherAction.size(); i++) {
            WaypointActionDTO currentAction = otherAction.get(i);
            String actionType = currentAction.getActionType();
            if (BusinessConstant.FINISH_TAKE_PHOTO_FLAG.equals(actionType)) continue;
            String finishActionValue = null;
            for (int j = i + 1; j < otherAction.size(); j++) {
                WaypointActionDTO futureAction = otherAction.get(j);
                if (BusinessConstant.FINISH_TAKE_PHOTO_FLAG.equals(futureAction.getActionType())) {
                    finishActionValue = futureAction.getActionValue();
                    break;
                }
            }

            // 如果当前列表没有找到 finish 动作，尝试查找后续列表中的 finish 动作
            if (finishActionValue == null) {
                for (int ii = waypoint.getWaypointSort() + 1; ii < maps.size(); ii++) {
                    List<WaypointActionDTO> dtos = maps.get(ii);
                    for (WaypointActionDTO futureAction : dtos) {
                        if (BusinessConstant.FINISH_TAKE_PHOTO_FLAG.equals(futureAction.getActionType())) {
                            finishActionValue = futureAction.getActionValue();
                            break;
                        }
                    }
                    if (finishActionValue != null) break;
                }
            }

            if (finishActionValue == null) break;
            if (BusinessConstant.EQUAL_DISTANCE_TAKE_PHOTO_FLAG.equals(actionType) || BusinessConstant.EQUAL_TIME_TAKE_PHOTO_FLAG.equals(actionType)) {
                Integer waypointIndex = waypoint.getWaypointSort();
                Element actionGroup = placemark.addElement("wpml:actionGroup");
                actionGroup.addElement("wpml:actionGroupId").setText(getNextGlobalActionGroupId(actionGroup) + "");
                actionGroup.addElement("wpml:actionGroupStartIndex").setText(waypointIndex + "");
                actionGroup.addElement("wpml:actionGroupEndIndex").setText(finishActionValue);
                actionGroup.addElement("wpml:actionGroupMode").setText("sequence");
                Element actionTrigger = actionGroup.addElement("wpml:actionTrigger");
                actionTrigger.addElement("wpml:actionTriggerType").setText(actionType);
                actionTrigger.addElement("wpml:actionTriggerParam").setText(currentAction.getActionValue());

                Element action = actionGroup.addElement("wpml:action");
                action.addElement("wpml:actionId").setText("0");
                action.addElement("wpml:actionActuatorFunc").setText(BusinessConstant.TAKE_PHOTO_FLAG);
                Element actionActuatorFuncParam = action.addElement("wpml:actionActuatorFuncParam");
                currentAction.setWaypointOrder(waypoint.getWaypointSort() + "");
                SetActionParams.executeAction(currentAction, actionActuatorFuncParam);
            }
        }
    }

    /**
     * 文档转字符串
     *
     * @param document 文档
     * @return 返回字符串
     */
    public static String documentToString(Document document) {
        OutputFormat format = OutputFormat.createPrettyPrint();
        StringWriter stringWriter = new StringWriter();
        XMLWriter writer = new XMLWriter(stringWriter, format);
        writer.setEscapeText(false);
        try {
            writer.write(document);
            writer.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return stringWriter.toString();
    }
}
