package com.bonus.material.device.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.PhoneUtil;
import com.bonus.common.biz.constant.MaterialConstants;
import com.bonus.common.biz.domain.*;
import com.bonus.common.biz.enums.HttpCodeEnum;
import com.bonus.common.biz.enums.MaStatusEnum;
import com.bonus.material.utils.CacheHelper;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.DateUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.bean.BeanUtils;
import com.bonus.common.core.utils.bean.BeanValidators;
import com.bonus.common.core.utils.poi.ExcelUtil;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.book.domain.BookCarInfoDto;
import com.bonus.material.devchange.domain.MapBean;
import com.bonus.material.device.domain.DevInfo;
import com.bonus.material.device.domain.MaDevQc;
import com.bonus.material.device.domain.Table;
import com.bonus.material.device.domain.dto.DevInfoImpDto;
import com.bonus.material.device.domain.dto.InfoMotionDto;
import com.bonus.material.device.domain.vo.*;
import com.bonus.material.device.mapper.BmFileInfoMapper;
import com.bonus.material.device.mapper.DevInfoMapper;
import com.bonus.material.device.mapper.MaDevQcMapper;
import com.bonus.material.device.service.DevInfoService;
import com.bonus.material.device.service.MaDevQcService;
import com.bonus.system.api.model.LoginUser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Validator;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.stream.Collectors;

import static com.bonus.common.biz.enums.MaStatusEnum.*;

/**
 * 设备信息Service业务层处理
 *
 * @author syruan
 */
@Service
@Slf4j
public class DevInfoServiceImpl implements DevInfoService {
    // 装备主展示图片字典
    private final Integer MAIN_IMAGES_DICT_VALUE = 0;

    // 装备详情展示图片字典
    private final Integer DETAILS_IMAGES_DICT_VALUE = 1;

    // 检测证明PDF附件字典
    private final Integer EXAMINATION_PDF = 2;

    // 合格证PDF附件字典
    private final Integer INSURANCE_PDF = 3;

    @Resource
    private DevInfoMapper devInfoMapper;

    @Resource
    private BmFileInfoMapper bmFileInfoMapper;

    @Resource
    private MaDevQcService maDevQcService;

    @Resource
    protected Validator validator;

    @Resource
    private MaDevQcMapper maDevQcMapper;

    @Autowired
    private CacheHelper cacheHelper;

    /**
     * 查询设备信息
     *
     * @param maId 设备信息主键
     * @return 设备信息
     */
    @Override
    public DevInfoVo selectDevInfoByMaId(Long maId, Boolean isHome) {
        DevInfoVo devInfoVo = devInfoMapper.selectDevInfoByMaId(maId);
        //判断该装备是否已经被该企业或个人加入预约车，不能重复加入
        Long userId = SecurityUtils.getLoginUser().getUserid();
        if (devInfoVo != null) {
            //更新搜索量
            try {
                //只针对于首页上架状态装备更新浏览量（去除后台查看浏览量更新）
                if (isHome != null && isHome && devInfoVo.getMaStatus().equals(MaStatusEnum.LISTING.getCode())) {
                    updateHotSearch(maId);
                }
            } catch (Exception e) {
                System.err.println("更新设备搜索量失败,不影响主业务流程");
            }
            BmFileInfo bmFileInfo = new BmFileInfo().setModelId(devInfoVo.getMaId()).setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
            List<BmFileInfo> fileList = bmFileInfoMapper.selectBmFileInfoList(bmFileInfo);
            ArrayList<Table> tableList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(fileList)) {
                fileList.removeIf(Objects::isNull);
                fileList.forEach(item -> {
                    if (item.getFileType().equals(Long.valueOf(MAIN_IMAGES_DICT_VALUE))) {
                        devInfoVo.getMainFileList().add(item);
                    } else if (item.getFileType().equals(Long.valueOf(DETAILS_IMAGES_DICT_VALUE))) {
                        devInfoVo.getDetailsFileList().add(item);
                    } /*else if (item.getFileType().equals(Long.valueOf(EXAMINATION_PDF))) {
                        devInfoVo.getExaminationPdf().add(item);
                    }*/ else if (item.getFileType().equals(Long.valueOf(INSURANCE_PDF))) {
                        String result = "";
                        if (StringUtils.isNotBlank(item.getFileName())) {
                            result = extracted(item.getFileName());
                        }
                        item.setFileName("合格证" + result);
                        devInfoVo.getInsurancePdf().add(item);
                    }

                });
            }
            Table table = new Table();
            table.setExaminationPdf(devInfoVo.getExaminationPdf());
            table.setInsurancePdf(devInfoVo.getInsurancePdf());
            table.setIdentifyCode(devInfoVo.getIdentifyCode());
            MaDevQc qc = maDevQcMapper.getQcListByOne(maId);
            if (Objects.nonNull(qc)) {
                table.setCheckMan(qc.getQcUser());
                table.setId(qc.getId());
                table.setCheckDate(qc.getQcTime());
                table.setNextCheckDate(qc.getNextCheckTime());
                List<BmFileInfo> info = bmFileInfoMapper.getInfoByMaIdAndTaskId(qc);
                for (BmFileInfo fileInfo : info) {
                    String result = "";
                    if (StringUtils.isNotBlank(fileInfo.getFileName())) {
                        result = extracted(fileInfo.getFileName());
                    }
                    fileInfo.setFileName("检测证明" + result);
                }
                devInfoVo.getExaminationPdf().addAll(info);
            }
            tableList.add(table);
            devInfoVo.setTableList(tableList);
            bmFileInfo.setFileType(0L);
            List<BmFileInfo> mainFileInfoList = bmFileInfoMapper.selectBmFileInfoList(bmFileInfo);
            if (!CollectionUtils.isEmpty(mainFileInfoList)) {
                devInfoVo.setPicUrl(mainFileInfoList.get(0).getFileUrl());
            }
            //根据设备id查询所属公司上架装备数以及公司访问量
            if (StringUtils.isNotBlank(devInfoVo.getCompanyId())) {
                int devNum = devInfoMapper.selectCompany(devInfoVo.getCompanyId());
                int companyVisitNum = devInfoMapper.getCompanyUpNum(devInfoVo.getCompanyId());
                DevInfoVo infoVo = devInfoMapper.selectCompanyById(devInfoVo.getCompanyId());
                devInfoVo.setCompanyVisitNum(companyVisitNum);
                devInfoVo.setCompanyCreateTime(devInfoVo.getCreateTime());
                devInfoVo.setDevUapNum(devNum);
            }
            //根据设备id及用户id去预约表中查询是否已经加入预约车
            BookCarInfoDto bookCarInfoDto = devInfoMapper.getBookCar(maId, userId);
            if (bookCarInfoDto != null) {
                devInfoVo.setIsBookCar(0);
            } else {
                devInfoVo.setIsBookCar(1);
            }
            //查询该设备的出租记录
            List<LeaseVo> leaseList = devInfoMapper.getLeaseList(maId);
            if (!CollectionUtils.isEmpty(leaseList)) {
                devInfoVo.setLeaseList(leaseList);
            }
            //查询自定义属性
            List<DevInfoPropertyVo> properties = devInfoMapper.selectDevInfoProperties(maId);
            devInfoVo.setDevInfoProperties(properties);

            //查询质检记录
            List<MaDevQc> qcList = maDevQcMapper.getQcList(maId);
            for (MaDevQc maDevQc : qcList) {
                BmFileInfo fileInfo = new BmFileInfo();
                fileInfo.setTaskId(Long.valueOf(maDevQc.getId()));
                fileInfo.setModelId(Long.valueOf(maDevQc.getMaId()));
                fileInfo.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                fileInfo.setFileType(4L);
                List<BmFileInfo> bmFileInfos = bmFileInfoMapper.selectBmFileInfo(fileInfo);
                maDevQc.setFileInfoList(bmFileInfos);
            }
            devInfoVo.setQcList(qcList);
        }
        return devInfoVo;
    }

    /**
     * 根据文件名截取文件名
     *
     * @param fileName
     */
    private String extracted(String fileName) {
        String result = "";
        // 找到最后一个下划线的索引位置
        int underscoreIndex = fileName.lastIndexOf("_");
        // 找到点号的索引位置
        int dotIndex = fileName.lastIndexOf(".");
        if (underscoreIndex != -1 && dotIndex != -1) {
            // 从下划线的下一个位置开始截取到点号的位置
            result = fileName.substring(underscoreIndex + 1, dotIndex);
        }
        return result;
    }

    /**
     * 更新设备搜索量
     *
     * @param maId
     */
    private void updateHotSearch(Long maId) {
        int count = devInfoMapper.getHotSearchCountByMaId(maId);
        if (count == 0) {
            devInfoMapper.insertHotSearch(maId);
        } else {
            devInfoMapper.updateHotSearchByMaId(maId);
        }
    }

    /**
     * 查询装备共享大厅列表
     *
     * @param devInfo 设备信息
     * @return 设备信息
     */
    @Override
    public List<DevInfoVo> selectDevInfoList(DevInfoVo devInfo) {
        List<DevInfoVo> voList = devInfoMapper.selectDevInfoList(devInfo);
        // 增加缓存处理
        cacheHelper.putList("devListCache",
                "user:" + SecurityUtils.getLoginUser().getSysUser().getUserId(), voList, Duration.ofMinutes(5L));
        return voList;
    }

    @Override
    public Map<String, Long> getCompanyCount(DevInfoVo devInfo) {
        // 先从缓存获取
        List<DevInfoVo> voList = cacheHelper.getList("devListCache", "user:" + SecurityUtils.getLoginUser().getSysUser().getUserId(), DevInfoVo.class);
        if (CollectionUtils.isEmpty(voList)) {
            System.out.println("缓存无此数据！");
            // 缓存内没有此数据再执行Mapper查询
            voList = devInfoMapper.selectDevInfoList(devInfo);
        } else {
            System.out.println("缓存已生效！");
        }
        Map<String, Long> map = voList.stream().collect(Collectors.groupingBy(DevInfoVo::getCompanyId, Collectors.counting()));
        return map;
    }


    @Override
    public List<DevInfoVo> selectZoneDevInfoList(DevInfoVo devInfo) {
        if (Objects.isNull(devInfo)) {
            devInfo = new DevInfoVo();
        }
        System.out.println("当前登录用户dept信息：" + SecurityUtils.getLoginUser().getSysUser().getDeptId());
        devInfo.setIsZone(true);
        devInfo.setZoneId(Math.toIntExact(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
        List<DevInfoVo> voList = devInfoMapper.selectDevInfoList(devInfo);
        extractedFile(voList);
        return voList;
    }


    /**
     * 查询设备收藏列表
     *
     * @param devInfo 设备信息
     * @return 设备信息
     */
    @Override
    public List<DevInfoVo> selectUserCollectList(DevInfoVo devInfo) {
        List<DevInfoVo> result = devInfoMapper.selectDevInfoList(devInfo);
        LoginUser user = SecurityUtils.getLoginUser();
        if (Objects.nonNull(user)) {
            List<UserCollect> userCollectList = devInfoMapper.selectUserCollectByUserId(user.getUserid());
            result = filterUserCollect(result, userCollectList);
        }
        fillInMaStatusStr(result);
        fillInCityStr(result);
        return result;
    }

    private List<DevInfoVo> filterUserCollect(List<DevInfoVo> list, List<UserCollect> userCollectList) {
        List<DevInfoVo> result = new ArrayList<>();
        for (DevInfoVo devInfoVo : list) {
            for (UserCollect userCollect : userCollectList) {
                if (devInfoVo.getMaId().longValue() == userCollect.getMaId().longValue()) {
                    result.add(devInfoVo);
                }
            }
        }
        return result;
    }


    @Override
    public AjaxResult selectDevInfoHotList(DevInfoVo devInfo) {
        List<DevNameVo> voList = new ArrayList<>();
        List<DevInfoVo> hotList = devInfoMapper.selectDevInfoHotList(devInfo);
        if (CollectionUtil.isEmpty(hotList)) {

            return AjaxResult.success(Collections.emptyMap());
        }
        extractedFile(hotList);
        for (DevInfoVo devInfoVo : hotList) {
            if (devInfoVo.getDeviceCount() <= 0) {
                // 下架
                devInfoVo.setMaStatus(1);
                devInfoMapper.upMaStatus(devInfoVo);
            }
        }
        List<DevInfoVo> collect = hotList.stream().filter(t -> t.getMaStatus() != 1).collect(Collectors.toList());
        // 按照一级设备类型进行分组
        Map<String, List<DevInfoVo>> groupedByFirstName = collect.stream()
                .filter(info -> info.getFirstName() != null)
                .collect(Collectors.groupingBy(DevInfoVo::getFirstName));
        // 遍历 Map 中的每个条目，将数据转化成 DevNameVo 对象
        for (Map.Entry<String, List<DevInfoVo>> entry : groupedByFirstName.entrySet()) {
            String typeName = entry.getKey();
            List<DevInfoVo> devInfoList = entry.getValue();
            // 创建一个 DevNameVo 对象并设置相应的字段
            DevNameVo devNameVo = new DevNameVo();
            devNameVo.setTypeName(typeName);
            devNameVo.setDevInfoList(devInfoList);
            // 将 DevNameVo 对象添加到 voList 中
            voList.add(devNameVo);
        }
        return AjaxResult.success(voList);
    }

    /**
     * 提取主图文件地址，方便用于列表页面回显
     *
     * @param hotList
     */
    private void extractedFile(List<DevInfoVo> hotList) {
        if (CollectionUtil.isNotEmpty(hotList)) {
            for (DevInfoVo devInfoVo : hotList) {
                BmFileInfo bmFileInfo = new BmFileInfo();
                bmFileInfo.setModelId(devInfoVo.getMaId());
                bmFileInfo.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                bmFileInfo.setFileType(0L);
                List<BmFileInfo> mainFileInfoList = bmFileInfoMapper.selectBmFileInfoList(bmFileInfo);
                if (!CollectionUtils.isEmpty(mainFileInfoList)) {
                    devInfoVo.setPicUrl(mainFileInfoList.get(0).getFileUrl());
                }
            }
        }
    }

    private void fillInMaStatusStr(List<DevInfoVo> list) {
        List<SysDic> sysDicList = devInfoMapper.getSysDic();
        for (DevInfoVo devInfoVo : list) {
            for (SysDic sysDic : sysDicList) {
                if (devInfoVo.getMaStatus().equals(sysDic.getId())) {
                    devInfoVo.setMaStatusName(sysDic.getName());
                }
            }
        }
    }

    private void fillInCityStr(List<DevInfoVo> list) {
        List<BaseAddress> addressList = devInfoMapper.getBaseAddress();
        for (DevInfoVo devInfoVo : list) {
            for (BaseAddress address : addressList) {
                if (devInfoVo.getCityId() == null || address.getCode() == null) {
                    continue;
                }
                if (devInfoVo.getCityId().equals(Integer.valueOf(address.getCode()))) {
                    devInfoVo.setCityStr(address.getName());
                    break;
                }
            }
        }
    }

    /**
     * 新增设备信息
     *
     * @param devInfo 设备信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult insertDevInfo(DevInfo devInfo) {
        if (devInfo == null) {
            return AjaxResult.error("设备信息不能为空");
        }
       /* if (!"2".equals(devInfo.getType())) {
            if (ObjectUtil.isEmpty(devInfo.getMainFileList())) {
                return AjaxResult.error("主展示图不能为空");
            }
            if (ObjectUtil.isEmpty(devInfo.getDetailsFileList())) {
                return AjaxResult.error("详情页展示图不能为空");
            }
        }*/
        String code = "";
       /* for (int i = 0; i < devInfo.getTableList().size(); i++) {*/
            //获取用户信息
            Long userId = SecurityUtils.getLoginUser().getUserid();
            //保存用户信息
            devInfo.setCreator(userId)
                    /*.setMaStatus(ON_HIRE.getCode())*/
                    .setOwnId(userId);
            if (org.apache.commons.lang3.StringUtils.isBlank(code)) {
                code = getString();
            }
            devInfo.setCode(code);
            //devInfo.setCompanyId(SecurityUtils.getLoginUser().getSysUser().getCompanyId().toString());
            devInfo.setDeviceCount(devInfo.getDeviceCount());
            //devInfo.setIdentifyCode(devInfo.getTableList().get(i).getIdentifyCode());
            //0914 添加字段
            devInfo.setChangeStatus("1");
            devInfo.setUpDownStatus("0");
            int num = devInfoMapper.insertDevInfo(devInfo);
            if (num == 0) {
                return AjaxResult.error("设备信息SQL保存失败，请修改后重试");
            }
            //devInfoMapper.updateTypeLeasePrice(devInfo);
            code = "";
            //保存自定义属性值
            /*if (!CollectionUtils.isEmpty(devInfo.getDevInfoProperties())) {
                devInfoMapper.insertDevInfoProperties(devInfo.getMaId(), devInfo.getDevInfoProperties());
            }*/
            //把文件保存到附件中
           /* Table table = devInfo.getTableList().get(i);
            AjaxResult error = uploadFiles(table, devInfo, userId, i);
            if (error != null) {
                return error;
            }*/
        /*}*/
        return AjaxResult.success("保存成功");
    }

    /**
     * 物资设备文件处理并上传
     *
     * @param devInfo 设备附件对象
     * @param userId  用户ID
     * @return 无异常返回null ，报错返回AjaxResult
     */
    private AjaxResult uploadFiles(Table table, DevInfo devInfo, Long userId, Integer i) {
        if (userId == null) {
            return AjaxResult.error("用户信息获取失败，请刷新后重试");
        }
        if (devInfo.getMaId() == null) {
            return AjaxResult.error("设备ID为空,请携带设备信息上传附件");
        }

        //把文件保存到附件中
        List<BmFileInfo> fileInfoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(devInfo.getMainFileList())) {
            devInfo.getMainFileList().removeIf(Objects::isNull);
            devInfo.getMainFileList().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(MAIN_IMAGES_DICT_VALUE));
            });
            fileInfoList.addAll(devInfo.getMainFileList());
        }
        if (CollectionUtil.isNotEmpty(devInfo.getDetailsFileList())) {
            devInfo.getDetailsFileList().removeIf(Objects::isNull);
            devInfo.getDetailsFileList().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(DETAILS_IMAGES_DICT_VALUE));
            });
            fileInfoList.addAll(devInfo.getDetailsFileList());
        }

        // 合格证
        if (CollectionUtil.isNotEmpty(devInfo.getTableList().get(i).getInsurancePdf())) {
            devInfo.getTableList().get(i).getInsurancePdf().removeIf(Objects::isNull);
            devInfo.getTableList().get(i).getInsurancePdf().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(INSURANCE_PDF));
            });
            fileInfoList.addAll(devInfo.getTableList().get(i).getInsurancePdf());
        }

        if (CollectionUtil.isNotEmpty(devInfo.getTableList().get(i).getExaminationPdf())) {
            devInfo.getTableList().get(i).getExaminationPdf().removeIf(Objects::isNull);
            devInfo.getTableList().get(i).getExaminationPdf().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(EXAMINATION_PDF));
            });
            fileInfoList.addAll(devInfo.getTableList().get(i).getExaminationPdf());

            List<BmFileInfo> examinationPdf = devInfo.getTableList().get(i).getExaminationPdf();
            ArrayList<BmFileInfo> copiedList = examinationPdf.stream()
                    .map(BmFileInfo::clone)
                    .collect(Collectors.toCollection(ArrayList::new));
            // 新增检测证明
            MaDevQc maDevQc = new MaDevQc();
            maDevQc.setMaId(devInfo.getMaId().intValue());
            maDevQc.setFileInfoList(copiedList);
            maDevQc.setNextCheckTime(table.getNextCheckDate());
            maDevQc.setQcUser(table.getCheckMan());
            maDevQc.setQcTime(table.getCheckDate());
            maDevQcService.addDev(maDevQc);
        }

        // 上传处理后的附件列表
        if (CollectionUtil.isNotEmpty(fileInfoList)) {
            System.out.println("设备附件数量:" + fileInfoList.size());
            for (BmFileInfo sysFileInfo : fileInfoList) {
                sysFileInfo.setModelId(devInfo.getMaId());
                sysFileInfo.setCreateBy(String.valueOf(userId));
            }
            int fileUploadTotal = bmFileInfoMapper.insertBmFileInfos(fileInfoList);
            if (fileUploadTotal == 0) {
                return AjaxResult.error("设备附件保存0条，保存失败，请修改后重试");
            }
        }
        return null;
    }

    private AjaxResult uploadFile(Table table, DevInfo devInfo, Long userId) {
        if (userId == null) {
            return AjaxResult.error("用户信息获取失败，请刷新后重试");
        }
        if (devInfo.getMaId() == null) {
            return AjaxResult.error("设备ID为空,请携带设备信息上传附件");
        }

        //把文件保存到附件中
        List<BmFileInfo> fileInfoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(devInfo.getMainFileList())) {
            devInfo.getMainFileList().removeIf(Objects::isNull);
            devInfo.getMainFileList().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(MAIN_IMAGES_DICT_VALUE));
            });
            fileInfoList.addAll(devInfo.getMainFileList());
        }
        if (CollectionUtil.isNotEmpty(devInfo.getDetailsFileList())) {
            devInfo.getDetailsFileList().removeIf(Objects::isNull);
            devInfo.getDetailsFileList().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(DETAILS_IMAGES_DICT_VALUE));
            });
            fileInfoList.addAll(devInfo.getDetailsFileList());
        }
        // 修改人：syruan
        // 修改时间：2025/02/20
        // 描述：经沟通，田聪聪提出需求，检测证明与合格证合二为一
        if (CollectionUtil.isNotEmpty(table.getInsurancePdf())) {
            table.getInsurancePdf().removeIf(Objects::isNull);
            table.getInsurancePdf().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(INSURANCE_PDF));
            });
            fileInfoList.addAll(table.getInsurancePdf());
        }
        if (CollectionUtil.isNotEmpty(table.getExaminationPdf())) {
            table.getExaminationPdf().removeIf(Objects::isNull);
            table.getExaminationPdf().forEach(item -> {
                item.setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE);
                item.setFileType(Long.valueOf(EXAMINATION_PDF));
            });
            fileInfoList.addAll(table.getExaminationPdf());
        }

        // 上传处理后的附件列表
        if (CollectionUtil.isNotEmpty(fileInfoList)) {
            System.out.println("设备附件数量:" + fileInfoList.size());
            for (BmFileInfo sysFileInfo : fileInfoList) {
                sysFileInfo.setModelId(devInfo.getMaId());
                sysFileInfo.setCreateBy(String.valueOf(userId));
            }
            int fileUploadTotal = bmFileInfoMapper.insertBmFileInfos(fileInfoList);
            if (fileUploadTotal == 0) {
                return AjaxResult.error("设备附件保存0条，保存失败，请修改后重试");
            }
        }
        return null;
    }


    /**
     * 修改设备信息
     *
     * @param devInfo 设备信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateDevInfo(DevInfo devInfo) {
        if (devInfo.getMaId() == null) {
            return AjaxResult.error("设备ID为空,请携带设备信息修改");
        }
        /*DevInfo deviceId = devInfoMapper.getDeviceNameCount(devInfo.getDeviceName());
        if (deviceId != null && !deviceId.getMaId().equals(devInfo.getMaId())) {
            return AjaxResult.error("设备名称已存在，请修改后重试！");
        }*/
        devInfoMapper.deleteDevInfoProperties(devInfo.getMaId());
        if (!CollectionUtils.isEmpty(devInfo.getDevInfoProperties())) {
            devInfoMapper.insertDevInfoProperties(devInfo.getMaId(), devInfo.getDevInfoProperties());
        }
        List<Table> tableList = devInfo.getTableList();
        String identifyCode = tableList.get(0).getIdentifyCode();
        devInfo.setIdentifyCode(identifyCode);
        int i = devInfoMapper.updateDevInfo(devInfo);

        if (i > 0) {
            BmFileInfo bmFileInfo = new BmFileInfo()
                    .setTaskType(MaterialConstants.MATERIAL_FILE_TYPE_CODE)
                    .setModelId(devInfo.getMaId());
            bmFileInfoMapper.deleteBmFileInfoByBizInfo(bmFileInfo);
        }

        Integer id = tableList.get(0).getId();
        if (id != null) {
            MaDevQc maDevQc = new MaDevQc();
            maDevQc.setId(id).setQcUser(tableList.get(0).getCheckMan()).setQcTime(tableList.get(0).getCheckDate()).setNextCheckTime(tableList.get(0).getNextCheckDate());
            maDevQcMapper.updateById(maDevQc);
            Long userId = SecurityUtils.getLoginUser().getUserid();
            Table table = tableList.get(0);
            uploadFile(table, devInfo, userId);
        } else {
            Long userId = SecurityUtils.getLoginUser().getUserid();
            //把文件保存到附件中
            Table table = devInfo.getTableList().get(0);
            AjaxResult error = uploadFiles(table, devInfo, userId, 0);
            if (error != null) {
                return error;
            }
        }
       /* if (i > 0) {
            Long userId = SecurityUtils.getLoginUser().getUserid();
            Table table = tableList.get(0);
            uploadFile(table, devInfo, userId);
        }*/
        return i > 0 ? AjaxResult.success("修改成功") : AjaxResult.error("修改失败");
    }

    /**
     * 批量删除设备信息
     *
     * @param maIds 需要删除的设备信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteDevInfoByMaIds(Long[] maIds) {
        devInfoMapper.batchDeleteDevInfoProperties(maIds);
        return devInfoMapper.deleteDevInfoByMaIds(maIds);
    }

    /**
     * 删除设备信息信息
     *
     * @param maId 设备信息主键
     * @return 结果
     */
    @Override
    public int deleteDevInfoByMaId(Long maId) {
        return devInfoMapper.deleteDevInfoByMaId(maId, MaStatusEnum.UNDER_RENT.getCode());
    }

    /**
     * 信息录入
     *
     * @param infoMotionDto 设备信息
     */
    @Override
    public int insertInfoMotionDto(InfoMotionDto infoMotionDto) {
        DevInfo devInfo = new DevInfo();
        BeanUtils.copyProperties(infoMotionDto, devInfo);
        devInfoMapper.insertDevInfo(devInfo);
        return devInfoMapper.insertLon(infoMotionDto);
    }


    /**
     * 统计装备
     */
    @Override
    public Map<String, Integer> sumType() {
        DevInfoVo devInfoVo = new DevInfoVo();
        Map<String, Integer> sumTypeMap = new IdentityHashMap<>();
        //获取所有的装备信息
        List<DevInfoVo> devInfoList = devInfoMapper.selectDevInfoList(devInfoVo);
        //获取每种状态列表
        Map<Integer, List<DevInfo>> groupedByMaStatus = devInfoList.stream()
                .collect(Collectors.groupingBy(DevInfo::getMaStatus));
        //获取所有的key
        Set<Integer> keys = groupedByMaStatus.keySet();
        //根据key计算每种状态的数量
        for (Integer key : keys) {
            List<DevInfo> deviceList = groupedByMaStatus.get(key);
            sumTypeMap.put(MaStatusEnum.getNameByCode(key), deviceList.size());
        }
        return sumTypeMap;
    }

    /**
     * 查询设备信息列表
     * 该方法根据传入的DevInfoVo对象中的属性值，查询符合条件的设备信息列表
     * 主要用于设备信息的批量查询筛选
     *
     * @param devInfo 包含查询条件的DevInfoVo对象，用于指定查询的设备信息条件
     * @return 返回一个DevInfoVo对象列表，包含所有符合条件的设备信息
     */
    @Override
    public List<DevInfoVo> selectDevInfoLists(DevInfoVo devInfo) {
        devInfo.setCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()).toString());
        List<DevInfoVo> list = devInfoMapper.selectDevInfoLists(devInfo);
        if (!CollectionUtils.isEmpty(list)) {
            for (DevInfoVo infoVo : list) {
                if (infoVo.getMaId() != null) {
                    MaDevQc qc = maDevQcMapper.getQcListByOne(infoVo.getMaId());
                    if (qc != null) {
                        infoVo.setNextCheckDate(qc.getNextCheckTime());
                    }
                }
            }
        }
        return list;
    }

    /**
     * 查询公司列表
     */
    @Override
    public List<BmCompanyInfo> selectCompanyList(BmCompanyInfo obj) {
        List<BmCompanyInfo> companyInfos = devInfoMapper.selectCompanyList(obj);
        List<BmCompanyInfo> companyMaCountList = devInfoMapper.getMaCountByCompany(obj);
        if (!CollectionUtils.isEmpty(companyInfos) && !CollectionUtils.isEmpty(companyMaCountList)) {
            for (BmCompanyInfo bmInfo : companyInfos) {
                for (BmCompanyInfo maCountList : companyMaCountList) {
                    if (bmInfo.getCompanyId().equals(maCountList.getCompanyId())) {
                        bmInfo.setMaCount(maCountList.getMaCount());
                    }
                }
            }
        }
        return companyInfos;
    }

    /**
     * 更新设备的上下架状态
     *
     * @param devInfo 包含设备ID列表和新状态的设备信息对象
     * @return AjaxResult对象，操作结果或错误信息
     */
    @Override
    public AjaxResult updateUpDown(DevInfo devInfo) {
        // 检查是否提供了设备ID列表和新状态
        if (devInfo == null || CollectionUtil.isEmpty(devInfo.getMaIds())) {
            return AjaxResult.error("请选择设备");
        }
        if (devInfo.getMaStatus() == null) {
            return AjaxResult.error("请选择设备状态");
        }

        devInfo.getMaIds().removeIf(Objects::isNull);
        List<Long> maIds = devInfo.getMaIds();

        if (CollectionUtil.isNotEmpty(maIds)) {
            for (Long maId : maIds) {
                DevInfo dto = devInfoMapper.getMaStatusByMaId(maId);
                Integer newStatus = devInfo.getMaStatus();
                if (dto.getDeviceCount() == 0 && newStatus.equals(LISTING.getCode())) {
                    return AjaxResult.error("设备ID:" + maId + "库存为0，无法上架");
                }
                // 根据旧状态和新状态进行状态转换检查
                switch (dto.getMaStatus()) {
                    case 0:
                        if (newStatus.equals(TO_BE_LISTED.getCode()) || newStatus.equals(ON_HIRE.getCode())) {
                            continue;
                        }
                        return AjaxResult.error("设备ID:" + maId + "是草稿状态，只能进行保存操作:" + newStatus);
                    case 1:
                        if (newStatus.equals(LISTING.getCode()) || newStatus.equals(ON_HIRE.getCode())) {
                            continue;
                        }
                        return AjaxResult.error("设备ID:" + maId + "已下架，只能进行上下架操作!");
                    case 2:
                        if (newStatus.equals(ON_HIRE.getCode()) || newStatus.equals(LISTING.getCode())) {
                            continue;
                        }
                        return AjaxResult.error("设备ID:" + maId + "设备已上架，只能进行上下架操作!!");
                    case 3:
                        return AjaxResult.error("设备ID:" + maId + "设备已出租，非法状态修改!!");
                    default:
                        return AjaxResult.error("设备ID:" + maId + "设备状态异常，请修改后重试");
                }
            }

            try {
                devInfoMapper.updateUpDown(maIds, devInfo.getMaStatus());
            } catch (DataAccessException e) {
                throw new ServiceException("批量修改状态时SQL执行异常:" + e.getMessage());
            }
        }

        return AjaxResult.success("操作成功");
    }

    @Override
    public String importMaProp(List<DevInfoImpDto> maPropInfoList, boolean updateSupport, Long userId) {
        if (StringUtils.isNull(maPropInfoList) || maPropInfoList.size() == 0) {
            throw new ServiceException("导入的数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (DevInfoImpDto devInfo : maPropInfoList) {
            try {
                BeanValidators.validateWithException(validator, devInfo);
                devInfo.setCreator(userId);
                devInfo.setOwnId(userId);
                devInfo.setCode(getString());
                DevInfo devInfo1 = new DevInfo();
                BeanUtils.copyProperties(devInfo, devInfo1);
                devInfo1.setCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()).toString());
                devInfo1.setMaStatus(0);
                devInfoMapper.insertDevInfo(devInfo1);
                successNum++;
                successMsg.append("<br/>" + successNum + "、资产名称 " + devInfo.getDeviceName() + " 导入成功");
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、资产名称 " + devInfo.getDeviceName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public void downLoadTemplate(HttpServletResponse response) {
        String templateName = "template.xlsx";
        OutputStream out = null;
        InputStream input = null;
        try {
            input = this.getClass().getClassLoader().getResourceAsStream("template/template.xlsx");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String((templateName).getBytes(), "iso-8859-1"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            out = response.getOutputStream();
            byte[] buffer = new byte[1024]; // 缓冲区
            int bytesToRead = -1;
            // 通过循环将读入内容输出到浏览器中
            while ((bytesToRead = input.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(out);
        }
    }

    @Override
    public List<DevInfoVo> selectAssociationList(DevInfoVo devInfo) {
        devInfo.setCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()).toString());
        return devInfoMapper.selectAssociationList(devInfo);
    }

    @Override
    public List<DevInfoVo> getTagDevList(DevInfoVo devInfoVo) {
        devInfoVo.setOwnCo(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
        return devInfoMapper.getTagDevList(devInfoVo);
    }

    @Override
    public List<DevInfoVo> getDevList(DevInfoVo devInfo) {
        // 直接由SQL一次性返回 rentNum 与 maStatus，无需循环二次查询
        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        devInfo.setDeptId(deptId);
        return devInfoMapper.getDevList(devInfo);
    }

    /**
     * 在租装备信息查询
     *
     * @param devInfo
     * @return
     */
    @Override
    public List<DevInfoVo> getLeaseDevList(DevInfoVo devInfo) {
        return devInfoMapper.getLeaseDevList(devInfo);
    }

    /**
     * 设备批量导入模版下载
     *
     * @param response
     */
    @Override
    public void downLoadDev(HttpServletResponse response) {
        //模板名称
        String templateName = "MaDevTemplate.xlsx";
        OutputStream out = null;
        InputStream input = null;
        try {
            input = this.getClass().getClassLoader().getResourceAsStream("template/MaDevTemplate.xlsx");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + new String((templateName).getBytes(), "iso-8859-1"));
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            out = response.getOutputStream();
            // 缓冲区
            byte[] buffer = new byte[1024];
            int bytesToRead = -1;
            // 通过循环将读入内容输出到浏览器中
            while ((bytesToRead = input.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 设备信息导入
     *
     * @param file
     * @return
     */
    @Override
    public AjaxResult importTbPeople(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (fileName != null) {
            String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (!MaterialConstants.XLSX.equalsIgnoreCase(fileExtension)) {
                // 文件后缀名不符合要求
                return AjaxResult.error("导入失败：文件后缀名不符合要求,必须为xlsx结尾");
            }
        }
        try {
            InputStream inputStream = file.getInputStream();
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            // 得到Excel的行数
            int totalRows = sheet.getPhysicalNumberOfRows();
            // 检查是否有行数
            if (totalRows <= 1) {
                throw new IllegalArgumentException("导入失败：Excel文件中没有数据，请检查后重新导入");
            }
            // 读取第一行表头
            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                throw new IllegalArgumentException("导入失败：文件中没有表头");
            }
            // 获取表头的列数
            int totalCells = headerRow.getPhysicalNumberOfCells();
            // 预期的表头列数为11列，可以根据实际需求修改这个条件
            if (totalCells != 11) {
                throw new IllegalArgumentException("导入失败：表头列数与预期不符，请检查导入模板");
            }
            // 获取数据行数
            int rowCount = sheet.getLastRowNum() + 1;
            if (rowCount > 50) {
                throw new IllegalArgumentException("导入失败：数据总条数不能超过 50 条");
            }
            // 读取表头内容并验证每一列
            extractedText(headerRow, totalCells);
            //读取Excel表格数据，做非空及格式判断
            extractedCell(sheet, totalRows, totalCells);
            ExcelUtil<DevTemplateVo> util = new ExcelUtil<>(DevTemplateVo.class);
            List<DevTemplateVo> maDevList = util.importExcel(file.getInputStream());
            List<DevTemplateVo> templateVos = new ArrayList<>();
            // 判断装备类目是否为空，查询装备id及价格
            if (!CollectionUtils.isEmpty(maDevList)) {
                for (DevTemplateVo devTemplateVo : maDevList) {
                    if (StringUtils.isNotBlank(devTemplateVo.getTypeName())) {
                        // 根据装备类目查询装备详情
                        List<DevInfoVo> list = devInfoMapper.selectDevTypeByName(devTemplateVo.getTypeName());
                        if (!CollectionUtils.isEmpty(list)) {
                            DevInfoVo devType = list.get(0);
                            devTemplateVo.setTypeId(devType.getTypeId() != null ? devType.getTypeId() : null);
                            devTemplateVo.setTypeName(devType.getTypeName() != null ? devType.getTypeName() : null);
                            devTemplateVo.setDayLeasePrice(devType.getDayLeasePrice() != null ? devType.getDayLeasePrice() : null);
                            devTemplateVo.setUnitName(devType.getUnitName() != null ? devType.getUnitName() : null);
                            if ("0".equals(devType.getManageType())) {
                                devTemplateVo.setDeviceCount(1);
                            }
                        }
                    }
                }
                // 对maDevList通过装备名称进行分组
                Map<String, List<DevTemplateVo>> map = maDevList.stream().collect(Collectors.groupingBy(DevTemplateVo::getDeviceName));
                for (Map.Entry<String, List<DevTemplateVo>> entry : map.entrySet()) {
                    List<DevTemplateVo> dtoList = new ArrayList<>();
                    // 如果map的数量大于1，则进行遍历
                    DevTemplateVo devTemplateVo = entry.getValue().get(0);
                    List<DevTemplateVo> devTemplateVos = entry.getValue();
                    for (DevTemplateVo templateVo : devTemplateVos) {
                        if (StringUtils.isBlank(templateVo.getIdentifyCode()) && StringUtils.isBlank(templateVo.getCheckMan())
                                && templateVo.getNextCheckDate() == null && templateVo.getCheckDate() == null) {
                            continue;
                        }
                        DevTemplateVo dto = new DevTemplateVo();
                        dto.setIdentifyCode(StringUtils.isNotBlank(templateVo.getIdentifyCode()) ? templateVo.getIdentifyCode() : null);
                        dto.setCheckMan(StringUtils.isNotBlank(templateVo.getCheckMan()) ? templateVo.getCheckMan() : null);
                        dto.setCheckDate(templateVo.getCheckDate() != null ? templateVo.getCheckDate() : null);
                        dto.setNextCheckDate(templateVo.getNextCheckDate() != null ? templateVo.getNextCheckDate() : null);
                        dtoList.add(dto);
                    }
                    if (!CollectionUtils.isEmpty(dtoList)) {
                        devTemplateVo.setTableList(dtoList);
                    }
                    devTemplateVo.setUploadUser(SecurityUtils.getLoginUser().getSysUser().getUserName());
                    devTemplateVo.setUploadTime(DateUtils.dateTime());
                    templateVos.add(devTemplateVo);

                }
            }
            return AjaxResult.success(templateVos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return AjaxResult.error(HttpCodeEnum.FAIL.getCode(), HttpCodeEnum.FAIL.getMsg());
    }

    @Override
    public List<DevInfoVo> selectCheckDevInfoList(DevInfoVo devInfo) {
        List<DevInfoVo> voList = devInfoMapper.selectCheckDevInfoList(devInfo);
        extractedFile(voList);
        return voList;
    }

    @Override
    public Integer updateCheckStatus(String ids, String status) {
        String[] split = ids.split(",");
        if(split.length>0){
            List<MapBean> list = new ArrayList<>();
            for (String s : split) {
                list.add(new MapBean(s,status));
            }
            return devInfoMapper.updateCheckStatus(list);
        }else {
            return 0;
        }
    }

    /**
     * @param maId
     * @param isHome
     * @return
     */
    @Override
    public DevInfoVo selectToolByMaId(Long maId, Boolean isHome) {
        return devInfoMapper.selectToolByMaId(maId);
    }

    /**
     * 读取Excel表格数据，做非空判断
     *
     * @param sheet
     * @param totalRows
     * @param totalCells
     */
    private void extractedCell(Sheet sheet, int totalRows, int totalCells) {
        //读取Excel表格数据，做非空判断
        // 循环Excel行数
        DataFormatter dataFormatter = new DataFormatter();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        for (int r = 1; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            // 循环Excel列数
            for (int c = 0; c < totalCells; c++) {
                Cell cell = row.getCell(c);
                String cellValue = "";
                if (cell != null && cell.getCellType() == CellType.NUMERIC) {
                    if (DateUtil.isCellDateFormatted(cell)) {
                        Date date = cell.getDateCellValue();
                        cellValue = dateFormat.format(date);
                    } else {
                        cellValue = String.valueOf(cell.getNumericCellValue());
                    }
                } else if (cell != null && cell.getCellType() == CellType.STRING) {
                    cellValue = cell.getStringCellValue();
                }
                if (c == 5) {
                    cellValue = dataFormatter.formatCellValue(row.getCell(c));
                }
                switch (c) {
                    case 0:
                        checkBlank(cellValue, r, c);
                        break;
                    case 3:
                        checkDate(cellValue, r, c);
                        break;
                    case 5:
                        checkPhone(cellValue, r, c);
                        break;
                    case 6:
                        checkNumber(cellValue, r, c);
                        break;
                    case 9:
                        checkDate(cellValue, r, c);
                        break;
                    case 10:
                        checkDate(cellValue, r, c);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /**
     * 检查数字格式是否为整数
     *
     * @param cellValue
     * @param r
     * @param c
     */
    private void checkNumber(String cellValue, int r, int c) {
        if (StringUtils.isNotBlank(cellValue)) {
            try {
                Integer.parseInt(cellValue);
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException(
                        String.format("第 %d 行，第 %d 列上架数量数据格式错误，请检查后重新导入", r + 1, c + 1));
            }
        }
    }

    /**
     * 检查日期格式
     *
     * @param cellValue
     * @param rowIndex
     * @param colIndex
     */
    private void checkDate(String cellValue, int rowIndex, int colIndex) {
        if (StringUtils.isNotBlank(cellValue)) {
            boolean b = isValidDate(cellValue);
            if (!b) {
                throw new IllegalArgumentException(
                        String.format("第 %d 行，第 %d 列日期格式错误，请检查后重新导入", rowIndex + 1, colIndex + 1));
            }
        }
    }

    /**
     * 判断日期格式是否正确
     *
     * @param dateStr
     * @return
     */
    private static boolean isValidDate(String dateStr) {
        // 构建三种允许单位数月份和日期的格式化器，并设置严格解析模式
        DateTimeFormatter[] formatters = {
                new DateTimeFormatterBuilder()
                        .appendValue(ChronoField.YEAR, 4)
                        .appendLiteral('-')
                        .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .appendLiteral('-')
                        .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .toFormatter()
                        .withResolverStyle(ResolverStyle.STRICT),
                new DateTimeFormatterBuilder()
                        .appendValue(ChronoField.YEAR, 4)
                        .appendLiteral('/')
                        .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .appendLiteral('/')
                        .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .toFormatter()
                        .withResolverStyle(ResolverStyle.STRICT),
                new DateTimeFormatterBuilder()
                        .appendValue(ChronoField.YEAR, 4)
                        .appendLiteral('.')
                        .appendValue(ChronoField.MONTH_OF_YEAR, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .appendLiteral('.')
                        .appendValue(ChronoField.DAY_OF_MONTH, 1, 2, java.time.format.SignStyle.NOT_NEGATIVE)
                        .toFormatter()
                        .withResolverStyle(ResolverStyle.STRICT)
        };

        // 遍历格式化器数组，尝试解析日期
        for (DateTimeFormatter formatter : formatters) {
            try {
                LocalDate.parse(dateStr, formatter);
                return true;
            } catch (DateTimeParseException e) {
                // 若解析失败，继续尝试下一个格式化器
            }
        }
        return false;
    }

    /**
     * 检查数据是否为空
     *
     * @param cellValue
     * @param rowIndex
     * @param colIndex
     */
    private void checkBlank(String cellValue, int rowIndex, int colIndex) {
        if (StringUtils.isBlank(cellValue)) {
            throw new IllegalArgumentException(
                    String.format("第 %d 行，第 %d 列数据为空，请检查后重新导入", rowIndex + 1, colIndex + 1));
        }
    }

    /**
     * 检查电话号码格式
     *
     * @param cellValue
     * @param rowIndex
     * @param colIndex
     */
    private void checkPhone(String cellValue, int rowIndex, int colIndex) {
        if (StringUtils.isNotBlank(cellValue)) {
            if (!PhoneUtil.isMobile(cellValue)) {
                throw new IllegalArgumentException(
                        String.format("第 %d 行，第 %d 列电话号码格式不正确，请检查后重新导入", rowIndex + 1, colIndex + 1));
            }
        }
    }

    /**
     * 读取Excel表格数据，做非空及格式判断
     *
     * @param headerRow
     * @param totalCells
     */
    private void extractedText(Row headerRow, int totalCells) {
        for (int cellNum = 0; cellNum < totalCells; cellNum++) {
            Cell cell = headerRow.getCell(cellNum);
            // 获取单元格内容并去除首尾空格
            String headerValue = cell.getStringCellValue().trim();
            // 根据列索引进行验证
            switch (cellNum) {
                case 0:
                    if (!"装备名称".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 1:
                    if (!"装备类目".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 2:
                    if (!"装备品牌".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 3:
                    if (!"出厂日期（例：2025-03-17）".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 4:
                    if (!"联系人".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 5:
                    if (!"联系电话".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 6:
                    if (!"上架数量（编码类型设备默传1）".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 7:
                    if (!"唯一标识符".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 8:
                    if (!"检修人".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 9:
                    if (!"检修时间（例：2025-03-17）".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                case 10:
                    if (!"下次检测时间（例：2025-03-17）".equals(headerValue)) {
                        throw new IllegalArgumentException("第 " + (cellNum + 1) + " 列表头列名与预期不符，请检查导入模板");
                    }
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void insertOutType(String devInfo) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String, Object> map = objectMapper.readValue(devInfo, new TypeReference<Map<String, Object>>() {

            });
            //获取公司名称
            String companyName = (String) map.get("companyName");
            // TODO 根据公司名称获取公司ID
//            BmCompanyInfo bmCompanyInfo = sysFileInfoMapper.getBmCompanyInfo(companyName);
            //获取设备类型名称
            String deviceName = (String) map.get("deviceName");
            //根据设备类型名称获取设备类型ID
            TypeInfo typeInfo = bmFileInfoMapper.getTypeInfo(deviceName);
            //获取日租金
            Long leasePrice = (Long) map.get("leasePrice");
            //设备型号
            String modelName = (String) map.get("modelName");
            //出厂日期
            Date outFacTime = (Date) map.get("outFacTime");
            DevInfo devInfo1 = new DevInfo();
            devInfo1.setCreateTime(new Date());
            //获取用户信息
            Long userId = SecurityUtils.getUserId();
            //保存用户信息
            devInfo1.setCreator(userId);
            devInfo1.setOwnId(userId);
            devInfo1.setCode(String.valueOf(UUID.randomUUID()));
            devInfo1.setTypeId(typeInfo.getTypeId());
            devInfo1.setJsDayPrice(Float.valueOf(leasePrice));
            devInfo1.setModelName(modelName);
            devInfo1.setProductionDate(outFacTime);
            devInfoMapper.insertDevInfo(devInfo1);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    private String getString() {
        //根据前台传过来的数据，生成需求编号
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date nowDate = DateUtils.getNowDate();
        String format = dateFormat.format(nowDate);
        String taskNum = devInfoMapper.selectTaskNumByMonth(nowDate);
        if (StringUtils.isNotBlank(taskNum)) {
            // 将字符串转换为整数
            int num = Integer.parseInt(taskNum);
            // 执行加一操作
            num++;
            // 将结果转换回字符串格式，并确保结果是4位数，不足4位则在前面补0
            taskNum = String.format("%04d", num);
        } else {
            taskNum = "0001";
        }
        return format + "-" + taskNum;
    }
}
