package com.ruoyi.project.business.service.impl;

import static com.ruoyi.project.business.enums.account.AccountStatusEnum.CONVERTED_PROJECT;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.ruoyi.common.enums.DelFlag;
import com.ruoyi.common.enums.ProjectStatus;
import com.ruoyi.common.enums.SerialNumberPrefix;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.importExcel.excel.helper.BasicTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ProjectEquipmentInfo;
import com.ruoyi.common.importExcel.excel.tempInfo.ProjectFromInfo;
import com.ruoyi.common.importExcel.utils.ExcelUtils;
import com.ruoyi.common.importExcel.utils.ExcelUtils.UploadResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.LocalUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.SpecialCharacterEscaper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.email.BaseEmailEntity;
import com.ruoyi.common.utils.email.EmailUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.project.business.domain.TbAgent;
import com.ruoyi.project.business.domain.TbArea;
import com.ruoyi.project.business.domain.TcAccount;
import com.ruoyi.project.business.domain.TcProject;
import com.ruoyi.project.business.domain.TcProjectEquipment;
import com.ruoyi.project.business.domain.TcProjectForRelated;
import com.ruoyi.project.business.domain.*;
import com.ruoyi.project.business.domain.vo.board.*;
import com.ruoyi.project.business.domain.vo.lead.LeadRes;
import com.ruoyi.project.business.domain.vo.project.ProjectEquipmentRes;
import com.ruoyi.project.business.domain.vo.project.ProjectExportVO;
import com.ruoyi.project.business.domain.vo.selectParam.ProjectParam;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.MessageTypeEnum;
import com.ruoyi.project.business.mapper.TbAgentMapper;
import com.ruoyi.project.business.mapper.TbAreaMapper;
import com.ruoyi.project.business.mapper.TcAccountMapper;
import com.ruoyi.project.business.mapper.TcLeadMapper;
import com.ruoyi.project.business.mapper.TcProjectMapper;
import com.ruoyi.project.business.service.ITbAgentService;
import com.ruoyi.project.business.service.ITcAccountService;
import com.ruoyi.project.business.service.ITcLeadService;
import com.ruoyi.project.business.service.ITcProjectEquipmentService;
import com.ruoyi.project.business.service.ITcProjectService;
import com.ruoyi.project.business.service.*;
import com.ruoyi.project.common.domain.Message;
import com.ruoyi.project.common.service.ISseEmitterService;
import com.ruoyi.project.common.util.InternalMsgUtil;
import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.service.ISysUserService;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

/**
 * 项目管理Service业务层处理
 *
 * @author ruoyi
 * @date 2024-04-10
 */
@Service("tcProjectService")
public class TcProjectServiceImpl extends ServiceImpl<TcProjectMapper, TcProject> implements ITcProjectService {

    public static final DecimalFormat formatter = new DecimalFormat("#,###.00");

    private static final Logger log = LoggerFactory.getLogger(TcProjectServiceImpl.class);

    @Resource
    private TcProjectMapper tcProjectMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ITcAccountService tcAccountService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISseEmitterService sseEmitterService;

    @Resource
    private ITcLeadService tcLeadService;

    @Resource
    private TcLeadMapper tcLeadMapper;

    @Resource
    private TcAccountMapper tcAccountMapper;

    @Resource
    private EmailUtil emailUtil;

    @Resource
    private ITbAgentService tbAgentService;

    @Resource
    private TbAreaMapper tbAreaMapper;

    @Resource
    private TbAgentMapper tbAgentMapper;

    @Resource
    private ITcProjectEquipmentService tcProjectEquipmentService;

    @Resource
    private ITcProjectHistoryService tcProjectHistoryService;

    @Resource
    private ITcProjectEquipmentHistoryService tcProjectEquipmentHistoryService;

    /**
     * 查询项目管理
     *
     * @param projectId 项目管理主键
     * @return 项目管理
     */
    @Override
    public TcProject selectTcProjectByProjectId(Long projectId) {
        // 校验数据是否已被删除(并且需要在权限内)
        TcProject tcProject = tcProjectMapper.selectTcProjectByProjectId(projectId);
        if (DelFlag.YES.getCode().equals(tcProject.getDelFlag())) {
            throw new ServiceException(MessageUtils.message("business.data.deleted"));
        }

        ProjectParam param = new ProjectParam();
        param.setProjectId(projectId);
        param.setPermissionChar(SecurityUtils.getPermissionCharIns());
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            param.setLoginUserId(SecurityUtils.getUserId());
            param.setPermission(SecurityUtils.getPermissionCharIns());
        }
        List<TcProject> projects = tcProjectMapper.selectTcProjectListNew(param);
        if(ObjectUtils.isEmpty(projects)){
            throw new ServiceException(MessageUtils.message("common.data.noPermession"));
        }

        // 查询负责人
        Optional.ofNullable(sysUserMapper.selectUserById(tcProject.getOwner()))
            .ifPresent(user -> tcProject.setOwnerName(user.getNickName()));

        // 查询客户关联线索
        List<LeadRes> tcLeadList = tcLeadMapper.selectLeadListByProjectId(projectId);
        tcProject.setLeadList(tcLeadList);
        tcProject.setLeadIds(tcLeadList.stream().map(LeadRes::getLeadId).collect(Collectors.toList()));

        // 查询所属代理商tbAgentMapper
        if (tcProject.getOwnerAgent() == 0) {
            // 总部
            tcProject.setOwnerAgentName(MessageUtils.message("agent.headquarters"));
        } else {
            Optional.ofNullable(tbAgentMapper.selectById(tcProject.getOwnerAgent()))
                .ifPresent(agent -> tcProject.setOwnerAgentName(agent.getAgentName()));
        }
        // ProjectEquipmentReq param = new ProjectEquipmentReq().setProjectId(tcProject.getProjectId());
        // tcProject.setMachineList(tcProjectEquipmentMapper.selectTcProjectEquipmentList(param));
        List<TcProjectEquipment> equipmentList = tcProjectEquipmentService.list(
            Wrappers.lambdaQuery(TcProjectEquipment.class)
                .eq(TcProjectEquipment::getProjectId, tcProject.getProjectId()));
        // 总价=单价×数量 保留两位小数
        tcProject.setPriceTotal(equipmentList.stream().map(item -> {
            BigDecimal amount = item.getAmount();
            Long equipmentQuantity = item.getEquipmentQuantity();
            return amount == null || equipmentQuantity == null ? BigDecimal.ZERO
                : amount.multiply(new BigDecimal(equipmentQuantity));
        }).reduce(BigDecimal.ZERO, BigDecimal::add));
        tcProject.setDeviceTotal(
            Math.toIntExact(equipmentList.stream().mapToLong(TcProjectEquipment::getEquipmentQuantity).sum()));
        tcProject.setMachineList(equipmentList);
        return tcProject;
    }

    /**
     * 查询关联项目
     *
     * @return 项目集合
     */
    @Override
    public List<TcProjectForRelated> selectProjectListByLoginId() {
        Long loginId = SecurityUtils.getUserId();
        return tcProjectMapper.selectProjectListByLoginId(loginId);
    }

    @Override
    public List<TcProjectForRelated> selectProjectListByProjectId(TcProject tcProject) {
        return tcProjectMapper.selectProjectListByProjectId(tcProject);
    }

    @Override
    public List<TcProjectForRelated> selectProjectListByQuery(TcProject tcProject) {
        Long loginId = SecurityUtils.getUserId();
        tcProject.setLoginId(loginId);
        SpecialCharacterEscaper.escapeSpecialCharacters(tcProject, TcProject::getQuery);
        return tcProjectMapper.selectProjectListByQuery(tcProject);
    }

    /**
     * 查询需要提醒的项目
     *
     * @param cycle 项目跟踪周期
     * @return 项目集合
     */
    @Override
    public List<TcProject> selectProjectListByCycle(Long cycle) {
        return tcProjectMapper.selectProjectListByCycle(cycle);

    }

    /**
     * 查询项目管理列表
     *
     * @param tcProject 项目管理
     * @return 项目管理
     */
    @Override
    public PageInfo<TcProject> selectTcProjectList(ProjectParam tcProject) {
        if (StringUtils.isNotEmpty(tcProject.getProjectNo())) {
            tcProject.setProjectNo(tcProject.getProjectNo().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getProjectName())) {
            tcProject.setProjectName(tcProject.getProjectName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getCity())) {
            tcProject.setCity(tcProject.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getOwnerName())) {
            tcProject.setOwnerName(tcProject.getOwnerName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        //        tcProject.setPermissionChar(SecurityUtils.getPermissionCharSea());
        tcProject.setPermissionChar(SecurityUtils.getPermissionCharIns());
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            tcProject.setLoginUserId(SecurityUtils.getUserId());
            tcProject.setPermission(SecurityUtils.getPermissionCharIns());
        }
        //return tcProjectMapper.selectTcProjectList(tcProject);
        List<TcProject> projects = tcProjectMapper.selectTcProjectListNew(tcProject);
        // for (TcProject project : projects) {
        //     Integer deviceTotal = project.getDeviceTotal();
        //     // 计算总价
        //     BigDecimal total = project.getDeviceAmount().setScale(2).multiply(new BigDecimal(deviceTotal));
        //     project.setPriceTotal(total);
        // }
        PageInfo<TcProject> result = new PageInfo<>(projects);
        projects = projects.stream().peek(item -> {
            if (Objects.nonNull(item.getPriceTotal())) {
                item.setPriceTotalStr(formatter.format(item.getPriceTotal()));
            } else {
                item.setPriceTotalStr("-");
            }
        }).collect(Collectors.toList());
        result.setList(projects);
        // handleChildren(projects);
        return result;
    }
    @Override
    public PageInfo<TcProject> selectTcProjectListNew(ProjectParam tcProject) {
        if (StringUtils.isNotEmpty(tcProject.getProjectNo())) {
            tcProject.setProjectNo(tcProject.getProjectNo().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getProjectName())) {
            tcProject.setProjectName(tcProject.getProjectName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getCity())) {
            tcProject.setCity(tcProject.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getOwnerName())) {
            tcProject.setOwnerName(tcProject.getOwnerName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        //        tcProject.setPermissionChar(SecurityUtils.getPermissionCharSea());
        tcProject.setPermissionChar(SecurityUtils.getPermissionCharIns());
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            tcProject.setLoginUserId(SecurityUtils.getUserId());
            tcProject.setPermission(SecurityUtils.getPermissionCharIns());
        }
        List<TcProject> projects = tcProjectMapper.selectTcProjectListNewWeb(tcProject);
        PageInfo<TcProject> result = new PageInfo<>(projects);
        projects = projects.stream().peek(item -> {
            if (Objects.nonNull(item.getPriceTotal())) {
                item.setPriceTotalStr(formatter.format(item.getPriceTotal()));
            } else {
                item.setPriceTotalStr("-");
            }
        }).collect(Collectors.toList());
        result.setList(projects);
        return result;
    }

    @Override
    public List<TcProject> listAllProject(ProjectParam tcProject) {
        if (Objects.nonNull(tcProject.getProjectId())) {
            tcProject.setPermissionChar("0");
            List<TcProject> projects = tcProjectMapper.selectTcProjectList(tcProject);
            // 查询报价设备信息，按照设备类型分类处理 children
            return handleQuotationInfo(projects);
        } else {
            return selectTcProjectList(tcProject).getList();
        }
    }

    /**
     * 处理报价信息,按照设备类型分类处理
     *
     * @param projects 项目列表
     */
    private List<TcProject> handleQuotationInfo(List<TcProject> projects) {
        // 查询 设备数量、类型、金额
        List<Long> projectIds = projects.stream().map(TcProject::getProjectId).collect(Collectors.toList());

        List<TcProject> quotationInfo =
                CollectionUtils.isNotEmpty(projectIds) ? tcProjectMapper.selectQuotationInfo(projectIds)
                        : new ArrayList<>();
        Map<Long, List<TcProject>> quotationMap = quotationInfo.stream()
                .collect(Collectors.groupingBy(TcProject::getProjectId));

        for (TcProject project : projects) {
            project.setRowKey(String.valueOf(project.getProjectId()));
            List<TcProject> children = quotationMap.get(project.getProjectId());
            if (CollectionUtils.isNotEmpty(children)) {
                if (children.size() > 1) {
                    for (TcProject child : children) {
                        BeanUtils.copyProperties(project, child, "rowKey", "elevatorNumber", "elevatorType",
                                "elevatorAmount");
                        child.setRowKey(child.getProjectId() + "_" + child.getElevatorType());
                    }
                    project.setChildren(children);
                } else {
                    project.setElevatorNumber(children.get(0).getElevatorNumber());
                    project.setElevatorType(children.get(0).getElevatorType());
                    project.setElevatorAmount(children.get(0).getElevatorAmount());
                }
            }
        }
        return projects;
    }

    @Override
    public List<ProjectExportVO> selectTcProjectListExport(ProjectParam tcProject) {
        if (StringUtils.isNotEmpty(tcProject.getProjectNo())) {
            tcProject.setProjectNo(tcProject.getProjectNo().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getProjectName())) {
            tcProject.setProjectName(tcProject.getProjectName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getCity())) {
            tcProject.setCity(tcProject.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(tcProject.getOwnerName())) {
            tcProject.setOwnerName(tcProject.getOwnerName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        //        tcProject.setPermissionChar(SecurityUtils.getPermissionCharSea());
        tcProject.setPermissionChar(SecurityUtils.getPermissionCharIns());
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            tcProject.setLoginUserId(SecurityUtils.getUserId());
            tcProject.setPermission(SecurityUtils.getPermissionCharIns());
        }
        List<TcProject> tcProjects = tcProjectMapper.selectTcProjectListExport(tcProject);
        Map<Long,String> tcLeadForRelatedMap= new HashMap<>();
        if(CollectionUtils.isNotEmpty(tcProjects)){
            List<Long> accountIdList = tcProjects.stream().map(item->item.getAccountId()).distinct() .collect(Collectors.toList());
            tcLeadForRelatedMap = suppleProjectExportVO(tcProjects.get(0).getLanguage(),accountIdList);
        }


        // handleChildren(tcProjects);
        List<TcProject> result = new ArrayList<>();
        for (TcProject project : tcProjects) {
            List<TcProjectEquipment> equipmentList = tcProjectEquipmentService.list(
                Wrappers.lambdaQuery(TcProjectEquipment.class)
                    .eq(TcProjectEquipment::getProjectId, project.getProjectId()));
            List<ProjectEquipmentRes> collect = equipmentList.stream()
                .map(a -> ProjectEquipmentRes.from(a, project.getCurrencyId()))
                .peek(item -> {
                    String amount = Optional.ofNullable(item.getAmount()).map(formatter::format).orElse("");
                    item.setAmountStr(amount);
                    String priceTotal = Optional.ofNullable(item.getPriceTotal()).map(formatter::format).orElse("");
                    item.setPriceTotalStr(priceTotal);
                }).collect(Collectors.toList());
            BigDecimal priceTotal = collect.stream().map(ProjectEquipmentRes::getPriceTotal)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            List<Long> collect1 = collect
                .stream()
                .map(ProjectEquipmentRes::getEquipmentQuantity)
                .filter(Objects::nonNull).collect(Collectors.toList());
            long total = 0;
            if (CollUtil.isNotEmpty(collect1)) {
                total = collect1.stream().mapToLong(a -> a).sum();
            }
            project.setDeviceTotal((int)total);
            project.setPriceTotal(priceTotal);
            String priceTotal1 = Optional.ofNullable(project.getPriceTotal()).map(formatter::format).orElse("");
            project.setPriceTotalStr(priceTotal1);
            project.setSubList(collect);
            if(tcLeadForRelatedMap.containsKey(project.getAccountId())){
                project.setLeads(tcLeadForRelatedMap.get(project.getAccountId()));
            }
            if (CollUtil.isNotEmpty(collect)) {
                for (ProjectEquipmentRes projectEquipmentRes : collect) {
                    TcProject project1 = new TcProject();
                    BeanUtils.copyProperties(project, project1);
                    project1.setSubList(Collections.singletonList(projectEquipmentRes));
                    result.add(project1);
                }
            } else {
                TcProject project1 = new TcProject();
                BeanUtils.copyProperties(project, project1);
                result.add(project1);
            }

        }

        return result.stream().map(item -> {
            ProjectExportVO exportVO = new ProjectExportVO();
            BeanUtils.copyProperties(item, exportVO);

            if (CollUtil.isNotEmpty(item.getSubList())) {
                ProjectEquipmentRes projectEquipmentRes = item.getSubList().get(0);
                exportVO.setStandard(projectEquipmentRes.getStandard());
                exportVO.setElevatorModel(projectEquipmentRes.getElevatorModel());
                exportVO.setEquipmentType(projectEquipmentRes.getEquipmentType());
                exportVO.setEquipmentQuantity(projectEquipmentRes.getEquipmentQuantity());
                exportVO.setAmountStr(projectEquipmentRes.getAmountStr());
                exportVO.setUnitPriceTotalStr(projectEquipmentRes.getPriceTotalStr());
                if(ObjectUtils.isEmpty(item.getLoseRemark())){
                    exportVO.setDelayLoseRemark(item.getDelayRemark());
                }else {
                    exportVO.setDelayLoseRemark(item.getLoseRemark());
                }
            }
            return exportVO;
        }).collect(Collectors.toList());
    }
     /**
      * @Author Chenj
      * @Description 对导出的内容完善
      * @Date 14:11 2024/8/5
      **/
    public Map<Long,String> suppleProjectExportVO(String language,List<Long> accountIdList){
        Map<Long,String> tcLeadForRelatedMap = tcLeadMapper.suppleProjectExportVO(language,accountIdList).stream().collect(Collectors.toMap(
                item->item.getRelativeAccount(),item->item.getLeadNo() + ": 【" + item.getAreaName() + "】 【" +item.getCompany() +"】" + "】 【" +item.getContact() +"】"
        ));

        return tcLeadForRelatedMap;
    }


    /**
     * 新增项目管理
     *
     * @param tcProject 项目管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTcProject(TcProject tcProject, Boolean needCheck) {
        // 获取权限字段串
        // String permissionChar = tcAccountService.getPermissionChar(tcProject.getAreaId());
        Long ownerAgent = tcProject.getOwnerAgent();
        String permissionChar = 0 == ownerAgent ? tcProject.getAreaId().toString() : ownerAgent.toString();
        // 校验项目名称是否重复
        if (Boolean.TRUE.equals(needCheck)
            && tcProjectMapper.selectCountByProjectName(tcProject.getProjectName(), permissionChar, null) > 0) {
            throw new ServiceException(
                "[" + tcProject.getProjectName() + "]" + MessageUtils.message("project.name.repeat"));
        }
        tcProject.setPermissionChar(permissionChar);
        // 业务编号采番规则，使用RedisCache.generateSerialNumber(SerialNumberPrefix.业务)方法
        String projectNo = redisCache.generateSerialNumber(SerialNumberPrefix.PRJ.getPrefix());
        tcProject.setProjectNo(projectNo);
        // 查询负责人的所有代理商
        if (tcProject.getOwnerAgent() == null) {
            tcProject.setOwnerAgent(sysUserMapper.selectDeptIdById(tcProject.getOwner()));
        }
        Long agentId = SecurityUtils.getDeptId();
        if (agentId == 0) {
            tcProject.setStatus(ProjectStatus.Third.getCode());
        } else {
            tcProject.setStatus(ProjectStatus.First.getCode());
            // // 或者直接放在代码最后执行
            // AsyncUtils.executeAsyncAfterCommit(() -> doSendEmail(tcProject));
        }
        Date now = DateUtils.getNowDate();
        tcProject.setCreateBy(SecurityUtils.getUserId().toString());
        tcProject.setCreateTime(now);
        tcProject.setUpdateTime(now);
        int result = tcProjectMapper.insertTcProject(tcProject);
        //        if (tcProject.getLeadId() != null) {
        //            tcLeadService.convertProject(tcProject.getLeadId(), tcProject.getProjectId());
        //        }

        // 跟新客户状态
        if (tcProject.getAccountId() != null) {
            TcAccount tcAccount = tcAccountService.selectTcAccountByAccountId(tcProject.getAccountId());
            tcAccount.setStatus(CONVERTED_PROJECT.getCode());
            // tcAccountService.updateTcAccount(tcAccount);
            tcAccountMapper.updateTcAccount(tcAccount);
        }
        // 线索信息绑定项目
        if (tcProject.getLeadIds() != null && !tcProject.getLeadIds().isEmpty()) {
            for (Long leadId : tcProject.getLeadIds()) {
                tcLeadService.convertProject(leadId, tcProject.getProjectId());
            }
        }

        //20240628新增设备多选
        List<TcProjectEquipment> machineList = tcProject.getMachineList();
        if (CollectionUtils.isEmpty(machineList)) {
            return result;
        }
        for (TcProjectEquipment item : machineList) {
            //赋值id
            item.setProjectId(tcProject.getProjectId());
            item.setTotalPrice(item.getAmount().multiply(BigDecimal.valueOf(item.getEquipmentQuantity())));
        }
        // tcProjectEquipmentMapper.InsertBySQL(machineList);
        boolean r = tcProjectEquipmentService.saveBatch(machineList);

        if (0L != agentId) {
            List<SysUser> sales = sysUserService.selectSaleByCurAgent();

            InternalMsgUtil.sendMsg(sales.stream().map(SysUser::getUserId).collect(Collectors.toList()),
                    tcProject.getProjectName());
        }

        if (ProjectStatus.First.getCode().equals(tcProject.getStatus())) {
            // 发送邮件
            sendEmail(tcProject, true);
        }

        // 履历信息插入
        Long newVersion = tcProjectMapper.getNewVersion(tcProject.getProjectId());
        TcProjectHistory tcProjectHistory = new TcProjectHistory();
        BeanUtils.copyBeanProp(tcProjectHistory, tcProject);
        tcProjectHistory.setVersion(newVersion);
        tcProjectHistoryService.insertTcProjectHistory(tcProjectHistory);

        if (CollectionUtils.isNotEmpty(machineList)) {
            List<TcProjectEquipmentHistory> equipmentHistories = machineList.stream().map(machine -> {
                TcProjectEquipmentHistory history = new TcProjectEquipmentHistory();
                BeanUtils.copyBeanProp(history, machine);
                history.setVersion(newVersion);
                return history;
            }).collect(Collectors.toList());
            tcProjectEquipmentHistoryService.saveBatch(equipmentHistories);
        }

        return result;
    }

    /**
     * 修改项目管理
     *
     * @param tcProject 项目管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTcProject(TcProject tcProject) {
        // 获取权限字段串
        // String permissionChar = tcAccountService.getPermissionChar(tcProject.getAreaId());
        String permissionChar = 0 == tcProject.getOwnerAgent() ? tcProject.getAreaId().toString() : tcProject.getOwnerAgent().toString();
        // 校验项目名称是否重复
        if (tcProjectMapper.selectCountByProjectName(tcProject.getProjectName(), permissionChar,
            tcProject.getProjectId()) > 0) {
            throw new ServiceException(MessageUtils.message("project.name.repeat"));
        }
        // 判断是否需要推送消息
        boolean flag = false;
        List<Long> oldIds = new ArrayList<>();
        List<Long> newIds = new ArrayList<>();
        TcProject oldProject = tcProjectMapper.selectTcProjectByProjectId(tcProject.getProjectId());
        if (!Objects.equals(oldProject.getOwner(), tcProject.getOwner())) {
            flag = true;
            oldIds.add(oldProject.getOwner());
            newIds.add(tcProject.getOwner());
        }
        tcProject.setPermissionChar(permissionChar);
        // 查询负责人的所有代理商
        if (tcProject.getOwnerAgent() == null) {
            tcProject.setOwnerAgent(sysUserMapper.selectDeptIdById(tcProject.getOwner()));
        }
        // 如果处于审批不通过状态：02，更新后转为待审批状态：01
        if (ProjectStatus.Second.getCode().equals(tcProject.getStatus())) {
            tcProject.setStatus(ProjectStatus.First.getCode());
        }
        tcProject.setUpdateBy(SecurityUtils.getUserId().toString());
        tcProject.setUpdateTime(DateUtils.getNowDate());
        // 不考虑非空全部修改
        int result = tcProjectMapper.updateTcProjectAll(tcProject);
        if (flag) {
            Object[] args = new String[1];
            args[0] = tcProject.getProjectName();
            MessageSource oldSource = SpringUtils.getBean(MessageSource.class);
            String messageContentOld = oldSource.getMessage("project.owner.message.old", args, new Locale("zh", "CN"));
            String messageContentUSOld = oldSource.getMessage("project.owner.message.old", args,
                new Locale("en", "US"));
            String messageContentRUOld = oldSource.getMessage("project.owner.message.old", args,
                new Locale("ru", "RU"));
            String messageContentESOld = oldSource.getMessage("project.owner.message.old", args,
                new Locale("es", "ES"));
            Message messageForOld = new Message();
            messageForOld.setMessageType(MessageTypeEnum.PROJECT.getValue());
            messageForOld.setMessageContent(messageContentOld);
            messageForOld.setMessageContentUS(messageContentUSOld);
            messageForOld.setMessageContentRU(messageContentRUOld);
            messageForOld.setMessageContentES(messageContentESOld);

            MessageSource newSource = SpringUtils.getBean(MessageSource.class);
            String messageContentNew = newSource.getMessage("project.owner.message.new", args, new Locale("zh", "CN"));
            String messageContentUSNew = newSource.getMessage("project.owner.message.new", args,
                new Locale("en", "US"));
            String messageContentRUNew = newSource.getMessage("project.owner.message.new", args,
                new Locale("ru", "RU"));
            String messageContentESNew = newSource.getMessage("project.owner.message.new", args,
                new Locale("es", "ES"));
            Message messageForNew = new Message();
            messageForNew.setMessageType(MessageTypeEnum.PROJECT.getValue());
            messageForNew.setMessageContent(messageContentNew);
            messageForNew.setMessageContentUS(messageContentUSNew);
            messageForNew.setMessageContentRU(messageContentRUNew);
            messageForNew.setMessageContentES(messageContentESNew);
            sseEmitterService.sendSaveMessage(newIds, messageForNew);
            sseEmitterService.sendSaveMessage(oldIds, messageForOld);
        }

        //20240628新增设备多选 (删了再新增)
        //先删除
        // tcProjectEquipmentMapper.deleteTcProjectEquipmentByProjectId(tcProject.getProjectId());
        tcProjectEquipmentService.remove(Wrappers.lambdaQuery(TcProjectEquipment.class)
            .eq(TcProjectEquipment::getProjectId, tcProject.getProjectId()));
        //再新增
        List<TcProjectEquipment> machineList = tcProject.getMachineList();
        // for (TcProjectEquipment item : machineList) {
        //     //赋值id
        //     item.setProjectId(tcProject.getProjectId());
        //     item.setCreateBy(SecurityUtils.getUserId().toString());
        //     item.setCreateTime(DateUtils.getNowDate());
        //     item.setUpdateBy(SecurityUtils.getUserId().toString());
        //     item.setUpdateTime(DateUtils.getNowDate());
        // }
        // tcProjectEquipmentMapper.InsertBySQL(machineList);
        for (TcProjectEquipment equipment : machineList) {
            equipment.setId(null);
            equipment.setTotalPrice(
                equipment.getAmount().multiply(BigDecimal.valueOf(equipment.getEquipmentQuantity())));
        }
        boolean r = tcProjectEquipmentService.saveBatch(machineList);
        if (!r) {
            throw new ServiceException("设备信息保存失败");
        }


        // 履历信息插入
        Long newVersion = tcProjectMapper.getNewVersion(tcProject.getProjectId());
        TcProjectHistory tcProjectHistory = new TcProjectHistory();
        BeanUtils.copyBeanProp(tcProjectHistory, tcProject);
        tcProjectHistory.setVersion(newVersion);
        tcProjectHistoryService.insertTcProjectHistory(tcProjectHistory);

        if (CollectionUtils.isNotEmpty(machineList)) {
            List<TcProjectEquipmentHistory> equipmentHistories = machineList.stream().map(machine -> {
                TcProjectEquipmentHistory history = new TcProjectEquipmentHistory();
                BeanUtils.copyBeanProp(history, machine);
                history.setVersion(newVersion);
                return history;
            }).collect(Collectors.toList());
            tcProjectEquipmentHistoryService.saveBatch(equipmentHistories);
        }
        return result;
    }

    /**
     * 批量删除项目管理
     *
     * @param projectIds 需要删除的项目管理主键
     * @return 结果
     */
    @Override
    public int deleteTcProjectByProjectIds(Long[] projectIds) {
        return tcProjectMapper.deleteTcProjectByProjectIds(projectIds);
    }

    /**
     * 删除项目管理信息
     *
     * @param projectId 项目管理主键
     * @return 结果
     */
    @Override
    public int deleteTcProjectByProjectId(Long projectId) {
        return tcProjectMapper.deleteTcProjectByProjectId(projectId);
    }

    /**
     * 查询客户关联项目
     *
     * @param tcProject 项目
     * @return 结果
     */
    @Override
    public List<TcProjectForRelated> selectProjectListByAccount(TcProject tcProject) {
        return tcProjectMapper.selectProjectListByAccount(tcProject);
    }

    /**
     * 设为标杆项目
     *
     * @param tcProject 项目
     * @return 结果
     */
    @Override
    public int setModel(TcProject tcProject) {
        tcProject.setUpdateBy(SecurityUtils.getUserId().toString());
        tcProject.setUpdateTime(DateUtils.getNowDate());

        int result = tcProjectMapper.updateTcProject(tcProject);

        TcProject exist = tcProjectMapper.selectTcProjectByProjectId(tcProject.getProjectId());

        // 履历信息插入
        Long newVersion = tcProjectMapper.getNewVersion(exist.getProjectId());
        TcProjectHistory tcProjectHistory = new TcProjectHistory();
        BeanUtils.copyBeanProp(tcProjectHistory, exist);
        tcProjectHistory.setVersion(newVersion);
        tcProjectHistory.setModifyRemark(tcProject.getModifyRemark());
        tcProjectHistoryService.insertTcProjectHistory(tcProjectHistory);

        List<TcProjectEquipment> machineList = tcProjectEquipmentService.list(Wrappers.<TcProjectEquipment>lambdaQuery()
                .eq(TcProjectEquipment::getProjectId, exist.getProjectId()).eq(TcProjectEquipment::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        if (CollectionUtils.isNotEmpty(machineList)) {
            List<TcProjectEquipmentHistory> equipmentHistories = machineList.stream().map(machine -> {
                TcProjectEquipmentHistory history = new TcProjectEquipmentHistory();
                BeanUtils.copyBeanProp(history, machine);
                history.setId(null);
                history.setVersion(newVersion);
                return history;
            }).collect(Collectors.toList());
            tcProjectEquipmentHistoryService.saveBatch(equipmentHistories);
        }
        return result;
    }

    /**
     * 延期/丢单
     *
     * @param tcProject 项目
     * @return 结果
     */
    @Override
    public int delayLost(TcProject tcProject) {
        // 延期
        if ("09".equals(tcProject.getStatus())) {
            tcProject.setProgress("0%");
        } else if ("10".equals(tcProject.getStatus())) {
            tcProject.setProgress("0% ");
        }
        tcProject.setStatus(null);
        tcProject.setUpdateBy(SecurityUtils.getUserId().toString());
        tcProject.setUpdateTime(DateUtils.getNowDate());
        int i =tcProjectMapper.updateTcProject(tcProject);

        TcProject exist = tcProjectMapper.selectTcProjectByProjectId(tcProject.getProjectId());
        // 履历信息插入
        Long newVersion = tcProjectMapper.getNewVersion(tcProject.getProjectId());
        TcProjectHistory tcProjectHistory = new TcProjectHistory();
        BeanUtils.copyBeanProp(tcProjectHistory, exist);
        tcProjectHistory.setVersion(newVersion);
        tcProjectHistory.setModifyRemark(tcProject.getModifyRemark());
        tcProjectHistoryService.insertTcProjectHistory(tcProjectHistory);

        List<TcProjectEquipment> machineList = tcProjectEquipmentService.list(Wrappers.<TcProjectEquipment>lambdaQuery()
                .eq(TcProjectEquipment::getProjectId, tcProject.getProjectId()).eq(TcProjectEquipment::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        if (CollectionUtils.isNotEmpty(machineList)) {
            List<TcProjectEquipmentHistory> equipmentHistories = machineList.stream().map(machine -> {
                TcProjectEquipmentHistory history = new TcProjectEquipmentHistory();
                BeanUtils.copyBeanProp(history, machine);
                history.setId(null);
                history.setVersion(newVersion);
                return history;
            }).collect(Collectors.toList());
            tcProjectEquipmentHistoryService.saveBatch(equipmentHistories);
        }

        return i;
    }

    /**
     * 审批
     *
     * @param tcProject 项目
     * @return 结果
     */
    @Override
    public int approve(TcProject tcProject) {
        if ("02".equals(tcProject.getStatus())) {
            tcProject.setStatus(ProjectStatus.Second.getCode());
        } else if ("03".equals(tcProject.getStatus())) {
            tcProject.setStatus(ProjectStatus.Third.getCode());
        }
        // 审批人
        tcProject.setAuditPerson(SecurityUtils.getUserId());
        tcProject.setUpdateBy(SecurityUtils.getUserId().toString());
        tcProject.setUpdateTime(DateUtils.getNowDate());
        int row = tcProjectMapper.updateTcProject(tcProject);
        if (row > 0) {
            // 发送邮件
            sendEmail(tcProject, false);
        }
        return row;
    }

    private void sendEmail(TcProject project, boolean isPendingApproval) {
        ThreadUtil.execute(() -> doSendEmail(project, isPendingApproval));
    }

    private void doSendEmail(TcProject project, boolean isPendingApproval) {
        String subject = "全球项目管理平台";
        String context;
        Long send2Uid;
        String projectNo;
        String projectName;
        String refuseReason = "";
        String projectStatus;
        if (isPendingApproval) {
            projectName = project.getProjectName();
            projectNo = project.getProjectNo();
            projectStatus = project.getStatus();
            TbAgent agent = tbAgentService.getById(project.getOwnerAgent());
            send2Uid = agent.getParentSalerId();
        } else {
            TcProject tcProject = tcProjectMapper.selectTcProjectByProjectId(project.getProjectId());
            projectName = tcProject.getProjectName();
            projectNo = tcProject.getProjectNo();
            projectStatus = tcProject.getStatus();
            send2Uid = tcProject.getOwner();
            refuseReason = tcProject.getRefuseReason();
        }

        SysUser user = sysUserMapper.selectById(send2Uid);
        String seng2Email = user.getEmail();

        ProjectStatus status = ProjectStatus.fromCode(projectStatus);
        Assert.notNull(status, "project status is invalid.");
        switch (status) {
            case First:
                context = "您有一个项目待审核，项目编号为{" + projectNo + "}";
                break;
            case Second:
                context = "您的{" + projectName + "}{" + projectNo + "}未通过审核，打回原因为{" + refuseReason + "}";
                break;
            case Third:
                context = "您的{" + projectName + "}{" + projectNo + "}已通过审核";
                break;
            default:
                throw new IllegalArgumentException("project status");
        }

        String text = context;

        BaseEmailEntity email = BaseEmailEntity.builder()
                .to(new String[]{seng2Email})
                .subject(subject)
                .text(text)
                .build();

        String flag = IdUtil.nanoId();

        log.info("flag:{}, 发送邮件：{}", flag, email);
        try {
            emailUtil.sendSimpleMail(email);
        } catch (Exception e) {
            log.error("flag:{}, 发送邮件失败", flag, e);
        }
        log.info("flag:{}, 发送邮件成功", flag);
    }

    @Override
    public List<TcProject> getUnFollowedList(String unfollowedMode) {
        // unfollowedMode: 1-最近一周；2-最近一个月；3-最近半年
        LocalDateTime startDate;
        LocalDateTime endDate = LocalDateTime.of(LocalDate.now(), LocalTime.of(23, 59, 59));

        switch (unfollowedMode) {
            case "1":
                startDate = LocalDate.now().minusDays(6).atStartOfDay();
                break;
            case "2":
                // startDate = LocalDate.now().minusMonths(1).atStartOfDay();
                startDate = LocalDate.now().minusDays(29).atStartOfDay();
                break;
            case "3":
                // startDate = LocalDate.now().minusMonths(6).atStartOfDay();
                startDate = LocalDate.now().minusDays(179).atStartOfDay();
                break;
            default:
                throw new IllegalArgumentException("unfollowedMode");
        }
        return tcProjectMapper.selectUnFollowedList(startDate, endDate, SecurityUtils.getPermissionCharIns());
    }

    @Override
    public int changeOwner(TcProject tcProject) {
        // 负责人与代理商脱钩
        // tcProject.setOwnerAgent(sysUserMapper.selectDeptIdById(tcProject.getOwner()));
        tcProject.setUpdateBy(SecurityUtils.getUserId().toString());
        tcProject.setUpdateTime(DateUtils.getNowDate());
        SysUser user = sysUserMapper.selectUserById(tcProject.getOwner());
        if (user == null) {
            throw new ServiceException("user not found");
        }
        tcProject.setPermissionChar(0L == user.getDeptId() ? user.getAreaId() : user.getDeptId().toString());

        // 同时变更区域，如果变更的目标用户有多个区域权限，取有关联的第一个
        TcProject projectDb = tcProjectMapper.selectTcProjectByProjectId(tcProject.getProjectId());
        List<Long> areaIdList = user.getAreaIdList();
        if (CollectionUtils.isNotEmpty(areaIdList)) {
            Long areaId = projectDb.getAreaId();
            List<TbArea> areas = tbAreaMapper.selectListByIdsAndAncestorId(areaIdList, areaId);
            // Map<Long, List<String>> area = areas.stream().collect(Collectors.toMap(TbArea::getAreaId, item -> Arrays.stream(item.getPermissionChar().split(",")).filter(StringUtils::isNotBlank).collect(Collectors.toList())));
            if (CollectionUtils.isEmpty(areas)) {
                tcProject.setAreaId(areaIdList.get(0));
            } else {
                tcProject.setAreaId(areas.get(0).getAreaId());
            }
        }

        int result = tcProjectMapper.updateTcProject(tcProject);

        TcProject exist = tcProjectMapper.selectTcProjectByProjectId(tcProject.getProjectId());
        // 履历信息插入
        Long newVersion = tcProjectMapper.getNewVersion(exist.getProjectId());
        TcProjectHistory tcProjectHistory = new TcProjectHistory();
        BeanUtils.copyBeanProp(tcProjectHistory, exist);
        tcProjectHistory.setVersion(newVersion);
        tcProjectHistory.setModifyRemark(tcProject.getModifyRemark());
        tcProjectHistoryService.insertTcProjectHistory(tcProjectHistory);

        List<TcProjectEquipment> machineList = tcProjectEquipmentService.list(Wrappers.<TcProjectEquipment>lambdaQuery()
                .eq(TcProjectEquipment::getProjectId, exist.getProjectId()).eq(TcProjectEquipment::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        if (CollectionUtils.isNotEmpty(machineList)) {
            List<TcProjectEquipmentHistory> equipmentHistories = machineList.stream().map(machine -> {
                TcProjectEquipmentHistory history = new TcProjectEquipmentHistory();
                BeanUtils.copyBeanProp(history, machine);
                history.setId(null);
                history.setVersion(newVersion);
                return history;
            }).collect(Collectors.toList());
            tcProjectEquipmentHistoryService.saveBatch(equipmentHistories);
        }

        return result;
    }

    @Override
    public List<TcProject> selectTcProjectListApp() {
        return tcProjectMapper.selectTcProjectListApp(SecurityUtils.getPermissionCharIns(), SecurityUtils.getUserId());
    }

    @Override
    public Integer existProjectByAgentIds(Long[] agentIds) {
        if (agentIds == null || agentIds.length == 0) {
            return null;
        }
        return tcProjectMapper.existProjectByAgentIds(agentIds);
    }

    @Override
    public List<Pair<Long, String>> selectAreasByCurUser() {
        List<Long> areaIds = tcProjectMapper.selectAreasByCurUser(SecurityUtils.getPermissionCharIns());

        return LocalUtils.selectAreasByCurUser(areaIds);
    }

    @Override
    public List<Pair<Long, String>> selectCountriesByCurUser() {
        List<Long> countryIds = tcProjectMapper.selectCountriesByCurUser(SecurityUtils.getPermissionCharIns());

        return LocalUtils.selectCountriesByCurUser(countryIds);
    }
    @Override
    public List<String> getProjectName(Long ownerAgent) {
        return tcProjectMapper.getProjectName(ownerAgent);
    }

    @Override
    public UploadResult<ProjectFromInfo> checkProjectFormInfoImport(BasicTableInfoHelper tableInfo,
        List<ProjectFromInfo> list) {
        if (CollUtil.isEmpty(list)) {
            // fast fail
            return ExcelUtils.checkData(list, it -> new ArrayList<>());
        }
        List<ProjectFromInfo> didList = getMerginList(list);
        // 获取当前账号的区域及其下属区域
        List<Long> areaIds = SecurityUtils.getAreaIds();
        List<Long> longs = tbAreaMapper.selectChildAreaIdsByAreaIds(areaIds);
        areaIds.addAll(longs);
        // 获取所有区域
        // List<String> areaList = didList.stream().map(ProjectFromInfo::getArea).collect(Collectors.toList());
        // List<TbArea> tbAreas = tbAreaMapper.listByAreaName(areaList);
        // Map<String, TbArea> areaMap = tbAreas.stream()
        //     .collect(Collectors.toMap(TbArea::getAreaName, i -> i, (a, b) -> a));

        // // 获取客户
        // List<String> accountNameList = didList.stream().map(ProjectFromInfo::getAccountName)
        //     .collect(Collectors.toList());
        // Map<String, TcAccount> accountMap = new HashMap<>();
        // if (CollUtil.isNotEmpty(accountNameList)) {
        //     List<TcAccount> tcAccounts = tcAccountService.listByAccountNameList(accountNameList);
        //     accountMap = tcAccounts.stream()
        //         .collect(Collectors.toMap(TcAccount::getAccountName, i -> i, (a, b) -> a));
        // }
        // Map<String, TcAccount> finalAccountMap = accountMap;

        // 获取负责人
        List<String> ownerList = didList.stream().map(ProjectFromInfo::getOwner).collect(Collectors.toList());
        Map<String, SysUser> userMap = new HashMap<>();
        if (CollUtil.isNotEmpty(ownerList)) {
            List<SysUser> list1 = sysUserService.getOwnerList(false);
            userMap = list1.stream()
                .collect(Collectors.toMap(SysUser::getNickName, c -> c, (a, b) -> a));
        }
        Map<String, SysUser> finalUserMap = userMap;
        // 标杆项目
        List<SysDictData> projectFlagList = DictUtils.getDictCache("project_flag");
        Map<String, String> projectFlagMap = getDictMap(projectFlagList);
        // 币种
        List<SysDictData> currencyTypeList = DictUtils.getDictCache("currency_type");
        Map<String, String> currencyTypeMap = getDictMap(currencyTypeList);
        // 产品系列（项目细分市场）
        List<SysDictData> projectMarketList = DictUtils.getDictCache("project_market");
        Map<String, String> projectMarketMap = getDictMap(projectMarketList);
        // 项目类型
        List<SysDictData> projectTypeList = DictUtils.getDictCache("project_type");
        Map<String, String> projectTypeMap = getDictMap(projectTypeList);
        // 设备类型
        List<SysDictData> intentionalProductList = DictUtils.getDictCache("intentional_product");
        Map<String, String> intentionalProductMap = getDictMap(intentionalProductList);
        // // 梯形
        // List<SysDictData> elevatorTypeList = DictUtils.getDictCache("elevator_type");
        // Map<String, String> elevatorTypeMap = getDictMap(elevatorTypeList);
        // 项目状态
        List<SysDictData> projectProgressList = DictUtils.getDictCache("project_progress");
        Map<String, String> projectProgressMap = getDictMap(projectProgressList);
        // // 项目审批状态
        // List<SysDictData> projectStatusList = DictUtils.getDictCache("project_status");
        // Map<String, String> projectStatusMap = getDictMap(projectStatusList);
        List<String> projectNameList = didList.stream().map(ProjectFromInfo::getProjectName)
            .collect(Collectors.toList());

        return ExcelUtils.checkData(didList, it -> {
            List<String> errors = Lists.newArrayList();
             notBlank(errors, "project.city", it.getCity());
            notBlank(errors, "business.owner", it.getOwner());
            notBlank(errors, "project.name", it.getProjectName());
            notBlank(errors, "project.type", it.getType());
            notBlank(errors, "project.flag", it.getModelFlag());
            notBlank(errors, "project.market", it.getSegmentedMarket());
            notBlank(errors, "project.relatedCustomer", it.getAccountName());
            // notBlank(errors, "project.audit.status", it.getStatus());
            notBlank(errors, "project.status", it.getProgress());
            notBlank(errors, "quotation.currencyName", it.getCurrency());
            // notBlank(errors, "project.keyContactPerson", it.getKeyContactPerson());
            // notBlank(errors, "project.keyContact", it.getKeyContact());
            // notBlank(errors, "project.keyEmail", it.getKeyEmail());

            notBlank(errors, "project.contactPerson", it.getContactPerson());
            notBlank(errors, "project.contact", it.getContact());
            notBlank(errors, "agent.email", it.getEmail());

            maxLength(errors, "project.name", it.getProjectName(), 100);
            maxLength(errors, "project.city", it.getCity(), 100);
            maxLength(errors, "project.keyContactPerson", it.getKeyContactPerson(), 100);
            maxLength(errors, "project.keyJobTitle", it.getKeyJobTitle(), 100);
            maxLength(errors, "project.keyContact", it.getKeyContact(), 100);
            maxLength(errors, "project.keyEmail", it.getKeyEmail(), 100);
            maxLength(errors, "project.address", it.getAddress(), 100);
            maxLength(errors, "lead.jobTitle", it.getJobTitle(), 100);
            maxLength(errors, "project.contact", it.getContact(), 100);
            maxLength(errors, "agent.email", it.getEmail(), 100);

            maxLength(errors, "project.specialRemark", it.getSpecialRemark(), 250);
            maxLength(errors, "project.solution", it.getSolution(), 250);
            maxLength(errors, "common.remark", it.getRemark(), 500);

            // 校验区域
            // TbArea tbArea = areaMap.get(it.getArea());
            // if (Objects.nonNull(tbArea)) {
            //     Long areaId = tbArea.getAreaId();
            //     if (!areaIds.contains(areaId)) {
            //         businessErrors.add("区域【" + it.getArea() + "】为非法区域");
            //     }
            // } else {
            //     businessErrors.add("区域【" + it.getArea() + "】不存在");
            // }
            // 负责人
            SysUser user = finalUserMap.get(it.getOwner());
            if (Objects.isNull(user)) {
                errors.add(MessageUtils.message("business.owner")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setOwnerId(user.getUserId());
            }
            // 校验关联客户
            TcAccount tcAccount = null;
            if (Objects.nonNull(user)) {
                String perm = String.valueOf(user.getDeptId());
                if (Objects.isNull(perm) || user.getDeptId() == 0) {
                    perm = user.getAreaId();
                }
                List<TcAccount> tcAccounts = tcAccountMapper.listRemote(null, perm, user.getUserId());
                if (CollUtil.isNotEmpty(tcAccounts)) {
                    tcAccount = tcAccounts
                        .stream()
                        .filter(a -> a.getAccountName().equals(it.getAccountName()))
                        .findFirst().orElse(null);
                }
            }

            if (Objects.nonNull(tcAccount)) {
                it.setAccountId(tcAccount.getAccountId());
                it.setCountryId(tcAccount.getCountryId());
                it.setAreaId(tcAccount.getAreaId());
                it.setAgentId(tcAccount.getOwnerAgent());
            } else {
                errors.add(MessageUtils.message("project.relatedCustomer")
                    + MessageUtils.message("excel.message.undefine"));
            }
            // 标杆项目
            String modelFlagValue = projectFlagMap.get(it.getModelFlag());
            if (StringUtils.isBlank(modelFlagValue)) {
                errors.add(MessageUtils.message("project.flag")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setModelFlagValue(modelFlagValue);
            }
            // 币种
            String currencyValue = currencyTypeMap.get(it.getCurrency());
            if (StringUtils.isBlank(currencyValue)) {
                errors.add(MessageUtils.message("quotation.currencyName")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setCurrencyValue(currencyValue);
            }
            // 产品系列
            String marketValue = projectMarketMap.get(it.getSegmentedMarket());
            if (StringUtils.isBlank(marketValue)) {
                errors.add(MessageUtils.message("project.market")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setSegmentedMarketValue(marketValue);
            }
            // 项目类型
            String typeValue = projectTypeMap.get(it.getType());
            if (StringUtils.isBlank(typeValue)) {
                errors.add(MessageUtils.message("project.type")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setTypeValue(typeValue);
            }
            // 项目状态
            String progressValue = projectProgressMap.get(it.getProgress());
            if (Objects.isNull(progressValue)) {
                errors.add(MessageUtils.message("project.status")
                    + MessageUtils.message("excel.message.undefine"));
            } else {
                it.setProgressValue(progressValue);
            }
            // // 审批状态
            // String statusValue = projectStatusMap.get(it.getStatus());
            // if (Objects.isNull(statusValue)) {
            //     errors.add(MessageUtils.message("project.audit.status")
            //         + MessageUtils.message("excel.message.undefine"));
            // } else {
            //     it.setStatusValue(statusValue);
            // }
            // try {
            //     it.setCompletionYearDate(DateUtil.parse(it.getCompletionYear(), DatePattern.NORM_DATE_PATTERN));
            // } catch (Exception e) {
            //     businessErrors.add("项目交期【" + it.getOwner() + "】非法");
            // }
            if (Objects.nonNull(it.getPlanDealMonth())) {
                try {
                    it.setPlanDealMonthDate(DateUtil.parse(it.getPlanDealMonth(), DatePattern.NORM_DATE_PATTERN));
                } catch (Exception e) {
                    errors.add(MessageUtils.message("project.planDealMonth")
                        + MessageUtils.message("excel.message.undefine"));
                }
            }

            if (Objects.nonNull(it.getExpectedInstallStartDateStr())) {
                try {
                    it.setExpectedInstallStartDate(
                        DateUtil.parse(it.getExpectedInstallStartDateStr(), DatePattern.NORM_DATE_PATTERN));
                } catch (Exception e) {
                    errors.add(MessageUtils.message("project.expectedInstallStartDate")
                        + MessageUtils.message("excel.message.undefine"));
                }
            }

            String permissionChar = null;
            if (Objects.nonNull(it.getAreaId())) {
                // 获取权限字段串
                // permissionChar = tcAccountService.getPermissionChar(it.getAreaId());
                permissionChar = 0 == it.getAgentId() ? it.getAreaId().toString() : it.getAgentId().toString();
            }
            // 校验项目名称是否重复
            if (Objects.nonNull(it.getAreaId())
                && StringUtils.isNotBlank(permissionChar)
                && tcProjectMapper.selectCountByProjectName(it.getProjectName(), permissionChar, null) > 0) {
                errors.add("[" + it.getProjectName() + "]" + MessageUtils.message("project.name.repeat"));
            } else {
                // 检查excel内是否重复
                if (projectNameList.stream().filter(a -> compareProjectName(it.getProjectName(), a)).count() > 1) {
                    errors.add("[" + it.getProjectName() + "]" + MessageUtils.message("project.name.repeat"));
                }
            }
            if (CollUtil.isNotEmpty(it.getEquipmentInfoList())) {
                for (ProjectEquipmentInfo projectEquipmentInfo : it.getEquipmentInfoList()) {
                    notBlank(errors, "project.stand", projectEquipmentInfo.getStand());
                    notBlank(errors, "quotation.elevatorMode", projectEquipmentInfo.getElevatorModel());
                    notBlank(errors, "project.equipmentType", projectEquipmentInfo.getEquipmentType());
                    notBlank(errors, "project.equipmentQuantity", projectEquipmentInfo.getEquipmentQuantityStr());
                    notBlank(errors, "project.amount", projectEquipmentInfo.getAmountStr());

                    maxLength(errors, "project.equipmentQuantity", projectEquipmentInfo.getEquipmentQuantityStr(), 8);
                    maxLength(errors, "project.amount", projectEquipmentInfo.getAmountStr(), 11);
                    maxLength(errors, "project.stand", projectEquipmentInfo.getStand(), 100);
                    maxLength(errors, "quotation.elevatorMode", projectEquipmentInfo.getElevatorModel(), 30);

                    // 设备类型
                    String equipmentTypeValue = intentionalProductMap.get(projectEquipmentInfo.getEquipmentType());
                    if (StringUtils.isBlank(equipmentTypeValue)) {
                        errors.add(MessageUtils.message("project.equipmentType")
                            + MessageUtils.message("excel.message.undefine"));
                    } else {
                        projectEquipmentInfo.setEquipmentTypeValue(equipmentTypeValue);
                    }
                    // // 梯形
                    // String elevatorTypeValue = elevatorTypeMap.get(projectEquipmentInfo.getElevatorModel());
                    // if (StringUtils.isBlank(elevatorTypeValue)) {
                    //     errors.add(MessageUtils.message("quotation.elevatorMode")
                    //         + MessageUtils.message("excel.message.undefine"));
                    // } else {
                    //     projectEquipmentInfo.setElevatorModelValue(elevatorTypeValue);
                    // }
                    try {
                        projectEquipmentInfo.setEquipmentQuantity(
                            Long.valueOf(projectEquipmentInfo.getEquipmentQuantityStr()));
                    } catch (Exception e) {
                        errors.add(MessageUtils.message("project.equipmentQuantity")
                            + MessageUtils.message("excel.message.illegalChar"));
                    }
                    try {
                        projectEquipmentInfo.setAmount(new BigDecimal(projectEquipmentInfo.getAmountStr()));
                    } catch (Exception e) {
                        errors.add(MessageUtils.message("project.amount")
                            + MessageUtils.message("excel.message.illegalChar"));
                    }

                    if (Objects.nonNull(projectEquipmentInfo.getEquipmentQuantity())
                        && projectEquipmentInfo.getEquipmentQuantity().compareTo(0L) <= 0) {
                        errors.add(MessageUtils.message("project.equipmentQuantity")
                            + MessageUtils.message("excel.message.zero"));
                    }
                    if (Objects.nonNull(projectEquipmentInfo.getAmount())
                        && projectEquipmentInfo.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                        errors.add(MessageUtils.message("project.amount")
                            + MessageUtils.message("excel.message.zero"));
                    }
                }
            }

            return errors;
        });
    }

    private boolean compareProjectName(String projectName, String a) {
        if (StringUtils.isAnyBlank(projectName, a)) {
            return false;
        }
        return projectName.equals(a);
    }

    private static void notBlank(List<String> businessErrors, String colName, Object obj) {
        String col = MessageUtils.message(colName);
        if (Objects.isNull(obj)) {
            businessErrors.add(col + MessageUtils.message("excel.message.notEmpty"));
        } else {
            if (obj instanceof String) {
                if (StringUtils.isBlank((String)obj)) {
                    businessErrors.add(col + MessageUtils.message("excel.message.notEmpty"));
                }
            }
        }
    }

    private static void maxLength(List<String> businessErrors, String colName, Object obj, Integer maxLength) {
        String col = MessageUtils.message(colName);
        // 非空时校验
        if (Objects.nonNull(obj)) {
            if (maxLength > 0 && obj.toString().length() > maxLength) {
                //                    result.add(colName + "长度不能大于" + maxLength);
                businessErrors.add(col + MessageUtils.message("excel.message.maxLength") + maxLength);
            }
        }
    }

    private static Map<String, String> getDictMap(List<SysDictData> list) {
        Map<String, String> map = new HashMap<>();
        if (CollUtil.isEmpty(list)) {
            return map;
        }
        for (SysDictData sysDictData : list) {
            map.put(sysDictData.getDictLabel(), sysDictData.getDictValue());
            map.put(sysDictData.getDictLabelUS(), sysDictData.getDictValue());
            map.put(sysDictData.getDictLabelRU(), sysDictData.getDictValue());
            map.put(sysDictData.getDictLabelES(), sysDictData.getDictValue());
        }
        return map;
    }

    private static List<ProjectFromInfo> getMerginList(List<ProjectFromInfo> list) {
        if (CollUtil.isNotEmpty(list)) {
            list = list.stream()
                .map(ProjectFromInfo::trimAll)
                .filter(TcProjectServiceImpl::filterNotBlank)
                .collect(Collectors.toList());
        }
        // 合并项目信息
        List<ProjectFromInfo> didList = new ArrayList<>();
        String lastProjectName = null;
        int lastIndex = 0;
        for (int i = 0; i < list.size(); i++) {
            ProjectFromInfo project = list.get(i);
            ProjectEquipmentInfo build = ProjectEquipmentInfo
                .builder()
                .stand(project.getStand())
                .elevatorModel(project.getElevatorModel())
                .equipmentType(project.getEquipmentType())
                .equipmentQuantityStr(project.getEquipmentQuantityStr())
                .amountStr(project.getAmountStr())
                .build();
            String projectName = list.get(i).getProjectName();
            // 首行必定不合并
            if (i == 0) {
                lastProjectName = list.get(i).getProjectName();
                ProjectFromInfo project1 = list.get(i);
                project1.setEquipmentInfoList(new ArrayList<>(Collections.singletonList(build)));
                didList.add(project1);
            } else {
                if (compare2ProjectName(lastProjectName, projectName)) {
                    didList.get(lastIndex).getEquipmentInfoList().add(build);
                } else {
                    lastProjectName = list.get(i).getProjectName();
                    ProjectFromInfo project1 = list.get(i);
                    project1.setEquipmentInfoList(new ArrayList<>(Collections.singletonList(build)));
                    didList.add(project1);
                    lastIndex = didList.size() - 1;
                }
            }
        }
        return didList;
    }

    private static boolean compare2ProjectName(String lastProjectName, String projectName) {
        if (StringUtils.isAnyBlank(lastProjectName, projectName)
            && (StringUtils.isNotBlank(lastProjectName) || StringUtils.isNotBlank(projectName))) {
            return false;
        }
        if (StringUtils.isAllBlank(lastProjectName, projectName)) {
            return true;
        }
        return lastProjectName.equals(projectName);
    }

    private static boolean filterNotBlank(ProjectFromInfo info) {
        Boolean result1 = StringUtils.isAllBlank(
            info.getCity(),
            info.getPlanDealMonth(),
            info.getOwner(),
            info.getProjectName(),
            info.getType(),
            info.getModelFlag(),
            info.getSegmentedMarket(),
            info.getAccountName(),
            info.getProgress(),
            info.getExpectedInstallStartDateStr(),
            info.getCurrency(),
            info.getAddress(),
            info.getKeyContactPerson(),
            info.getKeyContact(),
            info.getKeyEmail(),
            info.getKeyJobTitle(),
            info.getContactPerson(),
            info.getContact(),
            info.getJobTitle(),
            info.getEmail(),
            info.getSolution(),
            info.getSpecialRemark(),
            info.getRemark(),
            info.getStand(),
            info.getElevatorModel(),
            info.getEquipmentType(),
            info.getEquipmentQuantityStr(),
            info.getAmountStr()
        );
        return !result1;
    }

    @Override
    @Transactional
    public List<String> insertProjectImportExcel(BasicTableInfoHelper basicTableInfoHelper,
        List<ProjectFromInfo> projectList) {
        List<String> result = new ArrayList<>();
        for (ProjectFromInfo projectHelper : projectList) {
            TcProject tcProject = convert2Project(projectHelper);
            this.insertTcProject(tcProject, false);
        }
        return result;
    }

    @Override
    public List<TcProject> selectProjectListJDRQ() {
        return tcProjectMapper.selectProjectListJDRQ();
    }

    @Override
    public List<AgentProjectStatisticsVo> getAgentProjectStatisticsList(AgentProjectStatistics agentProjectStatistics) {
        if (StringUtils.isNotEmpty(agentProjectStatistics.getAccountName())) {
            agentProjectStatistics.setAccountName(agentProjectStatistics.getAccountName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
//        if (StringUtils.isNotEmpty(agentProjeagentProjectStatisticsctStatisticsVo.getAccountName())) {
//            agentProjectStatistics.setAccountName(agentProjectStatistics.getAccountName().replaceAll("%", "/%").replaceAll("_", "/_"));
//        }
        agentProjectStatistics.setPermissionChar(SecurityUtils.getPermissionCharIns());
        // 代理商销售经理的场合
        if (SecurityUtils.hasRole("agent_sales")) {
            agentProjectStatistics.setLoginUserId(SecurityUtils.getUserId());
            agentProjectStatistics.setPermission(SecurityUtils.getPermissionCharIns());
        }
        return tcProjectMapper.getAgentProjectStatisticsList(agentProjectStatistics);
    }

    @Override
    public List<AgentCompleteOrderVo> getAgentCompleteOrderList(AgentCompleteOrder agentCompleteOrder) {
        if (StringUtils.isNotEmpty(agentCompleteOrder.getCity())) {
            agentCompleteOrder.setCity(agentCompleteOrder.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        return tcProjectMapper.getAgentCompleteOrderList(agentCompleteOrder);
    }

    @Override
    public List<AccountCompleteOrderVo> getAccountCompleteOrderList(AgentCompleteOrder agentCompleteOrder) {
        if (StringUtils.isNotEmpty(agentCompleteOrder.getCity())) {
            agentCompleteOrder.setCity(agentCompleteOrder.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        if (StringUtils.isNotEmpty(agentCompleteOrder.getAccountName())) {
            agentCompleteOrder.setAccountName(agentCompleteOrder.getAccountName().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        return tcProjectMapper.getAccountCompleteOrderList(agentCompleteOrder);
    }

    @Override
    public List<AgentTargetProgressVo> getAgentTargetProgressList(AgentCompleteOrder agentCompleteOrder) {
        if (StringUtils.isNotEmpty(agentCompleteOrder.getCity())) {
            agentCompleteOrder.setCity(agentCompleteOrder.getCity().replaceAll("%", "/%").replaceAll("_", "/_"));
        }
        List<AgentTargetProgressVo> agentTargetProgressVoList = tcProjectMapper.getAgentTargetProgressList(agentCompleteOrder);
        for (AgentTargetProgressVo agentTargetProgressVo : agentTargetProgressVoList) {
            AgentTargetProgressVo agentCompleteOrder1 = new AgentTargetProgressVo();
            agentCompleteOrder1.setAgentId(agentTargetProgressVo.getAgentId());
            agentCompleteOrder1.setYearParam(agentCompleteOrder.getYearParam());
            agentCompleteOrder1.setTargetElevatorCount(agentTargetProgressVo.getTargetElevatorCount());
            List<AgentTargetProgressVo> listSub = tcProjectMapper.getAgentTargetProgressListSub(agentCompleteOrder1);
            agentTargetProgressVo.setAgentTargetProgressVoList(listSub);
        }
        return agentTargetProgressVoList;
    }

    private TcProject convert2Project(ProjectFromInfo helper) {
        TcProject project = new TcProject();
        project.setAccountId(helper.getAccountId());
        project.setAddress(helper.getAddress());
        project.setAreaId(helper.getAreaId());
        project.setCity(helper.getCity());
        // project.setCompletionYear(helper.getCompletionYearDate());
        project.setContact(helper.getContact());
        project.setCurrencyId(helper.getCurrencyValue());
        project.setContactPerson(helper.getContactPerson());
        project.setCountryId(helper.getCountryId());
        project.setEmail(helper.getEmail());
        project.setJobTitle(helper.getJobTitle());
        project.setKeyContact(helper.getKeyContact());
        project.setKeyContactPerson(helper.getKeyContactPerson());
        project.setKeyEmail(helper.getKeyEmail());
        project.setKeyJobTitle(helper.getKeyJobTitle());
        // project.setLeadIds();
        project.setModelFlag(helper.getModelFlagValue());
        project.setOwner(helper.getOwnerId());
        project.setOwnerAgent(helper.getAgentId());
        project.setPlanDealMonth(helper.getPlanDealMonthDate());
        project.setProgress(helper.getProgressValue());
        project.setExpectedInstallStartDate(helper.getExpectedInstallStartDate());
        // project.setStatus(helper.getStatusValue());
        project.setProjectName(helper.getProjectName());
        project.setRemark(helper.getRemark());
        project.setSegmentedMarket(helper.getSegmentedMarketValue());
        project.setSolution(helper.getSolution());
        project.setSpecialRemark(helper.getSpecialRemark());
        project.setType(helper.getTypeValue());
        List<ProjectEquipmentInfo> equipmentInfoList = helper.getEquipmentInfoList();
        if (CollUtil.isNotEmpty(equipmentInfoList)) {
            List<TcProjectEquipment> collect = equipmentInfoList.stream().map(item -> {
                TcProjectEquipment projectEquipment = new TcProjectEquipment();
                projectEquipment.setStandard(item.getStand());
                projectEquipment.setEquipmentQuantity(item.getEquipmentQuantity());
                projectEquipment.setEquipmentType(item.getEquipmentTypeValue());
                projectEquipment.setElevatorModel(item.getElevatorModel());
                projectEquipment.setAmount(item.getAmount());
                return projectEquipment;
            }).collect(Collectors.toList());
            project.setMachineList(collect);
        }
        return project;
    }

}
