package com.ruoyi.rocketmq.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.MsgEnum;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.rocketmq.domain.DeviceMessage;
import com.ruoyi.rocketmq.domain.RmDeploymentPolicy;
import com.ruoyi.rocketmq.domain.RmResourceRemote;
import com.ruoyi.rocketmq.domain.vo.PolicyTypeVo;
import com.ruoyi.rocketmq.domain.vo.PolicyVo;
import com.ruoyi.rocketmq.domain.vo.ScriptPolicyVo;
import com.ruoyi.rocketmq.domain.vo.ServerScriptPolicyVo;
import com.ruoyi.rocketmq.mapper.RmDeploymentPolicyMapper;
import com.ruoyi.rocketmq.mapper.RmResourceRemoteMapper;
import com.ruoyi.rocketmq.model.ProducerMode;
import com.ruoyi.rocketmq.producer.MessageProducer;
import com.ruoyi.rocketmq.service.IRmDeploymentPolicyService;
import com.ruoyi.rocketmq.utils.DataProcessUtil;
import com.ruoyi.system.api.RemoteRevenueConfigService;
import com.ruoyi.system.api.domain.RmResourceRegistrationRemote;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务器脚本策略Service业务层处理
 * 
 * @author gyt
 * @date 2025-09-15
 */
@Service
@Slf4j
public class RmDeploymentPolicyServiceImpl implements IRmDeploymentPolicyService 
{
    @Autowired
    private RmDeploymentPolicyMapper rmDeploymentPolicyMapper;
    @Autowired
    private RemoteRevenueConfigService remoteRevenueConfigService;
    @Autowired
    private DataProcessUtil dataProcessUtil;
    @Autowired
    private ProducerMode producerMode;
    @Autowired
    private RmResourceRemoteMapper rmResourceRemoteMapper;

    /**
     * 查询服务器脚本策略
     * 
     * @param id 服务器脚本策略主键
     * @return 服务器脚本策略
     */
    @Override
    public RmDeploymentPolicy selectRmDeploymentPolicyById(Long id)
    {
        RmDeploymentPolicy rmDeploymentPolicy = rmDeploymentPolicyMapper.selectRmDeploymentPolicyById(id);
        // 包含设备名称赋值
        getIncludeNameById(rmDeploymentPolicy);
        return rmDeploymentPolicy;
    }

    /**
     * 查询服务器脚本策略列表
     * 
     * @param rmDeploymentPolicy 服务器脚本策略
     * @return 服务器脚本策略
     */
    @Override
    public List<RmDeploymentPolicy> selectRmDeploymentPolicyList(RmDeploymentPolicy rmDeploymentPolicy)
    {
        List<RmDeploymentPolicy> deploymentPolicyList = rmDeploymentPolicyMapper.selectRmDeploymentPolicyList(rmDeploymentPolicy);
        // 包含设备名称赋值
        deploymentPolicyList.forEach(policy -> {

            getIncludeNameById(policy);
            // 不在线数量赋值
            String deviceMsg = policy.getDeployDevice();
            if (deviceMsg != null) {
                List<String> offOnlineList = new ArrayList<>();
                List<String> successList = new ArrayList<>();
                List<String> failList = new ArrayList<>();
                for (String clientId : deviceMsg.split("\n")) {
                    RmResourceRemote query = new RmResourceRemote();
                    query.setScriptId(policy.getId());
                    query.setClientId(clientId);
                    List<RmResourceRemote> resultList = rmResourceRemoteMapper.selectRmResourceRemoteList(query);
                    if (resultList.isEmpty()) {
                        offOnlineList.add(clientId);
                        continue;
                    }
                    resultList.forEach(resourceRemote -> {
                        if (resourceRemote.getResultFlag() == 0) {
                            failList.add(clientId);
                        } else if (resourceRemote.getResultFlag() == 1) {
                            successList.add(clientId);
                        }
                    });
                }
                policy.setSucessNum(successList.size());
                policy.setSucessClientIds(successList);
                policy.setFailNum(failList.size());
                policy.setFailClientIds(failList);
                policy.setOfflineNum(offOnlineList.size());
                policy.setOfflineClientIds(offOnlineList);
            }
        });

        return deploymentPolicyList;
    }

    /**
     * 根据资源id查询资源名称
     * @param policy
     */
    public void getIncludeNameById(RmDeploymentPolicy policy){
        if(policy == null){
            return;
        }
        if (StringUtils.isBlank(policy.getIncludedDevicesId())) {
            policy.setIncludedDevicesName("");
            return;
        }

        String[] ids = policy.getIncludedDevicesId().split(",");
        R<List<RmResourceRegistrationRemote>> resourceNameList =
                remoteRevenueConfigService.getRegistrationByIds(ids, SecurityConstants.INNER);

        if (resourceNameList == null || resourceNameList.getData() == null) {
            policy.setIncludedDevicesName("");
            return;
        }

        String names = resourceNameList.getData().stream()
                .filter(Objects::nonNull)
                .map(RmResourceRegistrationRemote::getResourceName)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining(","));

        policy.setIncludedDevicesName(names);
        if(policy.getResourceGroupId() != null){
            String resourceGroupName = dataProcessUtil.getResourceGroupNameById(policy.getResourceGroupId());
            policy.setResourceGroupName(resourceGroupName);
        }
    }

    /**
     * 新增服务器脚本策略
     * 
     * @param rmDeploymentPolicy 服务器脚本策略
     * @return 结果
     */
    @Override
    public int insertRmDeploymentPolicy(RmDeploymentPolicy rmDeploymentPolicy)
    {
        rmDeploymentPolicy.setCreateTime(DateUtils.getNowDate());
        rmDeploymentPolicy.setCreateBy(SecurityUtils.getUsername());
        return rmDeploymentPolicyMapper.insertRmDeploymentPolicy(rmDeploymentPolicy);
    }

    /**
     * 修改服务器脚本策略
     * 
     * @param rmDeploymentPolicy 服务器脚本策略
     * @return 结果
     */
    @Override
    public int updateRmDeploymentPolicy(RmDeploymentPolicy rmDeploymentPolicy)
    {
        rmDeploymentPolicy.setUpdateTime(DateUtils.getNowDate());
        // 有修改就改为待下发状态
        rmDeploymentPolicy.setPolicyStatus("0");
        if(rmDeploymentPolicy.getResourceGroupId() == null){
            rmDeploymentPolicy.setResourceGroupIdNull(Boolean.TRUE);
        }
        return rmDeploymentPolicyMapper.updateRmDeploymentPolicy(rmDeploymentPolicy);
    }

    /**
     * 批量删除服务器脚本策略
     * 
     * @param ids 需要删除的服务器脚本策略主键
     * @return 结果
     */
    @Override
    public int deleteRmDeploymentPolicyByIds(Long[] ids)
    {
        return rmDeploymentPolicyMapper.deleteRmDeploymentPolicyByIds(ids);
    }

    /**
     * 删除服务器脚本策略信息
     * 
     * @param id 服务器脚本策略主键
     * @return 结果
     */
    @Override
    public int deleteRmDeploymentPolicyById(Long id)
    {
        return rmDeploymentPolicyMapper.deleteRmDeploymentPolicyById(id);
    }

    @Override
    public int issueDeploymentPolicy(Long id) {
        try {
            // 获取策略详情和资源设备
            RmDeploymentPolicy policy = rmDeploymentPolicyMapper.selectRmDeploymentPolicyById(id);
            if (policy == null) {
                log.error("策略不存在，id: {}", id);
                return 0;
            }

            if (StringUtils.isBlank(policy.getIncludedDevicesId())) {
                policy.setIncludedDevicesName("");
                return 0;
            }
            String[] ids = policy.getIncludedDevicesId().split(",");
            R<List<RmResourceRegistrationRemote>> resourceNameList =
                    remoteRevenueConfigService.getRegistrationByIds(ids, SecurityConstants.INNER);
            List<RmResourceRegistrationRemote> devices = resourceNameList.getData();
            if (CollectionUtils.isEmpty(devices)) {
                return 0;
            }

            // 构建并发送脚本配置
            String[] commands = policy.getCommandContent().split(",");
            List<String> commandList = new ArrayList<>(Arrays.asList(commands));
            List<ScriptPolicyVo.ScriptFile> files = new ArrayList<>();
            ScriptPolicyVo scriptPolicyVo = new ScriptPolicyVo();
            scriptPolicyVo.setPolicyName(policy.getPolicyName());
            scriptPolicyVo.setFilePath(policy.getTargetDirectory());
            scriptPolicyVo.setCommands(commandList);
            scriptPolicyVo.setMethod(policy.getExecutionMethod());
            // 定时执行
            if(policy.getExecutionMethod() == 1){
                Date scheduledTime = policy.getScheduledTime();
                // 转化为时间戳（秒）
                long timestampInSecondes = scheduledTime.getTime() / 1000;
                scriptPolicyVo.setPolicyTime(timestampInSecondes);
            }
            String[] fileTypes = policy.getSourceFilePathType().split(",");
            String[] fileUrls = policy.getSourceFilePath().split(",");
            for(int i=0;i< fileTypes.length;i++){
                ScriptPolicyVo.ScriptFile file = new ScriptPolicyVo.ScriptFile();
                file.setFileType(Integer.parseInt(fileTypes[i]));
                file.setFileUrl(fileUrls[i]);
                String fileUrl = fileUrls[i];
                // 文件名称
                int lastSlashIndex = fileUrl.lastIndexOf("/");
                String fileName = fileUrl.substring(lastSlashIndex + 1);
                file.setFileName(fileName);
                files.add(file);
            }
            scriptPolicyVo.setFiles(files);
            sendDeploymentPolicyToDevices(devices, scriptPolicyVo);
            // 更新策略状态为已下发
            RmDeploymentPolicy deploymentPolicy = new RmDeploymentPolicy();
            deploymentPolicy.setId(id);
            deploymentPolicy.setPolicyStatus("1");
            deploymentPolicy.setDeployTime(DateUtils.getNowDate());
            rmDeploymentPolicyMapper.updateRmDeploymentPolicy(deploymentPolicy);

            return 1;
        } catch (Exception e) {
            log.error("下发策略失败，id: {}", id, e);
            return 0;
        }
    }
    /**
     * 发送配置到设备
     */
    private void sendDeploymentPolicyToDevices(List<RmResourceRegistrationRemote> devices, ScriptPolicyVo scriptPolicyVo) {
        MessageProducer messageProducer = new MessageProducer();
        String configJson = JSONObject.toJSONString(scriptPolicyVo);

        for (RmResourceRegistrationRemote device : devices) {
            try {
                DeviceMessage message = new DeviceMessage();
                message.setClientId(device.getHardwareSn());
                message.setData(configJson);
                message.setDataType(MsgEnum.执行脚本策略.getValue());

                messageProducer.sendAsyncProducerMessage(
                        producerMode.getAgentTopic(),
                        "",
                        "",
                        JSONObject.toJSONString(message)
                );
            } catch (Exception e) {
                log.error("发送设备配置失败，deviceId: {}", device.getHardwareSn(), e);
            }
        }
    }

    /**
     * 根据clientId下发包含此设备未下发的服务器脚本策略
     * @param clientId
     * @return
     */
    @Override
    public int issueDeployPolicyMsgByClientId(String clientId) {
        try {
            // 根据clientId查询未下发的策略信息
            RmDeploymentPolicy queryParam = new RmDeploymentPolicy();
            queryParam.setDeployDevice(clientId);
            queryParam.setPolicyStatus("0");
            // 获取策略详情
            List<RmDeploymentPolicy> policyList = rmDeploymentPolicyMapper.selectRmDeploymentPolicyByClientId(queryParam);
            if (policyList.isEmpty()) {
                log.warn("无待下发策略，clientId: {}", clientId);
                return 0;
            }else{
                for (RmDeploymentPolicy policy : policyList) {
                    // 构建并发送脚本配置
                    ServerScriptPolicyVo scriptPolicyVo = new ServerScriptPolicyVo();
                    scriptPolicyVo.setScriptId(policy.getId().toString());
                    scriptPolicyVo.setPolicyName(policy.getPolicyName());
                    scriptPolicyVo.setFileUrl(policy.getScriptPath());
                    scriptPolicyVo.setCommandParams(policy.getDefaultParams());
                    scriptPolicyVo.setMethod(policy.getExecutionMethod());
                    // 定时执行
                    if(policy.getExecutionMethod() == 1){
                        Date scheduledTime = policy.getScheduledTime();
                        // 转化为时间戳（秒）
                        long timestampInSecondes = scheduledTime.getTime() / 1000;
                        scriptPolicyVo.setPolicyTime(timestampInSecondes);
                    }
                    String[] clientIdArr = policy.getDeployDevice().split("\n");
                    sendDeploymentPolicy(clientIdArr, scriptPolicyVo);
                    // 更新策略状态为已下发
                    RmDeploymentPolicy deploymentPolicy = new RmDeploymentPolicy();
                    deploymentPolicy.setId(policy.getId());
                    deploymentPolicy.setPolicyStatus("1");
                    deploymentPolicy.setDeployTime(DateUtils.getNowDate());
                    rmDeploymentPolicyMapper.updateRmDeploymentPolicy(deploymentPolicy);
                }

                return 1;
            }
        } catch (Exception e) {
            log.error("下发策略失败，clientId: {}", clientId, e);
            return 0;
        }
    }
    /**
     * 发送配置到设备
     */
    private void sendDeploymentPolicy(String[] clientIdArr, ServerScriptPolicyVo scriptPolicyVo) {
        MessageProducer messageProducer = new MessageProducer();

        PolicyVo<ServerScriptPolicyVo> policyVo = new PolicyVo();
        List<ServerScriptPolicyVo> list = new ArrayList<>();
        list.add(scriptPolicyVo);
        policyVo.setContents(list);
        String policyVoStr = JSONObject.toJSONString(policyVo);
        PolicyTypeVo policyTypeVo = new PolicyTypeVo();
        policyTypeVo.setScripts(policyVoStr);
        String configJson = JSONObject.toJSONString(policyTypeVo);
        for (String clientId : clientIdArr) {
            try {
                DeviceMessage message = new DeviceMessage();
                message.setClientId(clientId);
                message.setData(configJson);
                message.setDataType(MsgEnum.获取最新策略应答.getValue());

                messageProducer.sendAsyncProducerMessage(
                        producerMode.getAgentTopic(),
                        "",
                        "",
                        JSONObject.toJSONString(message)
                );
            } catch (Exception e) {
                log.error("发送设备配置失败，deviceId: {}", clientId, e);
            }
        }
    }
}
