package com.fjhx.sale.service.sale.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.account.controller.utils.DateUtils;
import com.fjhx.area.utils.CustomizeAreaUtil;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.common.enums.CodingRuleEnum;
import com.fjhx.common.enums.FlowStatusEnum1;
import com.fjhx.common.enums.PushBusinessTypeEnum;
import com.fjhx.common.service.coding.CodingRuleService;
import com.fjhx.common.service.corporation.CorporationService;
import com.fjhx.common.utils.Assert;
import com.fjhx.common.utils.Utils;
import com.fjhx.customer.entity.customer.dto.CustomerDto;
import com.fjhx.customer.entity.customer.dto.CustomerSelectDto;
import com.fjhx.customer.entity.customer.po.Customer;
import com.fjhx.customer.entity.customer.vo.CustomerVo;
import com.fjhx.customer.service.customer.CustomerService;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.sale.entity.contract.vo.ContractVo;
import com.fjhx.sale.entity.quotation.dto.QuotationProductBomDto;
import com.fjhx.sale.entity.quotation.dto.QuotationProductDto;
import com.fjhx.sale.entity.quotation.po.QuotationPay;
import com.fjhx.sale.entity.quotation.po.QuotationProduct;
import com.fjhx.sale.entity.quotation.po.QuotationProductBom;
import com.fjhx.sale.entity.quotation.vo.QuotationProductBomVo;
import com.fjhx.sale.entity.quotation.vo.QuotationProductVo;
import com.fjhx.sale.entity.sale.dto.SaleQuotationDto;
import com.fjhx.sale.entity.sale.dto.SaleQuotationSelectDto;
import com.fjhx.sale.entity.sale.po.SaleQuotation;
import com.fjhx.sale.entity.sale.vo.SaleQuotationVo;
import com.fjhx.sale.mapper.sale.SaleQuotationMapper;
import com.fjhx.sale.service.contract.ContractService;
import com.fjhx.sale.service.quotation.QuotationPayService;
import com.fjhx.sale.service.quotation.QuotationProductBomService;
import com.fjhx.sale.service.quotation.QuotationProductService;
import com.fjhx.sale.service.sale.SaleQuotationService;
import com.fjhx.sale.util.code.CodeEnum;
import com.fjhx.socket.core.PushTypeEnum;
import com.fjhx.socket.core.WebSocketPush;
import com.fjhx.tenant.entity.dict.vo.DictTenantDataVo;
import com.fjhx.tenant.service.dict.DictTenantDataService;
import com.fjhx.tenant.utils.DictUtils;
import com.ruoyi.common.core.domain.BasePo;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 报价表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-14
 */
@Service
public class SaleQuotationServiceImpl extends ServiceImpl<SaleQuotationMapper, SaleQuotation> implements SaleQuotationService {
    @Autowired
    private QuotationProductService quotationProductService;

    @Autowired
    private QuotationPayService quotationPayService;

    @Autowired
    private ContractService contractService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private DictTenantDataService dictTenantDataService;

    @Autowired
    private CodingRuleService codingRuleService;

    @Autowired
    private CorporationService corporationService;
    @Autowired
    private QuotationProductBomService quotationProductBomService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private ProductInfoService productInfoService;
    @Autowired
    private ISysUserService sysUserService;

    /**
     * 报价表分页
     */
    @Override
    public Page<SaleQuotationVo> getPage(SaleQuotationSelectDto dto) {

        IWrapper<SaleQuotation> wrapper = IWrapper.getWrapper();

        //权限过滤：报价评估自己看自己
        if (Objects.equals(dto.getIsEstimate(), 1)) {
            wrapper.eq("sq", SaleQuotation::getCompanyId, SecurityUtils.getCompanyId());
            wrapper.ne("sq", SaleQuotation::getStatus, FlowStatusEnum1.DRAFT.getKey());
        }

        //报价状态
        wrapper.eq(SaleQuotation::getQuotationStatus, dto.getQuotationStatus());
        //报价公司
        wrapper.eq(SaleQuotation::getCompanyId, dto.getCompanyId());
        //报价单类型
        wrapper.eq(SaleQuotation::getType, dto.getType());


        //报价时间-时间范围过滤
        wrapper.ge("sq", SaleQuotation::getQuotationTime, dto.getQuotationTimeSta());
        wrapper.le("sq", SaleQuotation::getQuotationTime, dto.getQuotationTimeEnd());
        //创建时间-时间范围过滤
        wrapper.ge("sq", SaleQuotation::getCreateTime, dto.getBeginTime());
        wrapper.le("sq", SaleQuotation::getCreateTime, dto.getEndTime());

        wrapper.ne("sq", SaleQuotation::getStatus, FlowStatusEnum1.UPDATE.getKey());
        wrapper.eq("sq", SaleQuotation::getStatus, dto.getStatus());


        //关键字过滤
        String keyword = dto.getKeyword();
        if (ObjectUtil.isNotEmpty(keyword)) {
            List<SysUser> userList = sysUserService.list(Wrappers.<SysUser>query().like("nick_name", dto.getKeyword()));
            List<Long> userIds = userList.stream().map(SysUser::getUserId).collect(Collectors.toList());
            wrapper.and(q -> q
                    .like("sq", SaleQuotation::getCode, dto.getKeyword())
                    .or()
                    .in("sq", SaleQuotation::getCreateUser, userIds)
            );
        }

        wrapper.orderByDesc(SaleQuotation::getCreateTime);

        Page<SaleQuotationVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        List<SaleQuotationVo> records = page.getRecords();

        if (ObjectUtil.isEmpty(records)) {
            return page;
        }

        // 赋值用户名称
        UserUtil.assignmentNickName(records, BasePo::getCreateUser, SaleQuotationVo::setUserName);
        // 赋值买方公司名称(客户)
        customerService.attributeAssign(records, SaleQuotationVo::getBuyCorporationId, (item, customer) -> {
            item.setBuyCorporationName(customer.getName());
        });


        List<Long> companyIds = records.stream().map(SaleQuotation::getCompanyId).collect(Collectors.toList());
        List<SysDept> companyList = sysDeptService.list(Wrappers.<SysDept>query().in("dept_id", companyIds));
        Map<Long, String> companyMap = companyList.stream().collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName));

        List<Long> ids = records.stream().map(SaleQuotationVo::getId).collect(Collectors.toList());
        List<QuotationProduct> pList = quotationProductService.list(q -> q.in(QuotationProduct::getSaleQuotationId, ids));
        List<QuotationProductVo> quotationPayVos = BeanUtil.copyToList(pList, QuotationProductVo.class);
        //赋值产品信息
        productInfoService.attributeAssign(quotationPayVos, QuotationProductVo::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCustomCode());
            item.setProductName(productInfo.getName());

            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductWidth(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());

        });
        Map<Long, List<QuotationProductVo>> pMap = quotationPayVos.stream().collect(Collectors.groupingBy(QuotationProduct::getSaleQuotationId));

        for (SaleQuotationVo saleQuotationVo : records) {
            //赋值报价公司名称
            saleQuotationVo.setCompanyName(companyMap.get(saleQuotationVo.getCompanyId()));

            //赋值产品列表
            saleQuotationVo.setQuotationProductList(pMap.get(saleQuotationVo.getId()));
        }


        return page;
    }

    @Override
    @DSTransactional
    public void add(SaleQuotationDto saleQuotationDto) {
        //添加报价编码
        if (ObjectUtil.isEmpty(saleQuotationDto.getCode())) {
            saleQuotationDto.setCode(codingRuleService.createCode(CodingRuleEnum.SALE_QUOTATION.getKey(), saleQuotationDto.getBuyCorporationId()));
        }

        if (ObjectUtil.isEmpty(saleQuotationDto.getCompanyId())) {
            saleQuotationDto.setCompanyId(SecurityUtils.getCompanyId());
        }

        long id = IdWorker.getId();
        saleQuotationDto.setId(id);
        saleQuotationDto.setGroupId(id);//赋值数据分组id
        if (ObjectUtil.isEmpty(saleQuotationDto.getStatus())) {
            saleQuotationDto.setStatus(30);//默认审批通过
        }
        saleQuotationDto.setQuotationStatus(0);//报价状态未报价
        saveOrEdit(saleQuotationDto);

        //消息推送：给归属公司的 子公司总经理
        JSONObject msg = new JSONObject();
        msg.put("business_id", saleQuotationDto.getId());
        List<Long> generalManagerIds = UserUtil.getUserIdsByRoleKey("subsidiary_gm", saleQuotationDto.getCompanyId());
        for (Long generalManagerId : generalManagerIds) {
            WebSocketPush.byUser(PushTypeEnum.MESSAGE, generalManagerId,
                    "您有新的报价单待报价，请尽快处理！",
                    PushBusinessTypeEnum.NEW_QUOTATION.getType(),
                    msg.toString());
        }

    }

    @Override
    @DSTransactional
    public void edit(SaleQuotationDto saleQuotationDto) {
        if (Objects.equals(saleQuotationDto.getQuotationStatus(), 2)) {
            saleQuotationDto.setQuotationTime(new Date());
        }
        saveOrEdit(saleQuotationDto);
    }

    /**
     * 变更
     */
    @Override
    public void changeSaleQuotation(SaleQuotationDto saleQuotationDto) {
        SaleQuotation saleQuotation = this.getById(saleQuotationDto.getId());
        if (ObjectUtil.isEmpty(saleQuotation)) {
            throw new ServiceException("查询不到原报价单信息");
        }
        saleQuotation.setStatus(FlowStatusEnum1.UPDATE.getKey());
        this.updateById(saleQuotation);

        saleQuotationDto.setOldQuotationId(saleQuotation.getId());

        //变更清除id信息
        saleQuotationDto.setId(null);
        saleQuotationDto.setBackRemark(null);
        saleQuotationDto.setStatus(30);
        saleQuotationDto.setQuotationStatus(0);
        saleQuotationDto.setCode(Utils.getNewCode(saleQuotation.getCode()));//赋值新合同号
        List<QuotationProductDto> quotationProductList = saleQuotationDto.getQuotationProductList();
        for (QuotationProductDto quotationProductDto : quotationProductList) {
            quotationProductDto.setId(null);
            List<QuotationProductBomDto> quotationProductBomList = quotationProductDto.getQuotationProductBomList();
            for (QuotationProductBomDto quotationProductBomDto : quotationProductBomList) {
                quotationProductBomDto.setId(null);
            }
            quotationProductDto.setQuotationProductBomList(quotationProductBomList);
        }
        saleQuotationDto.setQuotationProductList(quotationProductList);
        //调用创建方法
        saveOrEdit(saleQuotationDto);
    }

    /**
     * 作废
     */
    @Override
    public void cancellation(Long id) {
        SaleQuotation saleQuotation = this.getById(id);
        saleQuotation.setStatus(FlowStatusEnum1.CANCELLATION.getKey());
        this.updateById(saleQuotation);
    }

    /**
     * 添加修改公共方法
     */
    private void saveOrEdit(SaleQuotationDto saleQuotationDto) {
        this.saveOrUpdate(saleQuotationDto);

        List<QuotationProductDto> quotationProductList = saleQuotationDto.getQuotationProductList();
        if (ObjectUtil.isNotEmpty(quotationProductList)) {
            for (QuotationProductDto quotationProductDto : quotationProductList) {
                //手动创建id
                if (ObjectUtil.isEmpty(quotationProductDto.getId())) {
                    quotationProductDto.setId(IdWorker.getId());
                }
                quotationProductDto.setSaleQuotationId(saleQuotationDto.getId());

                //保存配件
                List<QuotationProductBom> quotationProductBomList = BeanUtil.copyToList(quotationProductDto.getQuotationProductBomList(), QuotationProductBom.class);
                for (QuotationProductBom quotationProductBom : quotationProductBomList) {
                    quotationProductBom.setProductId(quotationProductDto.getProductId());
                    quotationProductBom.setQuotationProductId(quotationProductDto.getId());
                }
                quotationProductBomService.editLinked(quotationProductBomList, QuotationProductBom::getQuotationProductId, quotationProductDto.getId());
            }

            List<QuotationProduct> quotationProducts = BeanUtil.copyToList(quotationProductList, QuotationProduct.class);
            quotationProductService.editLinked(quotationProducts, QuotationProduct::getSaleQuotationId, saleQuotationDto.getId());
        }
    }

    /**
     * 报价表明细
     */
    @Override
    public SaleQuotationVo detail(Long id) {
        //查询报价表详情
        SaleQuotation saleQuotation = this.getById(id);
        SaleQuotationVo result = BeanUtil.toBean(saleQuotation, SaleQuotationVo.class);
        if (ObjectUtil.isEmpty(result)) {
            throw new ServiceException("查询不到明细信息请检查");
        }

        //获取归属公司信息
        SysDept sysDept = sysDeptService.getById(result.getCompanyId());
        if (ObjectUtil.isNotEmpty(sysDept)) {
            result.setCompanyName(sysDept.getDeptName());
        }

        return setDetailInfo(Arrays.asList(result)).get(0);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }

    /**
     * 获取报价单历史版本
     */
    @Override
    public List<SaleQuotationVo> getVersionList(Long saleQuotationId) {
        SaleQuotation saleQuotation = this.getById(saleQuotationId);
        Assert.notEmpty(saleQuotation, "查询不到报价单信息！");
        Long groupId = saleQuotation.getGroupId();
        List<SaleQuotation> saleQuotationList = this.list(q -> q.eq(SaleQuotation::getGroupId, groupId).orderByDesc(SaleQuotation::getCreateTime));
        List<SaleQuotationVo> saleQuotationVos = BeanUtil.copyToList(saleQuotationList, SaleQuotationVo.class);
        return setDetailInfo(saleQuotationVos);
    }

    /**
     * 赋值明细信息
     */
    private List<SaleQuotationVo> setDetailInfo(List<SaleQuotationVo> saleQuotationVos) {
        Long groupId = saleQuotationVos.get(0).getGroupId();

        //获取id列表
        List<Long> ids = saleQuotationVos.stream().map(SaleQuotation::getId).collect(Collectors.toList());
        //获取子产品列表
        List<QuotationProduct> productList = quotationProductService.list(q -> q.in(QuotationProduct::getSaleQuotationId, ids));
        List<QuotationProductVo> quotationProductVos = BeanUtil.copyToList(productList, QuotationProductVo.class);
        Map<Long, List<QuotationProductVo>> productMap = quotationProductVos.stream().collect(Collectors.groupingBy(QuotationProductVo::getSaleQuotationId));
        //赋值产品信息
        productInfoService.attributeAssign(quotationProductVos, QuotationProductVo::getProductId, (item, productInfo) -> {
            item.setProductCode(productInfo.getCustomCode());
            item.setProductName(productInfo.getName());
            item.setProductLength(productInfo.getLength());
            item.setProductWidth(productInfo.getWidth());
            item.setProductHeight(productInfo.getHeight());
            item.setProductColor(productInfo.getColor());
        });
        //获取配件列表
        List<Long> qpIds = productList.stream().map(QuotationProduct::getId).collect(Collectors.toList());
        Map<Long, List<QuotationProductBomVo>> qpbMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(qpIds)) {
            List<QuotationProductBom> bomList = quotationProductBomService.list(q -> q.in(QuotationProductBom::getQuotationProductId, qpIds));
            List<QuotationProductBomVo> quotationProductBomVos = BeanUtil.copyToList(bomList, QuotationProductBomVo.class);
            //赋值产品信息
            productInfoService.attributeAssign(quotationProductBomVos, QuotationProductBom::getMaterialId, (item, productInfo) -> {
                item.setProductCode(productInfo.getCustomCode());
                item.setProductName(productInfo.getName());
                item.setProductLength(productInfo.getLength());
                item.setProductWidth(productInfo.getWidth());
                item.setProductHeight(productInfo.getHeight());
                item.setProductColor(productInfo.getColor());
            });
            qpbMap = quotationProductBomVos.stream().collect(Collectors.groupingBy(QuotationProductBom::getQuotationProductId));
        }

        //赋值客户信息
        customerService.attributeAssign(saleQuotationVos, SaleQuotation::getBuyCorporationId, (item, customer) -> {
            item.setBuyCorporationName(customer.getName());
        });

        //获取地址信息
        List<Long> areaIdList = new ArrayList<>();
        for (SaleQuotation quotation : saleQuotationVos) {
            areaIdList.add(quotation.getBuyCountryId());
            areaIdList.add(quotation.getBuyProvinceId());
            areaIdList.add(quotation.getBuyCityId());
        }
        areaIdList = areaIdList.stream().distinct().collect(Collectors.toList());
        Map<Long, String> areaMap = CustomizeAreaUtil.getAreaMapByIds(areaIdList);

        //获取报价金额趋势
        List<SaleQuotation> quotationTrendList = this.list(q -> q
                .eq(SaleQuotation::getGroupId, groupId)
                .ne(SaleQuotation::getStatus, FlowStatusEnum1.CANCELLATION.getKey())
                .orderByAsc(SaleQuotation::getCreateTime)
        );

        //赋值信息
        for (SaleQuotationVo quotation : saleQuotationVos) {
            //赋值买方地址
            quotation.setBuyCountryName(areaMap.get(quotation.getBuyCountryId()));
            quotation.setBuyProvinceName(areaMap.get(quotation.getBuyProvinceId()));
            quotation.setBuyCityName(areaMap.get(quotation.getBuyCityId()));
            quotation.setBuyDetailedAddress(quotation.getBuyAddress());

            //赋值产品列表
            List<QuotationProductVo> quotationProductVos1 = productMap.getOrDefault(quotation.getId(), new ArrayList<>());
            for (QuotationProductVo quotationProductVo : quotationProductVos1) {
                //赋值配件列表
                quotationProductVo.setQuotationProductBomList(qpbMap.get(quotationProductVo.getId()));
            }
            quotation.setQuotationProductList(quotationProductVos1);

            //获取报价金额趋势
            quotation.setQuotationTrendList(quotationTrendList);
        }

        return saleQuotationVos;

    }

    //==================================================================================================================

    /**
     * 报价单的复制功能（报价单，报价-商品表的 ，报价-收费项目表，根据报价表的ID相关数据复制一份）
     */
    @Override
    public void copy(SaleQuotationDto saleQuotationDto) {
        if (ObjectUtil.isEmpty(saleQuotationDto.getId())) {
            throw new ServiceException("参数缺失：报价单ID不能为null");
        }
        //查询商品-报价表的数据
        SaleQuotation saleQuotation = this.getById(saleQuotationDto.getId());
        if (ObjectUtil.isNotEmpty(saleQuotation)) {
            throw new ServiceException("报价表的数据不存在");
        }

        //查询报价-商品表的数据
        List<QuotationProduct> quotationProductList = quotationProductService.list(Wrappers.<QuotationProduct>lambdaQuery()
                .eq(QuotationProduct::getSaleQuotationId, saleQuotationDto.getId()));

        //查询报价-收费项目表
        List<QuotationPay> quotationPays = quotationPayService.list(Wrappers.<QuotationPay>lambdaQuery()
                .eq(QuotationPay::getSaleQuotationId, saleQuotationDto.getId()));

        //添加商品-报价表
        quotationProductList.forEach(quotationProduct -> quotationProduct.setId(null));
        quotationProductService.saveBatch(quotationProductList);

        //添加报价-收费项目表
        quotationPays.forEach(quotationPay -> quotationPay.setId(null));
        quotationPayService.saveBatch(quotationPays);


        //添加报价表的信息
        saleQuotation.setId(null);
        saleQuotation.setCode(CodeEnum.SALE_QUOTATION.getCode());
        baseMapper.insert(saleQuotation);

    }

    /**
     * 查询这个客户的报价次数
     *
     * @param id （客户ID）
     */
    @Override
    public Integer getCount(Long id) {
        return baseMapper.getCount(id);
    }

    /**
     * 查询指定客户的每月报价总额
     *
     * @param dto
     * @return
     */
    @Override
    public List<SaleQuotationVo> getAmount(CustomerDto dto) {
        return baseMapper.getAmount(dto);
    }

    /**
     * 最新跟进（客户画像）
     */
    @Override
    public Page<SaleQuotationVo> latestFollowUp(CustomerSelectDto dto) {
        Page<SaleQuotationVo> saleQuotationVoPage = baseMapper.latestFollowUp(
                dto.getPage(),
                IWrapper.getWrapper().orderByDesc("create_time"),
                dto.getId(),
                SecurityUtils.getTenantId()
        );

        return saleQuotationVoPage;
    }

    /**
     * 销售统计（客户画像）
     */
    @Override
    public Map<String, Object> salesStatistics(SaleQuotationSelectDto dto) {
        Map<String, Object> map = new HashMap<>();
        //切换数据源
//        DynamicDataSourceContextHolder.push(SourceConstant.SALE);
        //查询这个客户的销售额（合同总金额）及成交合同数量
        ContractVo contractVo = contractService.getSalesTotal(dto.getId());
        map.put("contractVo", contractVo);
        Page<ContractVo> page = contractService.getSalesTotalList(dto.getPage(), dto.getId());
        List<ContractVo> contractVoList = page.getRecords();
        // 赋值用户名称
        UserUtil.assignmentNickName(contractVoList, BasePo::getCreateUser, ContractVo::setUserName);
        // 赋值买方公司名称(客户)
        customerService.attributeAssign(contractVoList, ContractVo::getBuyCorporationId, (item, customer) -> {
            item.setBuyCorporationName(customer.getName());
        });
        //赋值归属公司
        corporationService.attributeAssign(contractVoList, ContractVo::getSellCorporationId, (item, corporation) -> {
            item.setSellCorporationName(corporation.getName());
        });
        map.put("contractList", page);
        //查询这个客户的报价次数
        Integer count = this.getCount(dto.getId());
//        DynamicDataSourceContextHolder.poll();
        map.put("count", count);
        return map;
    }

    /**
     * 报价销售走势（客户画像）
     */
    @Override
    public Map<String, Object> salesTrend(CustomerDto dto) {
        Map<String, Object> map = new HashMap<>();

        List<String> monthBetweenDate = DateUtils.getMonthBetweenDate(DateUtil.offsetMonth(new Date(), -12), new Date());

        //存放报价的数据；
        List<Map<String, Object>> saleQuotationList = new ArrayList<>();
        //存放报价的数据；
        List<Map<String, Object>> contractList = new ArrayList<>();

        dto.setBeginTime(DateUtil.format(DateUtil.offsetMonth(new Date(), -12), "yyyy-MM"));
        dto.setEndTime(DateUtil.format(new Date(), "yyyy-MM"));
        //查询指定客户的每月报价总额
        List<SaleQuotationVo> saleQuotationVoList = this.getAmount(dto);

        Map<String, List<SaleQuotationVo>> saleQuotationVoMap = saleQuotationVoList.stream()
                .collect(Collectors.groupingBy(SaleQuotationVo::getTime));

        //查询指定客户的每月合同总额
        List<ContractVo> contractVoList = contractService.getAmount(dto);
        Map<String, List<ContractVo>> contractVoMap = contractVoList.stream()
                .collect(Collectors.groupingBy(ContractVo::getTime));

        //赋值每个月的值
        for (String month : monthBetweenDate) {
            //存放每月的报价总额
            Map<String, Object> saleQuotationMap = new HashMap<>();
            //每月的金额初始化的值为0
            saleQuotationMap.put("month", month);
            saleQuotationMap.put("saleAmount", new BigDecimal(0));
            List<SaleQuotationVo> saleQuotationVos = saleQuotationVoMap.get(month);
            //给每月的报价金额赋值
            if (ObjectUtil.isNotEmpty(saleQuotationVos)) {
                saleQuotationMap.put("saleAmount", saleQuotationVos.get(0).getAmount());
            }
            saleQuotationList.add(saleQuotationMap);

            //存放每月的合同总额
            Map<String, Object> contractMap = new HashMap<>();
            //每月的金额初始化的值为0
            contractMap.put("month", month);
            contractMap.put("contractAmount", new BigDecimal(0));
            List<ContractVo> contractVoList1 = contractVoMap.get(month);
            if (ObjectUtil.isNotEmpty(contractVoList1)) {
                contractMap.put("contractAmount", contractVoList1.get(0).getAmount());
            }
            contractList.add(contractMap);
        }
        map.put("contractList", contractList);
        map.put("saleQuotationList", saleQuotationList);
        return map;
    }

    /**
     * 销售明细（客户画像）
     */
    @Override
    public Page<SaleQuotationVo> saleDetail(CustomerSelectDto dto) {
        IWrapper<SaleQuotation> wrapper = IWrapper.getWrapper();
        wrapper.eq("t1", SaleQuotation::getBuyCorporationId, dto.getId());
        wrapper.eq("t1.status", FlowStatusEnum1.PASS.getKey());
        wrapper.orderByDesc("t1", SaleQuotation::getCreateTime);
        Page<SaleQuotationVo> saleQuotationVoPage = baseMapper.saleDetail(dto.getPage(), wrapper);
        List<SaleQuotationVo> records = saleQuotationVoPage.getRecords();
        // 赋值用户名称
        UserUtil.assignmentNickName(records, SaleQuotationVo::getCreateUser, SaleQuotationVo::setUserName);

        return saleQuotationVoPage;
    }

    /**
     * 来源统计（客户分析）
     */
    @Override
    public Map<String, Object> sourceStatistics(CustomerDto dto) {
        //切换数据源
//        DynamicDataSourceContextHolder.push(SourceConstant.CUSTOMER);
        //存放来源统计的数据
        Map<String, Object> map = new HashMap<>();

        //存放来源存量与增量的数据列表
        List<Map<String, Object>> stockList = new ArrayList<>();


        //来源存量（在指定时间外的数量）
        QueryWrapper<Object> query = Wrappers.query();
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.groupBy("c.source");
        query.le("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getBeginTime());
        query.ge("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getEndTime());
        List<CustomerVo> sourceStockList = customerService.sourceStock(query);

        //来源增量（在指定时间内的数量）
        query.clear();
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.groupBy("c.source");
        query.ge("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getBeginTime());
        query.le("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getEndTime());
        List<CustomerVo> sourceIncrementList = customerService.sourceIncrement(query);

//        DynamicDataSourceContextHolder.poll();

        //切换数据源
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        //获取来源的字典数据
        List<DictTenantDataVo> dictTenantDataVos = DictUtils.getDictList("customer_source");
        DynamicDataSourceContextHolder.poll();
        //获取来源增量总计
        Integer incrementAmount = sourceIncrementList.stream().map(customerVo -> customerVo.getCount())
                .collect(Collectors.toList()).stream().reduce(Integer::sum).orElse(0);
        map.put("incrementAmount", incrementAmount);
        //获取来源存量总计
        Integer stockAmount = sourceStockList.stream().map(customerVo -> customerVo.getCount())
                .collect(Collectors.toList()).stream().reduce(Integer::sum).orElse(0);
        map.put("stockAmount", stockAmount);

        Map<String, List<CustomerVo>> sourceIncrementMap = sourceIncrementList.stream()
                .collect(Collectors.groupingBy(CustomerVo::getSource));

        Map<String, List<CustomerVo>> sourceStockMap = sourceStockList.stream().collect(Collectors.groupingBy(Customer::getSource));

        if (dictTenantDataVos.size() == 0) {
            throw new ServiceException("数据有误：该租户没有配客户来源字典");
        }

        //赋值 增量 存量数据
        for (DictTenantDataVo dictTenantDataVo : dictTenantDataVos) {
            //存放来源存量与增量的数据
            Map<String, Object> stockMap = new HashMap<>();
            //赋值初使值
            stockMap.put("source", dictTenantDataVo.getDictValue());
            stockMap.put("stockAmount", 0);
            stockMap.put("incrementAmount", 0);

            //赋值增量数据
            List<CustomerVo> customers = sourceIncrementMap.get(dictTenantDataVo.getDictKey());
            if (ObjectUtil.isNotEmpty(customers)) {
                stockMap.put("incrementAmount", customers.get(0).getCount());
            }
            //赋值存量数据
            List<CustomerVo> customerVos = sourceStockMap.get(dictTenantDataVo.getDictKey());
            if (ObjectUtil.isNotEmpty(customerVos)) {
                stockMap.put("stockAmount", customerVos.get(0).getCount());
            }
            stockList.add(stockMap);
        }
        map.put("stockList", stockList);

        return map;
    }

    /**
     * 类型统计（客户分析）
     */
    @Override
    public Map<String, Object> typeStatistics(CustomerDto dto) {
        if (ObjectUtil.isEmpty(dto.getBeginTime()) && ObjectUtil.isNotEmpty(dto.getEndTime())) {
            throw new ServiceException("参数缺失：开始时间，结束时间不能为null");
        }
        //存放类型统计数据
        Map<String, Object> map = new HashMap<>();

        //存放询盘数据 成交单的列表
        List<Map<String, Object>> saleList = new ArrayList<>();

        QueryWrapper<Object> query = Wrappers.query();
        query.ge("DATE_FORMAT(sq.create_time,'%Y-%m')", dto.getBeginTime());
        query.le("DATE_FORMAT(sq.create_time,'%Y-%m')", dto.getEndTime());
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.eq("sq.status", 30);

        //获取类型的字典数据
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        List<DictTenantDataVo> dictTenantDataVoList = DictUtils.getDictList("customer_status");

        if (dictTenantDataVoList.size() == 0) {
            throw new ServiceException("数据有误：该租户没有配客户类型字典");
        }

        //赋值询盘 成交单数据
        for (DictTenantDataVo dictTenantDataVo : dictTenantDataVoList) {
            //存放询盘数据 成交单的数据
            Map<String, Object> saleMap = new HashMap<>();
            //赋值初使值
            saleMap.put("status", dictTenantDataVo.getDictValue());
            saleMap.put("contractAmount", 0);
            saleMap.put("saleAmount", 0);
            saleList.add(saleMap);
        }
        map.put("saleList", saleList);
        return map;
    }

    /**
     * 趋势分析（客户分析）
     */
    @Override
    public Map<String, Object> trendAnalysis(CustomerDto dto) {
        Map<String, Object> map = new HashMap<>();
        //切换数据源
//        DynamicDataSourceContextHolder.push(SourceConstant.CUSTOMER);

        Date now = new Date();
        //获取当前月数往前12月的月份数
        List<String> monthBetweenDate = DateUtils.getMonthBetweenDate(DateUtil.offsetMonth(now, -12), now);
        dto.setBeginTime(DateUtil.format(DateUtil.offsetMonth(now, -12), "yyyy-MM"));
        dto.setEndTime(DateUtil.format(now, "yyyy-MM"));
        //来源存量（在指定时间外的数量）
        QueryWrapper<Object> query = Wrappers.query();
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.groupBy("DATE_FORMAT(c.create_time,'%Y-%m')");
        query.le("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getBeginTime());
        query.ge("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getEndTime());
//        query.select("count(*) count, DATE_FORMAT(c.create_time,'%Y-%m') time");
        List<CustomerVo> sourceStockList = customerService.sourceStock(query);
        Map<String, List<CustomerVo>> sourceStockMap = sourceStockList.stream().collect(Collectors.groupingBy(CustomerVo::getTime));

        //来源增量（在指定时间内的数量）
        query.clear();
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.groupBy("DATE_FORMAT(c.create_time,'%Y-%m')");
        query.ge("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getBeginTime());
        query.le("DATE_FORMAT(c.create_time,'%Y-%m')", dto.getEndTime());
//        query.select("count(*) count, DATE_FORMAT(c.create_time,'%Y-%m') time");
        List<CustomerVo> sourceIncrementList = customerService.sourceIncrement(query);
        Map<String, List<CustomerVo>> sourceIncrementMap = sourceIncrementList.stream().collect(Collectors.groupingBy(CustomerVo::getTime));
//        DynamicDataSourceContextHolder.poll();

        query.clear();
        query.ge("DATE_FORMAT(sq.create_time,'%Y-%m')", dto.getBeginTime());
        query.le("DATE_FORMAT(sq.create_time,'%Y-%m')", dto.getBeginTime());
        query.eq(ObjectUtil.isNotEmpty(dto.getCountryId()), "c.country_id", dto.getCountryId());
        query.eq(ObjectUtil.isNotEmpty(dto.getProvinceId()), "c.province_id", dto.getProvinceId());
        query.eq(ObjectUtil.isNotEmpty(dto.getCityId()), "c.city_id", dto.getCityId());
        query.eq("sq.status", 30);
        query.groupBy("DATE_FORMAT(sq.create_time,'%Y-%m')");
//        query.select("count(*), DATE_FORMAT(sq.create_time,'%Y-%m') time");
        //类型询盘统计（报价）
        List<SaleQuotationVo> saleStatisticsList = baseMapper.saleStatistics(query);
        Map<String, List<SaleQuotationVo>> saleStatisticsMap = saleStatisticsList.stream()
                .collect(Collectors.groupingBy(SaleQuotationVo::getTime));

        //查询成交单统计（合同）
        List<SaleQuotationVo> contractStatisticsList = contractService.contractStatistics(query);
        Map<String, List<SaleQuotationVo>> contractStatisticsMap = contractStatisticsList.stream()
                .collect(Collectors.groupingBy(SaleQuotationVo::getTime));

        //存放来源存量
        List<Map<String, Object>> sourceStockList1 = new ArrayList<>();
        //存放来源增量
        List<Map<String, Object>> sourceIncrementList1 = new ArrayList<>();
        //存放类型询盘
        List<Map<String, Object>> saleStatisticList1 = new ArrayList<>();
        //类型成交单
        List<Map<String, Object>> contractStatisticsList1 = new ArrayList<>();

        //赋值
        for (String month : monthBetweenDate) {
            //存放来源存量
            Map<String, Object> stockMap = new HashMap<>();
            //设置默认值
            stockMap.put("month", month);
            stockMap.put("count", 0);
            List<CustomerVo> sourceStocks = sourceStockMap.get(month);
            if (ObjectUtil.isNotEmpty(sourceStocks)) {
                stockMap.put("count", sourceStocks.get(0).getCount());
            }
            sourceStockList1.add(stockMap);

            //存放来源增量
            Map<String, Object> incrementMap = new HashMap<>();
            //设置默认值
            incrementMap.put("month", month);
            incrementMap.put("count", 0);
            List<CustomerVo> sourceIncrements = sourceIncrementMap.get(month);
            if (ObjectUtil.isNotEmpty(sourceIncrements)) {
                incrementMap.put("count", sourceIncrements.get(0).getCount());
            }
            sourceIncrementList1.add(incrementMap);

            //类型询盘
            Map<String, Object> saleMap = new HashMap<>();
            //设置默认值
            saleMap.put("month", month);
            saleMap.put("count", 0);
            List<SaleQuotationVo> saleList = saleStatisticsMap.get(month);
            if (ObjectUtil.isNotEmpty(saleList)) {
                saleMap.put("count", saleList.get(0).getCount());
            }
            saleStatisticList1.add(saleMap);

            //类型成交单
            Map<String, Object> contractMap = new HashMap<>();
            //设置默认值
            contractMap.put("month", month);
            contractMap.put("count", 0);
            List<SaleQuotationVo> contractList = contractStatisticsMap.get(month);
            if (ObjectUtil.isNotEmpty(contractList)) {
                contractMap.put("count", contractList.get(0).getCount());
            }
            contractStatisticsList1.add(contractMap);
        }
        map.put("sourceStockList", sourceStockList1);
        map.put("sourceIncrementList", sourceIncrementList1);
        map.put("saleStatisticList", saleStatisticList1);
        map.put("contractStatisticsList", contractStatisticsList1);
        return map;
    }

//    /**
//     * 赋值买卖公司地址
//     */
//    private void setArea(SaleQuotationVo saleQuotationVo) {
//
//        List<Long> areaIdList = Arrays.asList(
//                saleQuotationVo.getBuyCountryId(),
//                saleQuotationVo.getBuyProvinceId(),
//                saleQuotationVo.getBuyCityId()
//        );
//        Map<Long, String> areaMap = CustomizeAreaUtil.getAreaMapByIds(areaIdList);
//        saleQuotationVo.setBuyCountryName(areaMap.get(saleQuotationVo.getBuyCountryId()));
//        saleQuotationVo.setBuyProvinceName(areaMap.get(saleQuotationVo.getBuyProvinceId()));
//        saleQuotationVo.setBuyCityName(areaMap.get(saleQuotationVo.getBuyCityId()));
//        saleQuotationVo.setBuyDetailedAddress(saleQuotationVo.getBuyAddress());
//    }


}
