package com.dsk.cscec.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsk.common.excel.ExcelResult;
import com.dsk.common.utils.poi.ExcelUtil;
import com.dsk.cscec.constant.CbProjectConstants;
import com.dsk.cscec.domain.*;
import com.dsk.cscec.domain.bo.CbProjectBaseBo;
import com.dsk.cscec.domain.bo.CbProjectOtherBo;
import com.dsk.cscec.domain.vo.CbProjectExpenseSummaryImportVo;
import com.dsk.cscec.domain.vo.CbProjectOtherImportVo;
import com.dsk.cscec.domain.vo.CbProjectOtherVo;
import com.dsk.cscec.listener.CbProjectExpenseSummaryImportListener;
import com.dsk.cscec.listener.CbProjectOtherImportListener;
import com.dsk.cscec.mapper.CbProjectFileMapper;
import com.dsk.cscec.mapper.CbProjectOtherMapper;
import com.dsk.cscec.service.*;
import com.dsk.system.service.ISysOssService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@Service
public class CbProjectOtherServiceImpl extends ServiceImpl<CbProjectOtherMapper, CbProjectOther> implements CbProjectOtherService {


    private final String firstPattern = "[\\(（]*[一|二|三|四|五|六|七|八|九|十]+[\\)）]*";
    private final Pattern secondPattern = Pattern.compile("^\\d+(\\.\\d+)*$");
    private final Pattern pattern3 = Pattern.compile("^([1-9][0-9]*|0)$");

    @Resource
    private CbProjectRecordService cbProjectRecordService;
    @Resource
    private CbProjectFileService projectFileService;
    @Resource
    private ISysOssService ossService;
    @Resource
    private CbProjectExpenseSummaryService projectExpenseSummaryService;
    @Resource
    private CbProjectFileMapper projectFileMapper;

    @SneakyThrows
    @Override
    public void importExcelData(MultipartFile file, Long projectId) {
        String name = file.getOriginalFilename();
        name = FileNameUtil.getPrefix(name);

        CbProjectRecord byId = cbProjectRecordService.getById(projectId);
        Assert.notNull(byId, "项目信息不能为空");
        Integer cbStage = byId.getCbStage();
        CbProjectOtherImportListener importListener = new CbProjectOtherImportListener(projectId, 0L);
        EasyExcel.read(file.getInputStream(), CbProjectOtherImportVo.class, importListener).sheet().doRead();
        ExcelResult<CbProjectOtherImportVo> result = importListener.getExcelResult();
        String analysis = result.getAnalysis();
        List<CbProjectOtherImportVo> list = result.getList();
        if (CollectionUtil.isEmpty(list)) {
            //解析失败
            log.debug(">>>>解析失败" + list.size());
            //todo 解析失败更新文件备注

            return;
        }
        log.debug(">>>>" + list.size());
        CbProjectOther rootProjectOther = new CbProjectOther();
        rootProjectOther.setItemContent(name);
        rootProjectOther.setParentId(0L);
        rootProjectOther.setProjectId(projectId);
        rootProjectOther.setCbStage(cbStage);
        rootProjectOther.setCbProjectFileId(0L);

        LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(rootProjectOther);
        CbProjectOther rootOther = this.getOne(tWrapper);
        if (ObjectUtil.isEmpty(rootOther)) {
            this.save(rootProjectOther);
            rootProjectOther.setDealWithNumber(String.valueOf(rootProjectOther.getId()));
            this.updateById(rootProjectOther);
        }

        Long rootMeasuresId = rootProjectOther.getId();
        if (CollectionUtil.isNotEmpty(list)) {
            for (CbProjectOtherImportVo importVo : list) {
                String number = importVo.getNumber();

                CbProjectOther cbProjectOther = new CbProjectOther();
                //保存一级节点
                if (ReUtil.isMatch(firstPattern, number) || ReUtil.isMatch(pattern3, number)) {
                    BeanUtil.copyProperties(importVo, cbProjectOther);
                    cbProjectOther.setParentId(rootMeasuresId);
//                    cbProjectOther.setLevel(1);

                } else if (ReUtil.isMatch(secondPattern, number)) {
                    BeanUtil.copyProperties(importVo, cbProjectOther);
                    // 根据no查询父级节点
                    CbProjectOther parentCbCostMeasure = getCbProjectOther(rootMeasuresId, number, projectId, cbStage);
                    String[] split = number.split("\\.");
//                    cbProjectOther.setLevel(split.length);
                    cbProjectOther.setParentId(parentCbCostMeasure.getId());
                }
                String newNo = String.valueOf(rootMeasuresId).concat(".").concat(cbProjectOther.getDealWithNumber());
                cbProjectOther.setDealWithNumber(newNo);
                cbProjectOther.setProjectId(projectId);
                cbProjectOther.setCbStage(cbStage);
                this.save(cbProjectOther);
            }
        }

    }

    @Override
    public List<Map<String, Object>> listByLevel(Long projectId, int i) {
        CbProjectRecord byId = cbProjectRecordService.getById(projectId);
        Assert.notNull(byId, "项目信息不能为空");
        CbProjectOther projectOther = new CbProjectOther();
        projectOther.setParentId(0L);
        projectOther.setLevel(i);
        projectOther.setProjectId(projectId);
        projectOther.setCbStage(byId.getCbStage());
        QueryWrapper<CbProjectOther> tWrapper = Wrappers.query(projectOther);
        tWrapper.select("id","item_content as itemContent");
        tWrapper.orderByAsc("id");
        List<Map<String, Object>> mapList = this.listMaps(tWrapper);
        return mapList;
    }

    @Override
    public List<CbProjectOtherVo> selectDataList(CbProjectOtherBo projectOtherBo) {
        List<CbProjectOtherVo> dataList = new ArrayList<>();
        Assert.notNull(projectOtherBo.getProjectId(), "项目ID不能为空");
        CbProjectRecord byId = cbProjectRecordService.getById(projectOtherBo.getProjectId());
        Assert.notNull(byId, "项目信息不能为空");
        projectOtherBo.setCbStage(byId.getCbStage());
        dataList = baseMapper.selectListByProjectAndStage(projectOtherBo);
        return dataList;
    }

    /***
     *@Description: 其他费用数据解析
     *@Param:
     *@return: void
     *@Author: Dgm
     *@date: 2024/2/23 18:03
     */
    @Async
    @Override
    public void projectOtherDataAnalysis(CbProjectBaseBo baseBo) throws Exception {
        // 项目Id
        Long projectId = baseBo.getProjectId();
        // 成本阶段(0：标前成本 1：标后成本 2：转固成本)
        Integer cbStage = baseBo.getCbStage();
        Assert.notNull(projectId, "项目信息不能为空");
        // 查询其他费用导入文件
        List<CbProjectFile> projectFileList = projectFileMapper.selectAnalysisList(projectId, CbProjectConstants.CB_TYPE_OTHER_PROJECT, cbStage);
        if (ObjectUtils.isEmpty(projectFileList)) {
            return;
        }
        //文件处理
        for (CbProjectFile file : projectFileList) {
            if (file.getDelFlag() == 0) {
                //文件下载
                InputStream inputStream = ossService.downFileIO(file.getFileOssId());
                if (ObjectUtil.isNull(inputStream)) {
                    file.setFileParseStatus(3);
                    file.setFailRemark("文件数据不存在");
                    projectFileService.updateById(file);
                    continue;
                }

                // 文件名称
                String fileName = file.getFileName();
                fileName = FileNameUtil.getPrefix(fileName);
                // 文件Id
                Long fileId = file.getId();
                if ("其他费".equals(fileName)) {
                    totalDataAnalysis(inputStream, fileName, file, projectId, cbStage);
                    continue;
                }
                //解析数据
                ExcelResult<CbProjectOtherImportVo> importVoExcelResult =
                        ExcelUtil.importExcel(inputStream, CbProjectOtherImportVo.class,new CbProjectOtherImportListener(projectId, fileId));
                List<CbProjectOtherImportVo> importVoList = importVoExcelResult.getList();
                if (CollectionUtil.isEmpty(importVoList)) {
                    //解析失败
                    log.debug(">>>>解析失败" + importVoList.size());
                    file.setFileParseStatus(3);
                    file.setFailRemark("表格中不存在待导入数据!");
                    projectFileService.updateById(file);
                    continue;
                }
                log.debug(">>>>" + importVoList.size());
                CbProjectOther rootProjectOther = new CbProjectOther();
                rootProjectOther.setItemContent(fileName);
                rootProjectOther.setParentId(0L);
                rootProjectOther.setProjectId(projectId);
                rootProjectOther.setLevel(0);
                rootProjectOther.setCbStage(cbStage);
                rootProjectOther.setCbProjectFileId(fileId);

                LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(rootProjectOther);
                CbProjectOther rootOther = this.getOne(tWrapper);
                if (ObjectUtil.isEmpty(rootOther)) {
                    this.save(rootProjectOther);
                    rootProjectOther.setDealWithNumber(String.valueOf(rootProjectOther.getId()));
                    this.updateById(rootProjectOther);
                }

                Long rootMeasuresId = rootProjectOther.getId();
                if (CollectionUtil.isNotEmpty(importVoList)) {
                    for (CbProjectOtherImportVo importVo : importVoList) {
                        String number = importVo.getNumber();
                        CbProjectOther cbProjectOther = new CbProjectOther();
                        BeanUtil.copyProperties(importVo, cbProjectOther);
                        if (ObjectUtil.isEmpty(number)) {
                            cbProjectOther.setParentId(rootMeasuresId);
                            cbProjectOther.setLevel(1);
                        } else {
                            //保存一级节点
                            if (ReUtil.isMatch(firstPattern, number) || ReUtil.isMatch(pattern3, number)) {
                                cbProjectOther.setParentId(rootMeasuresId);
                                cbProjectOther.setLevel(1);
                            } else if (ReUtil.isMatch(secondPattern, number)) {
                                // 根据no查询父级节点
                                CbProjectOther parentCbCostMeasure = getCbProjectOther(rootMeasuresId, number, projectId, cbStage);
                                String[] split = number.split("\\.");
                                cbProjectOther.setLevel(split.length);
                                cbProjectOther.setParentId(parentCbCostMeasure.getId());
                            }
                        }
                        if (ObjectUtil.isNotEmpty(cbProjectOther.getDealWithNumber())) {
                            String newNo = String.valueOf(rootMeasuresId).concat(".").concat(cbProjectOther.getDealWithNumber());
                            cbProjectOther.setDealWithNumber(newNo);
                        }
                        cbProjectOther.setProjectId(projectId);
                        cbProjectOther.setCbStage(cbStage);
                        this.save(cbProjectOther);
                    }
                }

            }
            file.setFileParseStatus(2);
            projectFileService.updateById(file);
        }
    }

    /***
     *@Description: 解析其他费用总和
     *@Param:
     *@return: void
     *@Author: Dgm
     *@date: 2024/2/23 18:03
     */
    public void totalDataAnalysis(InputStream inputStream, String name, CbProjectFile file, Long projectId, Integer cbStage) throws Exception {
        //解析数据
        ExcelResult<CbProjectExpenseSummaryImportVo> importVoExcelResult =
                ExcelUtil.importExcel(inputStream, CbProjectExpenseSummaryImportVo.class,new CbProjectExpenseSummaryImportListener(projectId, cbStage));
        List<CbProjectExpenseSummaryImportVo> importVoList = importVoExcelResult.getList();
        if (CollectionUtil.isEmpty(importVoList)) {
            //解析失败
            log.debug(">>>>解析失败" + importVoList.size());
            file.setFileParseStatus(3);
            file.setFailRemark("表格中不存在待导入数据!");
            projectFileService.updateById(file);
        }
        log.debug(">>>>" + importVoList.size());
        if (CollectionUtil.isNotEmpty(importVoList)) {
            for (CbProjectExpenseSummaryImportVo importVo : importVoList) {
                CbProjectExpenseSummary projectExpenseSummary = new CbProjectExpenseSummary();
                BeanUtil.copyProperties(importVo, projectExpenseSummary);
                projectExpenseSummary.setProjectId(projectId);
                projectExpenseSummary.setCbStage(cbStage);
                projectExpenseSummary.setDataType(3);
                projectExpenseSummaryService.save(projectExpenseSummary);
            }
        }
        file.setFileParseStatus(2);
        projectFileService.updateById(file);
    }

    /**
     * 根据当前序号、项目id、成本阶段查询父级信息
     *
     * @param number
     * @param projectId
     * @param cbStage
     * @return
     */
    public CbProjectOther getCbProjectOther(Long rootMeasuresId, String number, Long projectId, Integer cbStage) {
        String parentNo = number.substring(0, number.lastIndexOf('.'));
        parentNo = String.valueOf(rootMeasuresId).concat(".").concat(parentNo);
        CbProjectOther projectOther = new CbProjectOther();
        projectOther.setDealWithNumber(parentNo);
        projectOther.setProjectId(projectId);
        projectOther.setCbStage(cbStage);
        LambdaQueryWrapper<CbProjectOther> tWrapper = Wrappers.lambdaQuery(projectOther);
        CbProjectOther other = this.getOne(tWrapper);
        return other;
    }

}
