package cd.casic.ci.process.process.service.aflManager.impl;

import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.SeedsCountResp;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.engine.constant.PipelineVariableConstant;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.process.dao.aflManager.AflSeedInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflSeedInfo;
import cd.casic.ci.process.process.service.aflManager.AflSeedInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author HopeLi
 * @version v1.0
 * @ClassName TargetVersionServiceImpl
 * @Date: 2025/5/17 15:20
 * @Description:
 */
@Service
@Slf4j
public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedInfo> implements AflSeedInfoService {

    @Resource
    private RunContextManager runContextManager;

    @Resource
    private ResourceManagerService resourceManagerService;

    private static final String remoteFilePath = "/home/casic/706/yunqi/";

    private static final String seedFilePath = "/ai_afl/default/queue/";

    @Override
    public List<SeedsCountResp> findSeedsCount(AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
        List<SeedsCountResp> seedsCounts = new ArrayList<>(0);

        if (StringUtils.isEmpty(req.getPipelineId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId不能为空");
        }

        BaseRunContext pipelineRunContext = runContextManager.getContext(req.getPipelineId());
        if (ObjectUtils.isEmpty(pipelineRunContext)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到pipeline运行上下文");
        }
        String resourceId = pipelineRunContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) pipelineRunContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
//        String resourceId = "2";
        if (StringUtils.isEmpty(resourceId)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
        }

        ResourceDetailResp resourceById = resourceManagerService.findResourceDetailById(resourceId);
        if (resourceById == null || resourceById.getMachineInfo() == null) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
        }

        MachineInfoDO resourceMachine = resourceById.getMachineInfo();

        List<String> resultList = SftpUploadUtil.findCreateTimeByCommand(resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/queue/");

        //解析resultList

        //todo 分区计算交由前端处理了，代码暂且注释掉，若前端无法处理则延续算法后端解决
        //分区计算
        //int timeWindow = 0;
        for (String o : resultList) {
            SeedsCountResp seedsCount = new SeedsCountResp();

            String[] lineParts = o.split("\\s+创建时间:\\s+");
            if (lineParts.length < 2) {
                System.err.println("无效格式: " + o);
                break;
            }

            String fileNamePart = lineParts[0]; // 文件信息部分
            String createTime = lineParts[1];   // 创建时间

            // 提取 rep 值
            int repValue = 0;
            String seedId = "";
            fileNamePart = fileNamePart.substring(fileNamePart.lastIndexOf("/") + 1);
            for (String part : fileNamePart.split(",")) {
                if (part.startsWith("rep:")) {
                    repValue = Integer.parseInt(part.substring(4));
                    break;
                }
                if (part.startsWith("id:")) {
                    seedId = part.substring(4);
                }
            }

            // 解析创建时间
            // 截取到秒部分（即去掉 .934800255 +0000）
            String truncatedTime = createTime.split("\\.")[0]; // 得到：2025-07-06 02:17:39

            // 使用仅包含年月日时分秒的格式解析
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            LocalDateTime createDateTime = LocalDateTime.parse(truncatedTime, formatter);

            // 获取开始时间
            BaseRunContext taskRunContext = runContextManager.getContext(req.getTaskId());
            if (ObjectUtils.isEmpty(taskRunContext)){
                throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到task运行上下文");
            }
            LocalDateTime startTime = taskRunContext.getStartTime();

//             //使用支持微秒的格式
//            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
//
            // 解析为 LocalDateTime
//            LocalDateTime startTime = LocalDateTime.parse("2025-06-30 11:45:51.875000", formatter1);

            // 计算时间差（分钟）
            Duration duration = Duration.between(startTime, createDateTime);
            int minutesDifference = Math.toIntExact(Math.abs(duration.toMinutes()));

            seedsCount.setRepValue(repValue);
            seedsCount.setMinutesDifference(minutesDifference);
            seedsCount.setSeedId(seedId);
            seedsCounts.add(seedsCount);

//            if (minutesDifference < timeWindow){
//                if (!ObjectUtils.isEmpty(seedsCounts)){
//                    //将数据统计到上一个时间窗口中
//                    SeedsCountResp seedsCountResp = seedsCounts.get(seedsCounts.size() - 1);
//                    Integer value = seedsCountResp.getRepValue();
//                    seedsCountResp.setRepValue(value + repValue);
//                }
//            } else if (minutesDifference > timeWindow){
//                timeWindow = timeWindow + 100;
//                seedsCount.setTimeWindow(timeWindow);
//                seedsCount.setRepValue(repValue);
//                seedsCounts.add(seedsCount);
//
//            }else {
//                if (!ObjectUtils.isEmpty(seedsCounts)){
//                    //将数据统计到上一个时间窗口中
//                    SeedsCountResp seedsCountResp = seedsCounts.get(seedsCounts.size() - 1);
//                    Integer value = seedsCountResp.getRepValue();
//                    seedsCountResp.setRepValue(value + repValue);
//
//                    //同时新增下一个100分钟统计的时间窗口数据
//                    seedsCount.setTimeWindow(timeWindow + 100);
//                    seedsCount.setRepValue(0);
//                    seedsCounts.add(seedsCount);
//                }
//            }
        }
        return seedsCounts;
    }

    @Override
    public void saveAflSeedInfo(AflManagerReq req) {
        if (StringUtils.isEmpty(req.getPipelineId()) || StringUtils.isEmpty(req.getTaskId())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId或者taskId不能为空");
        }
        String uuid = req.getGroupIdentifier();

        BaseRunContext runContext = runContextManager.getContext(req.getPipelineId());
        if (ObjectUtils.isEmpty(runContext)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到运行上下文");
        }
        String resourceId = runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
        if (StringUtils.isEmpty(resourceId)){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
        }

        ResourceDetailResp resourceById = resourceManagerService.findResourceDetailById(resourceId);
        if (resourceById == null || resourceById.getMachineInfo() == null) {
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
        }

        MachineInfoDO resourceMachine = resourceById.getMachineInfo();
        String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
        resourceMachine.setPassword(password);
        try {
            // 步骤1：列出源目录下的所有文件
            List<String> files = SftpUploadUtil.listFilesInRemoteDirectory(
                    resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + seedFilePath);

            if (!CollectionUtils.isEmpty(files)) {
                // 步骤2：下载文件流并保存到数据库
                Map<String,byte[]> copiedFiles = SftpUploadUtil.copyRemoteFilesToByteArray(
                        resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(), null, files);
                System.out.println("共下载 " + copiedFiles.size() + " 个文件");

                List<AflSeedInfo> aflSeedInfos = new ArrayList<>(0);
                if (!ObjectUtils.isEmpty(copiedFiles)){
                    //新增数据到seed表中
                    for (Map.Entry<String, byte[]> entry : copiedFiles.entrySet()) {
                        String key = entry.getKey();
                        byte[] value = entry.getValue();

                        AflSeedInfo aflSeedInfo = new AflSeedInfo();

                        // 提取文件名部分（queue/之后的内容）
                        String fileNamePart = key.substring(key.indexOf("queue/") + 6);

                        // 使用正则匹配 id: 开头的内容
                        java.util.regex.Pattern patternId = java.util.regex.Pattern.compile("id:([^,]+)");
                        java.util.regex.Matcher matcherId = patternId.matcher(fileNamePart);

                        // 使用正则匹配 rep: 开头的内容
                        java.util.regex.Pattern patternRep = java.util.regex.Pattern.compile("rep:(\\d+)");
                        java.util.regex.Matcher matcherRep = patternRep.matcher(fileNamePart);

                        if (matcherRep.find()) {
                            String repValue = matcherRep.group(1);
                            aflSeedInfo.setSeedAmount(repValue);
                        }

                        if (matcherId.find()) {
                            String idValue = matcherId.group(1);
                            aflSeedInfo.setSeedId(idValue);
                        }

                        aflSeedInfo.setFileContent(value);
                        if (!StringUtils.isEmpty(req.getTaskId())){
                            aflSeedInfo.setTaskId(req.getTaskId());
                        }
                        if (!StringUtils.isEmpty(req.getPipelineHistoryId())){
                            aflSeedInfo.setPipelineHistoryId(req.getPipelineHistoryId());
                        }
                        aflSeedInfo.setPipelineId(req.getPipelineId());
                        aflSeedInfo.setGroupIdentifier(uuid);

                        aflSeedInfos.add(aflSeedInfo);
                    }
                }

                if (!CollectionUtils.isEmpty(aflSeedInfos)){
                    //查询种子运行分钟数，同时入库
                    List<SeedsCountResp> seedsCount = this.findSeedsCount(req);
                    if (!CollectionUtils.isEmpty(seedsCount)){
                        aflSeedInfos.forEach(o->{
                            seedsCount.forEach(j->{
                                if (o.getSeedId().equals(j.getSeedId())){
                                    o.setMinutesDifference(j.getMinutesDifference());
                                }
                            });
                        });
                    }
                    baseMapper.insertBatch(aflSeedInfos);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateHistoryPipelineIdByAflSeedInfo(AflManagerReq req) {
        if (!StringUtils.isEmpty(req.getGroupIdentifier())){
            throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"groupIdentifier不能为空");
        }
        QueryWrapper<AflSeedInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("group_identifier", req.getGroupIdentifier());
        List<AflSeedInfo> aflSeedInfos = baseMapper.selectList(wrapper);
        if (!Collections.isEmpty(aflSeedInfos)){
            aflSeedInfos.forEach(o->{
                o.setPipelineHistoryId(req.getPipelineHistoryId());
            });
        }
        baseMapper.updateBatch(aflSeedInfos);
    }
}
