package org.agt.module.license.service.license;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.compress.CompressUtil;
import cn.hutool.extra.compress.archiver.Archiver;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.agt.framework.common.pojo.CommonResult;
import org.agt.framework.common.pojo.PageResult;
import org.agt.framework.common.util.object.BeanUtils;
import org.agt.framework.dict.core.DictFrameworkUtils;
import org.agt.framework.web.core.util.WebFrameworkUtils;
import org.agt.module.infra.api.file.FileApi;
import org.agt.module.license.controller.admin.license.vo.ImportRespVO;
import org.agt.module.license.controller.admin.license.vo.LicenseCodeImportExcelVO;
import org.agt.module.license.controller.admin.license.vo.LicenseDetailVO;
import org.agt.module.license.controller.admin.license.vo.LicenseImportExcelVO;
import org.agt.module.license.controller.admin.license.vo.LicensePageReqVO;
import org.agt.module.license.controller.admin.license.vo.LicensePageRespVO;
import org.agt.module.license.controller.admin.license.vo.LicenseRespVO;
import org.agt.module.license.controller.admin.license.vo.LicenseSaveReqVO;
import org.agt.module.license.dal.dataobject.customer.CustomerDO;
import org.agt.module.license.dal.dataobject.license.LicenseDO;
import org.agt.module.license.dal.dataobject.license.LicenseDetailDO;
import org.agt.module.license.dal.dataobject.license.LicenseDetailHistoryDO;
import org.agt.module.license.dal.dataobject.license.LicenseHistoryDO;
import org.agt.module.license.dal.dataobject.license.LicenseProviderDO;
import org.agt.module.license.dal.dataobject.project.ProjectDO;
import org.agt.module.license.dal.mysql.customer.CustomerMapper;
import org.agt.module.license.dal.mysql.license.LicenseDetailHistoryMapper;
import org.agt.module.license.dal.mysql.license.LicenseDetailMapper;
import org.agt.module.license.dal.mysql.license.LicenseHistoryMapper;
import org.agt.module.license.dal.mysql.license.LicenseMapper;
import org.agt.module.license.dal.mysql.license.LicenseProviderMapper;
import org.agt.module.license.dal.mysql.project.ProjectMapper;
import org.agt.module.license.enums.LicenseStatusEnum;
import org.agt.module.license.framework.util.FileTypeUtils;
import org.agt.module.system.api.mail.MailSendApi;
import org.agt.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
import org.agt.module.system.api.notify.NotifyMessageSendApi;
import org.agt.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.agt.framework.common.exception.util.ServiceExceptionUtil.exception;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_DOWNLOAD_FAILED;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_IMPORT_LIST_IS_EMPTY;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_NOT_EXISTS;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_SN_DUPLICATE;
import static org.agt.module.license.enums.ErrorCodeConstants.LICENSE_UPDATE_FAILED;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_CREATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_CREATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_DELETE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_DELETE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_GENERATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_GENERATE_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_REAPPLY_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_REAPPLY_SUCCESS;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_UPDATE_SUB_TYPE;
import static org.agt.module.license.enums.LogRecordConstants.SYSTEM_LICENSE_UPDATE_SUCCESS;

/**
 * License Service 实现类
 *
 * @author 管理员
 */
@Slf4j
@Service
@Validated
public class LicenseServiceImpl implements LicenseService {

    @Resource
    private LicenseMapper licenseMapper;

    @Resource
    private CustomerMapper customerMapper;

    @Resource
    private ProjectMapper projectMapper;

    @Resource
    private LicenseProviderMapper licenseProviderMapper;

    @Resource
    private FileApi fileApi;

    @Resource
    private MailSendApi mailSendApi;

    @Resource
    private NotifyMessageSendApi notifySendApi;

    @Resource
    private LicenseDetailMapper licenseDetailMapper;

    @Resource
    private LicenseHistoryMapper licenseHistoryMapper;

    @Resource
    private LicenseDetailHistoryMapper licenseDetailHistoryMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_CREATE_SUB_TYPE, bizNo = "{{#license.id}}",
            success = SYSTEM_LICENSE_CREATE_SUCCESS)
    public Long createLicense(LicenseSaveReqVO createReqVO, boolean isReapply) {
        // 校验项目Sn是否唯一, boolean isReapply
        if (!validateLicenseSnUnique(createReqVO.getSerialNo(), createReqVO.getId())) {
            throw exception(LICENSE_SN_DUPLICATE, createReqVO.getSerialNo());
        }

        if (createReqVO.getExpiryDate() != null) {
            createReqVO.setExpiryDate(LocalDateTime.of(createReqVO.getExpiryDate().toLocalDate(), LocalTime.of(23, 59, 59)));
        }
        // 插入
        LicenseDO license = BeanUtils.toBean(createReqVO, LicenseDO.class);
        license.setStatus(LicenseStatusEnum.NOT_APPLIED.getCode());
        if (isReapply) {
            licenseMapper.update(Wrappers.<LicenseDO>lambdaUpdate()
                    .eq(LicenseDO::getId, license.getId())
                    .set(LicenseDO::getExpiryDate, license.getExpiryDate())
                    .set(LicenseDO::getUserNumber, license.getUserNumber())
                    .set(LicenseDO::getSerialNo, license.getSerialNo())
                    .set(LicenseDO::getRanNumber, license.getRanNumber())
                    .set(LicenseDO::getRemark, StrUtil.isBlank(license.getRemark()) ? null : license.getRemark())
                    .set(LicenseDO::getApprover, license.getApprover())
                    .set(LicenseDO::getFileUrl, null)
            );
        } else {
            licenseMapper.insert(license);
        }

        List<LicenseDetailDO> licenseDetails = updateLicenseDetail(createReqVO.getNeCodeList(), license);

        createReqVO.setId(license.getId());
        applyLicense(createReqVO, licenseDetails);

        LogRecordContext.putVariable("license", license);
        // 返回
        return license.getId();
    }

    @Override
    @LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
            success = SYSTEM_LICENSE_UPDATE_SUCCESS)
    public void updateLicense(LicenseSaveReqVO updateReqVO) {
        // 校验项目Sn是否唯一
        if (!validateLicenseSnUnique(updateReqVO.getSerialNo(), updateReqVO.getId())) {
            throw exception(LICENSE_SN_DUPLICATE, updateReqVO.getSerialNo());
        }
        // 校验存在
        LicenseDO licenseDO = validateLicenseExists(updateReqVO.getId());
        if (updateReqVO.getExpiryDate() != null) {
            updateReqVO.setExpiryDate(LocalDateTime.of(updateReqVO.getExpiryDate().toLocalDate(), LocalTime.of(23, 59, 59)));
        }
        if (!(LicenseStatusEnum.IN_APPLICATION.getCode().equals(licenseDO.getStatus())
                || LicenseStatusEnum.REAPPLYING.getCode().equals(licenseDO.getStatus()) || licenseDO.getDataType() == 1)) {
            throw exception(LICENSE_UPDATE_FAILED);
        }

        // 更新
        LicenseDO updateObj = BeanUtils.toBean(updateReqVO, LicenseDO.class);
        licenseMapper.updateById(updateObj);

        licenseDetailMapper.delete(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, updateObj.getId()));

        updateLicenseDetail(updateReqVO.getNeCodeList(), updateObj);

        // 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(licenseDO, LicenseSaveReqVO.class));
        LogRecordContext.putVariable("license", licenseDO);
    }

    private List<LicenseDetailDO> updateLicenseDetail(List<LicenseDetailVO> neCodeList, LicenseDO updateObj) {
        List<LicenseDetailDO> licenseDetails = BeanUtils.toBean(neCodeList, LicenseDetailDO.class);
        for (LicenseDetailDO licenseDetail : licenseDetails) {
            licenseDetail.setId(null);
            licenseDetail.setLicenseId(updateObj.getId());
        }
        licenseDetailMapper.insertBatch(licenseDetails);
        return licenseDetails;
    }

    @Override
    public void applyLicense(LicenseSaveReqVO updateReqVO, List<LicenseDetailDO> licenseDetails) {
        // 发送邮件
        // 1. 准备参数
        Long userId = updateReqVO.getApprover();
        String templateCode = "license_apply"; // 邮件模版，记得在【邮箱管理】中配置噢
        Map<String, Object> templateParams = new HashMap<>();
        ProjectDO projectDO = projectMapper.selectById(updateReqVO.getProjectId());
        CustomerDO customerDO = customerMapper.selectById(projectDO.getCustomerId());
        templateParams.put("customer", customerDO.getName());
        templateParams.put("project", projectDO.getName());
        templateParams.put("sn", updateReqVO.getSerialNo());
        templateParams.put("url", "http://192.168.9.50#/license/generate?id=" + updateReqVO.getId());

        // 2. 发送邮件
        mailSendApi.sendSingleMailToAdmin(new MailSendSingleToUserReqDTO()
                .setUserId(userId).setTemplateCode(templateCode).setTemplateParams(templateParams));

        // 发送站内信
        notifySendApi.sendSingleMessageToAdmin(new NotifySendSingleToUserReqDTO()
                .setUserId(userId).setTemplateCode(templateCode).setTemplateParams(templateParams));

        // 更新表
        LicenseDO licenseDO = new LicenseDO();
        licenseDO.setId(updateReqVO.getId());
        licenseDO.setStatus(LicenseStatusEnum.IN_APPLICATION.getCode());
        licenseDO.setApplicant(WebFrameworkUtils.getLoginUserId());
        licenseDO.setApplicationTime(LocalDateTime.now());
        licenseMapper.updateById(licenseDO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_REAPPLY_SUB_TYPE, bizNo = "{{#license.id}}",
            success = SYSTEM_LICENSE_REAPPLY_SUCCESS)
    public void reapplyLicense(LicenseSaveReqVO updateReqVO) {
        // 校验存在
        validateLicenseExists(updateReqVO.getId());
        // 将现有的license迁移到历史表
        LicenseDO licenseDO = licenseMapper.selectById(updateReqVO.getId());
        List<LicenseDetailDO> licenseDetailDOS = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()));

        LicenseHistoryDO historyDO = BeanUtils.toBean(licenseDO, LicenseHistoryDO.class);

        licenseDetailMapper.delete(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()));

        for (LicenseDetailVO neCode : updateReqVO.getNeCodeList()) {
            neCode.setId(null);
            neCode.setFileUrlLegacy(null);
            neCode.setFileUrl(null);
            neCode.setProviderId(null);
        }
        Long licenseId = createLicense(updateReqVO, true);
        historyDO.setId(null);
        historyDO.setLicenseId(licenseId);
        licenseHistoryMapper.insert(historyDO);

        if (CollUtil.isNotEmpty(licenseDetailDOS)) {
            List<LicenseDetailHistoryDO> detailHistoryDOList = BeanUtils.toBean(licenseDetailDOS, LicenseDetailHistoryDO.class);
            detailHistoryDOList.forEach(c -> {
                c.setId(null);
                c.setLicenseId(historyDO.getId());
            });
            licenseDetailHistoryMapper.insertBatch(detailHistoryDOList);
        }
        licenseMapper.update(Wrappers.<LicenseDO>lambdaUpdate().eq(LicenseDO::getId, licenseId)
                .set(LicenseDO::getStatus, LicenseStatusEnum.REAPPLYING.getCode()).set(LicenseDO::getDataType, null));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_GENERATE_SUB_TYPE, bizNo = "{{#license.id}}",
            success = SYSTEM_LICENSE_GENERATE_SUCCESS)
    public String generate(Long id) {
        LicenseDO licenseDO = licenseMapper.selectById(id);

        List<LicenseDetailDO> licenseDetails = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()));

        List<String> resultList = new ArrayList<>(); // 初始化结果列表
        for (LicenseDetailDO neCodeVO : licenseDetails) {
            // 添加数据到License提供者表
            LicenseProviderDO licenseProviderDO = new LicenseProviderDO();
            licenseProviderDO.setProjectId(licenseDO.getProjectId());
            licenseProviderDO.setSerialNo(licenseDO.getSerialNo());
            licenseProviderDO.setExpiryDate(licenseDO.getExpiryDate());
            licenseProviderDO.setRanNumber(licenseDO.getRanNumber());
            licenseProviderDO.setUserNumber(licenseDO.getUserNumber());
            List<Integer> neList = neCodeVO.getNeList();
            List<String> neLabels = new ArrayList<>();
            for (Integer ne : neList) {
                String label = DictFrameworkUtils.parseDictDataLabel("lic_ne_all", ne.toString());
                if (StrUtil.isBlank(label)) {
                    label = DictFrameworkUtils.parseDictDataLabel("lic_ne_5g", ne.toString());
                    if (StrUtil.isBlank(label)) {
                        label = DictFrameworkUtils.parseDictDataLabel("lic_ne_4g", ne.toString());
                        if (StrUtil.isBlank(label)) {
                            label = DictFrameworkUtils.parseDictDataLabel("lic_ne_23g", ne.toString());
                            if (StrUtil.isBlank(label)) {
                                label = DictFrameworkUtils.parseDictDataLabel("lic_ne_add", ne.toString());
                            }
                        }
                    }
                }
                neLabels.add(label);
            }
            // 重复网元后面添加序号
            String currentElement = neLabels.get(0);
            boolean isDuplicate = false;
            for (String item : resultList) {
                if (item.equals(currentElement)) {
                    isDuplicate = true;
                    break;
                }
            }
            if (isDuplicate) {
                int count = 1;
                String newElement = currentElement + "_" + count;
                while (resultList.contains(newElement)) {
                    count++;
                    newElement = currentElement + "_" + count;
                }
                neLabels.set(0, newElement);
                resultList.add(newElement);
            } else {
                resultList.add(currentElement);
            }

            licenseProviderDO.setNeList(StrUtil.join(",", neLabels));
            licenseProviderDO.setActivationCode(neCodeVO.getActivationCode());
            licenseProviderDO.setOperationType(1);
            licenseProviderDO.setState(2);
            licenseProviderDO.setRemark(licenseDO.getRemark());
            licenseProviderDO.setApprover(licenseDO.getApprover());

            licenseProviderMapper.insert(licenseProviderDO);
            neCodeVO.setProviderId(licenseProviderDO.getId());
        }

        licenseDetailMapper.updateBatch(licenseDetails);

        licenseDO.setStatus(LicenseStatusEnum.GENERATING.getCode());
        licenseMapper.updateById(licenseDO);

        try {
            // 发送邮件
            // 1. 准备参数
            Long userId = licenseDO.getApplicant();
            String templateCode = "license_approver"; // 邮件模版，记得在【邮箱管理】中配置噢
            Map<String, Object> templateParams = new HashMap<>();
            ProjectDO projectDO = projectMapper.selectById(licenseDO.getProjectId());
            CustomerDO customerDO = customerMapper.selectById(projectDO.getCustomerId());
            templateParams.put("customer", customerDO.getName());
            templateParams.put("project", projectDO.getName());
            templateParams.put("sn", licenseDO.getSerialNo());
            templateParams.put("url", "http://192.168.9.50#/license/generate?id=" + licenseDO.getId());

            // 2. 发送邮件
            mailSendApi.sendSingleMailToAdmin(new MailSendSingleToUserReqDTO()
                    .setUserId(userId).setTemplateCode(templateCode).setTemplateParams(templateParams));

        } catch (Exception e) {
            log.error("邮件发送失败：{}", e.getMessage(), e);
        }

        LogRecordContext.putVariable("license", licenseDO);
        return "";
    }

    public void genLicenseTask() {
        List<LicenseDO> licenses = licenseMapper.selectList(Wrappers.<LicenseDO>lambdaQuery().eq(LicenseDO::getStatus, LicenseStatusEnum.GENERATING.getCode()));
        for (LicenseDO licenseDO : licenses) {
            List<LicenseDetailDO> licenseDetails = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()));

            for (LicenseDetailDO detail : licenseDetails) {
                if (StrUtil.isNotBlank(detail.getFileUrl()) && StrUtil.isNotBlank(detail.getFileUrlLegacy())) {
                    continue;
                }
                LicenseProviderDO licenseProviderDO = licenseProviderMapper.selectById(detail.getProviderId());
                if (licenseProviderDO == null || licenseProviderDO.getState() != 3) {
                    continue;
                }

                String fileName = getFileName(licenseDO.getSerialNo(), detail.getNeList());

                List<String> fileUrls = new ArrayList<>();
                String newFilePath1 = licenseProviderDO.getNewFilePath1();
                if (StrUtil.isNotBlank(newFilePath1)) {
                    byte[] fileContent = null;
                    try {
                        log.info("下载License文件路径为：{}", newFilePath1);
                        fileContent = FileUtil.readBytes(newFilePath1);
                        fileName = FileUtil.getName(newFilePath1);
                    } catch (Exception e) {
                        log.error("读取文件失败", e);
                    }
                    if (fileContent == null) {
                        log.error("读取文件失败为空");
//                        fileContent = ResourceUtil.readBytes("file/MME_13750602_2024-08-02_system.ini");
                    } else {
                        // 上传到文件服务
//                        String preFileName = "45G_";
//                        if (newFilePath1.contains("Legacy_")) {
//                            preFileName = "Legacy_";
//                        }
                        String fileURL = fileApi.createFile(fileContent, fileName);
                        fileUrls.add(fileURL);
                    }

                }

                String newFilePath0 = licenseProviderDO.getNewFilePath0();
                if (StrUtil.isNotBlank(newFilePath0)) {
                    byte[] fileContent0 = null;
                    try {
                        log.info("下载Legacy_License文件路径为：{}", newFilePath0);
                        fileContent0 = FileUtil.readBytes(newFilePath0);
                        fileName = FileUtil.getName(newFilePath0);
                    } catch (Exception e) {
                        log.error("读取文件失败", e);
                    }
                    if (fileContent0 == null) {
                        log.error("读取文件失败为空");
//                        fileContent0 = ResourceUtil.readBytes("file/MME_13750602_2024-08-02_system.ini");
                    } else {
                        // 上传到文件服务
//                        String preFileName = "45G_";
//                        if (newFilePath0.contains("Legacy_")) {
//                            preFileName = "Legacy_";
//                        }
                        String fileURL = fileApi.createFile(fileContent0, fileName);
                        fileUrls.add(fileURL);
                    }

                }

                if (CollUtil.isEmpty(fileUrls)) {
                    byte[] fileContent = ResourceUtil.readBytes("file/MME_13750602_2024-08-02_system.ini");
                    String fileURL = fileApi.createFile(fileContent, fileName);
                    fileUrls.add(fileURL);
                }

                if (CollUtil.isNotEmpty(fileUrls)) {
                    detail.setFileUrl(fileUrls.get(0));
                }
                if (CollUtil.isNotEmpty(fileUrls) && fileUrls.size() > 1) {
                    detail.setFileUrlLegacy(fileUrls.get(1));
                }
                licenseDetailMapper.updateById(detail);
            }

            boolean isCompleted = licenseDetails.stream().allMatch(c -> StrUtil.isNotBlank(c.getFileUrl()));

            if (isCompleted && CollUtil.isNotEmpty(licenseDetails)) {

                licenseDO.setStatus(LicenseStatusEnum.COMPLETED.getCode());
                licenseDO.setFileUrl(licenseDO.getSerialNo() + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ".tar.gz");
                licenseMapper.updateById(licenseDO);
            }

        }

    }

    private static String getFileName(String serialNo, List<Integer> neList) {
        List<String> neLabels = new ArrayList<>();
        for (Integer ne : neList) {
            String label = DictFrameworkUtils.parseDictDataLabel("lic_ne_all", ne.toString());
            if (StrUtil.isBlank(label)) {
                label = DictFrameworkUtils.parseDictDataLabel("lic_ne_5g", ne.toString());
                if (StrUtil.isBlank(label)) {
                    label = DictFrameworkUtils.parseDictDataLabel("lic_ne_4g", ne.toString());
                    if (StrUtil.isBlank(label)) {
                        label = DictFrameworkUtils.parseDictDataLabel("lic_ne_23g", ne.toString());
                        if (StrUtil.isBlank(label)) {
                            label = DictFrameworkUtils.parseDictDataLabel("lic_ne_add", ne.toString());
                        }
                    }
                }
            }
            neLabels.add(label);
        }
        String neListStr = StrUtil.join("_", neLabels);
        if (StrUtil.isNotBlank(neListStr)) {
            neListStr = neListStr + "_";
        }
        return neListStr + serialNo + "_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_system.ini";
    }

    @Override
    @LogRecord(type = SYSTEM_LICENSE_TYPE, subType = SYSTEM_LICENSE_DELETE_SUB_TYPE, bizNo = "{{#id}}",
            success = SYSTEM_LICENSE_DELETE_SUCCESS)
    public void deleteLicense(Long id) {
        // 校验存在
        LicenseDO license = validateLicenseExists(id);
        // 删除
        licenseMapper.deleteById(id);

        licenseDetailMapper.delete(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, id));

        List<LicenseHistoryDO> licenseHistoryDOS = licenseHistoryMapper.selectList(Wrappers.<LicenseHistoryDO>lambdaQuery().eq(LicenseHistoryDO::getLicenseId, id));
        for (LicenseHistoryDO licenseHistoryDO : licenseHistoryDOS) {
            licenseDetailHistoryMapper.delete(Wrappers.<LicenseDetailHistoryDO>lambdaQuery().eq(LicenseDetailHistoryDO::getLicenseId, licenseHistoryDO.getId()));
        }
        licenseHistoryMapper.delete(Wrappers.<LicenseHistoryDO>lambdaQuery().eq(LicenseHistoryDO::getLicenseId, id));

        LogRecordContext.putVariable("license", license);
    }

    private LicenseDO validateLicenseExists(Long id) {
        LicenseDO licenseDO = licenseMapper.selectById(id);
        if (licenseDO == null) {
            throw exception(LICENSE_NOT_EXISTS);
        }
        return licenseDO;
    }

    @Override
    public LicenseRespVO getLicense(Long id) {
        LicenseDO licenseDO = licenseMapper.selectById(id);
        ProjectDO projectDO = projectMapper.selectById(licenseDO.getProjectId());
        LicenseRespVO licenseRespVO = BeanUtils.toBean(licenseDO, LicenseRespVO.class);
        if (projectDO != null) {
            licenseRespVO.setCustomerId(projectDO.getCustomerId());
        }
        fillLicenseRespVO(licenseRespVO);
        return licenseRespVO;
    }

    private void fillLicenseRespVO(LicenseRespVO license) {
        List<LicenseDetailDO> licenseDetailDOS = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, license.getId()));
        List<LicenseDetailVO> details = BeanUtils.toBean(licenseDetailDOS, LicenseDetailVO.class);
        fillDetail(details, license);
        List<LicenseHistoryDO> historyList = licenseHistoryMapper.selectList(Wrappers.<LicenseHistoryDO>lambdaQuery()
                .eq(LicenseHistoryDO::getLicenseId, license.getId())
                .orderByDesc(LicenseHistoryDO::getApplicationTime));
        Optional<LicenseHistoryDO> histroyOptional = historyList.stream().findFirst();
        license.setHasHistory(LicenseStatusEnum.COMPLETED.getCode().equals(license.getStatus()) || histroyOptional.isPresent());
        int applyCount = 1;
        if (histroyOptional.isPresent()) {
            applyCount = applyCount + historyList.size();
        }
        license.setApplyCount(applyCount);
        if (LicenseStatusEnum.REAPPLYING.getCode().equals(license.getStatus())) {
            if (histroyOptional.isPresent()) {
                LicenseHistoryDO historyDO = histroyOptional.get();
                LicenseRespVO oldLicense = BeanUtils.toBean(historyDO, LicenseRespVO.class);

                List<LicenseDetailHistoryDO> oldDetailDOS = licenseDetailHistoryMapper.selectList(Wrappers.<LicenseDetailHistoryDO>lambdaQuery().eq(LicenseDetailHistoryDO::getLicenseId, oldLicense.getId()));
                List<LicenseDetailVO> oldDetails = BeanUtils.toBean(oldDetailDOS, LicenseDetailVO.class);
                fillDetail(oldDetails, oldLicense);

                license.setOldLicense(oldLicense);

                List<LicenseDetailVO> mergeDetails = fillMergeDetails(oldDetails, details, false);
                license.setNeCodeList(mergeDetails);
            }
        }

    }

    private static @NotNull List<LicenseDetailVO> fillMergeDetails(List<LicenseDetailVO> oldDetails, List<LicenseDetailVO> details, boolean isHistory) {
        int maxLength = oldDetails.size();
        if (oldDetails.size() < details.size()) {
            maxLength = details.size();
        }

        List<LicenseDetailVO> mergeDetails = new ArrayList<>();
        for (int i = 0; i < maxLength; i++) {
            Map<String, String> activationCodeMap = new HashMap<>();
            Map<String, List<Integer>> neListMap = new HashMap<>();
            Map<String, List<String>> fileUrlListMap = new HashMap<>();

            LicenseDetailVO mergeDetail = new LicenseDetailVO();
            if (i < oldDetails.size()) {
                activationCodeMap.put("old", oldDetails.get(i).getActivationCode());
                neListMap.put("old", oldDetails.get(i).getNeList());
                fileUrlListMap.put("old", null);
            }

            if (i < details.size()) {
                activationCodeMap.put("new", details.get(i).getActivationCode());
                neListMap.put("new", details.get(i).getNeList());
                if (isHistory) {
                    fileUrlListMap.put("old", details.get(i).getFileUrlList());
                } else {
                    fileUrlListMap.put("new", null);
                }
                mergeDetail.setFileUrl(details.get(i).getFileUrl());
                mergeDetail.setNeList(details.get(i).getNeList());
                mergeDetail.setActivationCode(details.get(i).getActivationCode());
                mergeDetail.setFileUrlList(details.get(i).getFileUrlList());
            }
            mergeDetail.setActivationCodeMap(activationCodeMap);
            mergeDetail.setNeListMap(neListMap);
            mergeDetail.setFileUrlListMap(fileUrlListMap);
            mergeDetails.add(mergeDetail);
        }
        return mergeDetails;
    }

    private void fillDetail(List<LicenseDetailVO> details, LicenseRespVO licenseRespVO) {
        for (LicenseDetailVO detail : details) {
            List<String> fileUrlList = new ArrayList<>();
            if (StrUtil.isNotBlank(detail.getFileUrl())) {
                fileUrlList.add(detail.getFileUrl());
            }
            if (StrUtil.isNotBlank(detail.getFileUrlLegacy())) {
                fileUrlList.add(detail.getFileUrlLegacy());
            }
            detail.setFileUrlList(fileUrlList);

            Map<String, String> activationCodeMap = new HashMap<>();
            activationCodeMap.put("old", detail.getActivationCode());
            activationCodeMap.put("new", detail.getActivationCode());
            detail.setActivationCodeMap(activationCodeMap);

            Map<String, List<Integer>> neListMap = new HashMap<>();
            neListMap.put("old", detail.getNeList());
            neListMap.put("new", detail.getNeList());
            detail.setNeListMap(neListMap);

            Map<String, List<String>> fileUrlListMap = new HashMap<>();
            fileUrlListMap.put("old", detail.getFileUrlList());
            detail.setFileUrlListMap(fileUrlListMap);
        }
        licenseRespVO.setNeCodeList(details);
    }

    @Override
    public PageResult<LicensePageRespVO> getLicensePage(LicensePageReqVO pageReqVO) {
        if (StrUtil.isNotBlank(pageReqVO.getSortField())) {
            pageReqVO.setSortField(StrUtil.toUnderlineCase(pageReqVO.getSortField()));
        }
        IPage<LicenseRespVO> page = licenseMapper.queryPage(new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);

        PageResult<LicensePageRespVO> voPageResult = BeanUtils.toBean(new PageResult<>(page.getRecords(), page.getTotal()), LicensePageRespVO.class);
//        for (LicenseRespVO licenseRespVO : voPageResult.getList()) {
//            fillLicenseRespVO(licenseRespVO);
//        }
        return voPageResult;
    }

    @Override
    public List<LicenseRespVO> getLicenseByExpiryDate() {
        return licenseMapper.selectListByExpiryDate();
    }


    @Override
    public Boolean validateLicenseSnUnique(String sn, Long id) {
        if (StrUtil.isBlank(sn)) {
            return true;
        }
        LicenseDO license = licenseMapper.selectBySn(sn);
        if (license == null) {
            return true;
        }
        // 如果 id 为空，说明不用比较是否为相同 id 的License
        if (id == null) {
            return false;
        }
        if (!license.getId().equals(id)) {
            return false;
        }
        return true;
    }

    @Override
    public List<LicenseRespVO> getLicenseHistory(Long id) {
        LicenseDO licenseDO = licenseMapper.selectById(id);
        List<LicenseRespVO> allLicenses = new ArrayList<>();
        if (LicenseStatusEnum.COMPLETED.getCode().equals(licenseDO.getStatus())) {
            LicenseRespVO license = BeanUtils.toBean(licenseDO, LicenseRespVO.class);
            ProjectDO projectDO = projectMapper.selectById(licenseDO.getProjectId());
            if (projectDO != null) {
                license.setCustomerId(projectDO.getCustomerId());
            }
            List<LicenseDetailDO> licenseDetailDOS = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, license.getId()));
            List<LicenseDetailVO> details = BeanUtils.toBean(licenseDetailDOS, LicenseDetailVO.class);
            fillDetail(details, license);
            allLicenses.add(license);
        }
        List<LicenseHistoryDO> historyDOList = licenseHistoryMapper.selectList(Wrappers.<LicenseHistoryDO>lambdaQuery()
                .eq(LicenseHistoryDO::getLicenseId, id).orderByDesc(LicenseHistoryDO::getApplicationTime));
        List<LicenseRespVO> voList = BeanUtils.toBean(historyDOList, LicenseRespVO.class);
        for (LicenseRespVO licenseRespVO : voList) {
            ProjectDO projectDO = projectMapper.selectById(licenseRespVO.getProjectId());
            if (projectDO != null) {
                licenseRespVO.setCustomerId(projectDO.getCustomerId());
            }
            fillLicenseHistoryRespVO(licenseRespVO);
        }
        allLicenses.addAll(voList);
        for (int i = 0; i < allLicenses.size(); i++) {
            if (i + 1 >= allLicenses.size()) {
                continue;
            }
            allLicenses.get(i).setOldLicense(allLicenses.get(i + 1));
            List<LicenseDetailVO> mergeDetails = fillMergeDetails(allLicenses.get(i).getOldLicense().getNeCodeList(), allLicenses.get(i).getNeCodeList(), true);
            allLicenses.get(i).setNeCodeList(mergeDetails);
        }
        return allLicenses;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ImportRespVO importList(List<LicenseImportExcelVO> list, Boolean updateSupport) {
        if (CollUtil.isEmpty(list)) {
            throw exception(LICENSE_IMPORT_LIST_IS_EMPTY);
        }

//        list = list.stream().filter(c -> StrUtil.isNotBlank(c.getSerialNo())).collect(Collectors.toList());
//        for (LicenseImportExcelVO importExcelVO : list) {
//            if (StrUtil.isBlank(importExcelVO.getProjectName())) {
//                importExcelVO.setProjectName(importExcelVO.getCustomerName() + "-" + importExcelVO.getSerialNo());
//            }
//        }

        // 根据sn分组
        ImportRespVO respVO = ImportRespVO.builder().creates(new ArrayList<>())
                .updates(new ArrayList<>()).failures(new LinkedHashMap<>()).build();
//        Map<String, List<LicenseImportExcelVO>> map = list.stream().collect(Collectors.groupingBy(LicenseImportExcelVO::getSerialNo));
//
//        List<LicenseImportExcelVO> imports = new ArrayList<>();
//        for (Map.Entry<String, List<LicenseImportExcelVO>> entry : map.entrySet()) {
//            String serialNo = entry.getKey();
//            List<LicenseImportExcelVO> importList = entry.getValue();
//
//            if (importList.size() > 1) {
//                importList.sort(Comparator.comparing(LicenseImportExcelVO::getApplicationTime).reversed());
//                imports.add(importList.get(0));
//                for (int i = 1; i < importList.size(); i++) {
//                    respVO.getFailures().put(serialNo, "SN重复，以最新的为准");
//                }
//            } else {
//                imports.addAll(importList);
//            }
//        }
        for (LicenseImportExcelVO importVO : list) {
            if (StrUtil.isBlank(importVO.getProjectName())) {
                importVO.setProjectName(importVO.getCustomerName() + "-" + importVO.getSerialNo());
            }
            String serialNo = importVO.getSerialNo();
            if (StrUtil.isBlank(serialNo)) {
                respVO.getFailures().put(importVO.getCustomerName(), "SN不能为空");
                continue;
            }
            if (StrUtil.isBlank(importVO.getCustomerName())) {
                respVO.getFailures().put(serialNo, "客户名称不能为空");
                continue;
            }
            importVO.setCustomerName(importVO.getCustomerName().trim());
            importVO.setProjectName(importVO.getProjectName().trim());
            LocalDateTime createTime = getCreateTime(importVO);
            CustomerDO customerDO = customerMapper.selectOne(Wrappers.<CustomerDO>lambdaQuery().eq(CustomerDO::getName, importVO.getCustomerName()), false);
            if (customerDO == null) {
                Integer maxCustomerCode = customerMapper.selectOldMaxCode();
                customerDO = new CustomerDO();
                customerDO.setName(importVO.getCustomerName());
                customerDO.setCode(maxCustomerCode == null ? "1000" : maxCustomerCode + 1 + "");
                customerDO.setDataType(1);
                customerDO.setCreateTime(createTime);
                customerMapper.insert(customerDO);
            } else if (updateSupport) {
                customerDO.setCreateTime(createTime);
                customerMapper.updateById(customerDO);
            }
            Long customerId = customerDO.getId();

            ProjectDO projectDO = projectMapper.getBySnAndProjectAndCustomer(null, importVO.getProjectName(), importVO.getCustomerName());
            Long projectId = null;

            if (projectDO == null) {
                Integer maxProjectCode = projectMapper.selectOldMaxCode();
                projectDO = BeanUtils.toBean(importVO, ProjectDO.class);
                projectDO.setCustomerId(customerId);
                projectDO.setName(importVO.getProjectName());
                projectDO.setCode(maxProjectCode == null ? "1000" : maxProjectCode + 1 + "");
                projectDO.setBusinessOwner(customerMapper.getUserByName(importVO.getBusinessOwnerName()));
                projectDO.setTechnicalOwnerA(customerMapper.getUserByName(importVO.getTechnicalOwnerAName()));
                projectDO.setTechnicalOwnerB(customerMapper.getUserByName(importVO.getTechnicalOwnerBName()));
                projectDO.setDataType(1);
                projectDO.setCreateTime(createTime);
                projectDO.setStartTime(createTime);
                projectMapper.insert(projectDO);
                projectId = projectDO.getId();
            } else if (updateSupport) {
                projectId = projectDO.getId();
                projectDO = BeanUtils.toBean(importVO, ProjectDO.class);
                projectDO.setId(projectId);
                projectDO.setCustomerId(customerId);
                projectDO.setBusinessOwner(customerMapper.getUserByName(importVO.getBusinessOwnerName()));
                projectDO.setTechnicalOwnerA(customerMapper.getUserByName(importVO.getTechnicalOwnerAName()));
                projectDO.setTechnicalOwnerB(customerMapper.getUserByName(importVO.getTechnicalOwnerBName()));
                projectDO.setCreateTime(createTime);
                projectDO.setStartTime(createTime);
                projectMapper.updateById(projectDO);
            } else {
                projectId = projectDO.getId();
            }

            LicenseDO licenseDO = new LicenseDO();
            licenseDO.setProjectId(projectId);
            licenseDO.setSerialNo(serialNo);
            licenseDO.setStatus(LicenseStatusEnum.COMPLETED.getCode());
//            licenseDO.setApplicant(WebFrameworkUtils.getLoginUserId());
            String expiryDateExt = importVO.getExpiryDateExt();
            LocalDateTime expiryDate;
            if (StrUtil.isNotBlank(expiryDateExt)) {
                if ("永久".equals(expiryDateExt)) {
                    expiryDate = LocalDateTime.of(2099, 12, 31, 23, 59, 59);
                } else {
                    expiryDate = LocalDateTime.of(LocalDate.parse(expiryDateExt, DateTimeFormatter.ofPattern("yyyy/M/d")), LocalTime.of(23, 59, 59));
                }
                licenseDO.setExpiryDate(expiryDate);
            }

            licenseDO.setApplicationTime(createTime);
//            licenseDO.setUserNumber(importVO.getUserNumber());
//            licenseDO.setRanNumber(importVO.getRanNumber());
//            licenseDO.setApprover(161L);

            String neListStr = importVO.getNeListStr();
            List<Integer> neList = getNeList(neListStr);
            if (CollUtil.isEmpty(neList)) {
                respVO.getFailures().put(serialNo, "网元不能为空");
                continue;
            }

            LicenseDO license = licenseMapper.getBySnAndProjectAndCustomer(serialNo, importVO.getProjectName(), importVO.getCustomerName());
            if (license == null) {
                licenseDO.setDataType(1);
                licenseMapper.insert(licenseDO);
                LicenseDetailDO licenseDetailDO = new LicenseDetailDO();
                licenseDetailDO.setLicenseId(licenseDO.getId());
                licenseDetailDO.setNeList(neList);
                licenseDetailMapper.insert(licenseDetailDO);
                respVO.getCreates().add(serialNo);
                continue;
            }
            if (!updateSupport) {
                respVO.getFailures().put(serialNo, "已存在相同的客户、项目和SN");
                continue;
            }

            licenseDO.setId(license.getId());
            licenseMapper.updateById(licenseDO);

            licenseDetailMapper.delete(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()));
            LicenseDetailDO licenseDetailDO = new LicenseDetailDO();
            licenseDetailDO.setLicenseId(licenseDO.getId());
            licenseDetailDO.setNeList(neList);
            licenseDetailMapper.insert(licenseDetailDO);


            List<LicenseHistoryDO> licenseHistoryDOS = licenseHistoryMapper.selectList(Wrappers.<LicenseHistoryDO>lambdaQuery().eq(LicenseHistoryDO::getLicenseId, licenseDO.getId()));
            for (LicenseHistoryDO licenseHistoryDO : licenseHistoryDOS) {
                licenseDetailHistoryMapper.delete(Wrappers.<LicenseDetailHistoryDO>lambdaQuery().eq(LicenseDetailHistoryDO::getLicenseId, licenseHistoryDO.getId()));
            }
            licenseHistoryMapper.delete(Wrappers.<LicenseHistoryDO>lambdaQuery().eq(LicenseHistoryDO::getLicenseId, licenseDO.getId()));
            respVO.getUpdates().add(serialNo);
        }

        Map<String, String> failures = respVO.getFailures();
        Map<String, String> newMap = failures.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getValue,
                        Map.Entry::getKey,
                        (existing, replacement) -> existing + "、" + replacement)); // 使用第一个遇到的key作为结果
        respVO.setFailureMap(newMap);
        respVO.setTotal(list.size());
        return respVO;
    }

    @Override
    public ImportRespVO importCodeList(List<LicenseCodeImportExcelVO> list, Boolean updateSupport) {

        ImportRespVO respVO = ImportRespVO.builder().creates(new ArrayList<>())
                .updates(new ArrayList<>()).failures(new LinkedHashMap<>()).build();
//        list = list.stream().filter(c -> StrUtil.isNotBlank(c.getSerialNo())).collect(Collectors.toList());

        String lastSn = "";
        String lastCustomer = "";
        for (LicenseCodeImportExcelVO importVO : list) {
            if (StrUtil.isBlank(importVO.getSerialNo())) {
                importVO.setSerialNo(lastSn);
            }
            if (StrUtil.isBlank(importVO.getCustomerName())) {
                importVO.setCustomerName(lastCustomer);
            }
            lastSn = importVO.getSerialNo();
            lastCustomer = importVO.getCustomerName();
        }
        for (LicenseCodeImportExcelVO importExcelVO : list) {
            String serialNo = importExcelVO.getSerialNo().trim();
            if (StrUtil.isBlank(importExcelVO.getCustomerName())) {
                continue;
            }
            String customerName = importExcelVO.getCustomerName().trim();
            String regex = "\\d{8}";

            if (!serialNo.matches(regex) && customerName.matches(regex)) {
                importExcelVO.setSerialNo(customerName);
            }

        }

        Map<String, List<LicenseCodeImportExcelVO>> map = list.stream().collect(Collectors.groupingBy(LicenseCodeImportExcelVO::getSerialNo));

        List<LicenseCodeImportExcelVO> newImportList = new ArrayList<>();
        for (Map.Entry<String, List<LicenseCodeImportExcelVO>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<LicenseCodeImportExcelVO> value = entry.getValue();

            List<String> codeList = new ArrayList<>();
            for (LicenseCodeImportExcelVO importVO : value) {
                if (StrUtil.isBlank(importVO.getActivationCode())) {
                    respVO.getFailures().put(key, "没有找到激活码");
                    continue;
                }
                String activationCode = importVO.getActivationCode();
                if (activationCode.contains(":")) {
                    activationCode = activationCode.substring(activationCode.indexOf(":") + 1);
                }
                if (activationCode.matches("^[A-Z0-9]{20,}$")) {
                    codeList.add(activationCode);
                }

            }

            if (CollUtil.isEmpty(codeList)) {
                respVO.getFailures().put(key, "没有找到激活码");
                continue;
            }
            if (CollUtil.isNotEmpty(codeList) && codeList.size() > 1) {
                respVO.getFailures().put(key, "激活码有多个");
                continue;
            }
            LicenseCodeImportExcelVO newImportVO = new LicenseCodeImportExcelVO();
            newImportVO.setSerialNo(key);
            newImportVO.setActivationCode(codeList.get(0));
            newImportList.add(newImportVO);
        }

        for (LicenseCodeImportExcelVO newImportVO : newImportList) {
            List<LicenseDO> licenseDOS = licenseMapper.selectList(Wrappers.<LicenseDO>lambdaQuery()
                    .eq(LicenseDO::getSerialNo, newImportVO.getSerialNo()).eq(LicenseDO::getDataType, 1));
            Optional<LicenseDO> first = licenseDOS.stream().findFirst();
            if (!first.isPresent()) {
                respVO.getFailures().put(newImportVO.getSerialNo(), "没有找到该SN");
                continue;
            }
            LicenseDO licenseDO = first.get();
            LicenseDetailDO licenseDetailDO = licenseDetailMapper.selectOne(Wrappers.<LicenseDetailDO>lambdaQuery().eq(LicenseDetailDO::getLicenseId, licenseDO.getId()), false);
            if (licenseDetailDO == null) {
                respVO.getFailures().put(newImportVO.getSerialNo(), "没有找到网元");
                continue;
            }
            if (!updateSupport && StrUtil.isNotBlank(licenseDetailDO.getActivationCode())) {
                respVO.getFailures().put(newImportVO.getSerialNo(), "激活码已存在");
                continue;
            }
            licenseDetailDO.setActivationCode(newImportVO.getActivationCode());
//            licenseDetailMapper.updateById(licenseDetailDO);
            if (StrUtil.isNotBlank(licenseDetailDO.getActivationCode())) {
                respVO.getCreates().add(newImportVO.getSerialNo());
            }
        }

        return respVO;
    }

    private static LocalDateTime getCreateTime(LicenseImportExcelVO importVO) {
        LocalDateTime createTime = LocalDateTime.now();
        try {
            createTime = LocalDateTime.of(importVO.getApplicationTime(), LocalTime.of(0, 0, 0));
        } catch (Exception e) {
            log.error("导入excel时间错误:{}", e.getMessage());
        }
        return createTime;
    }

    private static List<Integer> getNeList(String neListStr) {

        List<Integer> neList = new ArrayList<>();

        try {
            List<String> neLabels = StrUtil.split(neListStr, "+");
            for (String ne : neLabels) {

                if ("5GC".equals(ne)) {
                    List<String> licNe5gStr = DictFrameworkUtils.getDictDataValueList("lic_ne_5g");
                    List<Integer> licNe5g = licNe5gStr.stream().map(Integer::parseInt).toList();
                    neList.addAll(licNe5g);
                    continue;
                }
                if ("4GC".equals(ne)) {
                    List<String> licNe5gStr = DictFrameworkUtils.getDictDataValueList("lic_ne_4g");
                    List<Integer> licNe5g = licNe5gStr.stream().map(Integer::parseInt).toList();
                    neList.addAll(licNe5g);
                    continue;
                }

                String value = DictFrameworkUtils.parseDictDataValue("lic_ne_all", ne);
                if (StrUtil.isBlank(value)) {
                    value = DictFrameworkUtils.parseDictDataValue("lic_ne_5g", ne);
                    if (StrUtil.isBlank(value)) {
                        value = DictFrameworkUtils.parseDictDataValue("lic_ne_4g", ne);
                        if (StrUtil.isBlank(value)) {
                            value = DictFrameworkUtils.parseDictDataValue("lic_ne_23g", ne);
                            if (StrUtil.isBlank(value)) {
                                value = DictFrameworkUtils.parseDictDataValue("lic_ne_add", ne);
                            }
                        }
                    }
                }
                if (StrUtil.isNotBlank(value)) {
                    neList.add(Integer.parseInt(value));
                }

            }
        } catch (NumberFormatException e) {
            log.error("导入网元转换失败{}", e.getMessage());
        }
        return neList;
    }

    private void fillLicenseHistoryRespVO(LicenseRespVO license) {
        List<LicenseDetailHistoryDO> licenseDetailDOS = licenseDetailHistoryMapper.selectList(Wrappers.<LicenseDetailHistoryDO>lambdaQuery().eq(LicenseDetailHistoryDO::getLicenseId, license.getId()));
        List<LicenseDetailVO> details = BeanUtils.toBean(licenseDetailDOS, LicenseDetailVO.class);
        fillDetail(details, license);

    }

    public void updateDetailById(LicenseDetailVO licenseDetail) {
        LicenseDetailDO licenseDetailDO = licenseDetailMapper.selectById(licenseDetail.getId());
        if (StrUtil.isBlank(licenseDetailDO.getFileUrl())) {
            licenseDetailDO.setFileUrl(licenseDetail.getFileUrl());
        } else {
            licenseDetailDO.setFileUrlLegacy(licenseDetail.getFileUrl());
        }
        licenseDetailMapper.updateById(licenseDetailDO);
    }

    public void download(HttpServletResponse response, Long id) {
        try {
            List<LicenseDetailDO> detailList = licenseDetailMapper.selectList(Wrappers.<LicenseDetailDO>lambdaQuery()
                    .eq(LicenseDetailDO::getLicenseId, id));

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Archiver archiver = CompressUtil.createArchiver(CharsetUtil.CHARSET_UTF_8, "tar.gz", outputStream);

            for (LicenseDetailDO detail : detailList) {
                addArchiverFile(archiver, detail.getFileUrl());
                addArchiverFile(archiver, detail.getFileUrlLegacy());
            }
            archiver.finish().close();
            FileTypeUtils.writeAttachment(response, "temp.tar.gz", outputStream.toByteArray());
        } catch (IOException e) {
            throw exception(LICENSE_DOWNLOAD_FAILED);
        }
    }

    private void addArchiverFile(Archiver archiver, String fileUrl) {
        String tempFilePath = "/opt/agt/temp/";
        if (StrUtil.isNotBlank(fileUrl)) {
            String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1, fileUrl.lastIndexOf("_")) + ".ini";
            CommonResult<byte[]> result = fileApi.getFileContent(fileUrl);
            byte[] fileContent = result.getData();
            archiver.add(FileUtil.writeBytes(fileContent, tempFilePath + fileName));
            FileUtil.del(tempFilePath + fileName);
        }
    }

}