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

import java.io.File;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.base.Functions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruoyi.common.enums.FileBuzType;
import com.ruoyi.common.enums.SerialNumberPrefix;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.office.doc.CommonDocUtils;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.project.business.domain.*;
import com.ruoyi.project.business.domain.bo.TqContractBo;
import com.ruoyi.project.business.domain.bo.contract.TqContractLiftBo;
import com.ruoyi.project.business.domain.flow.Flow;
import com.ruoyi.project.business.domain.flow.FlowAuditParam;
import com.ruoyi.project.business.domain.vo.contract.TqContractDto;
import com.ruoyi.project.business.domain.vo.contract.TqContractLiftVo;
import com.ruoyi.project.business.domain.vo.contract.TqContractVo;
import com.ruoyi.project.business.domain.vo.currency.ContractCurrencyTime;
import com.ruoyi.project.business.domain.vo.quotation.QuotationVO;
import com.ruoyi.project.business.dto.ContractSigningStatistic;
import com.ruoyi.project.business.dto.LiftCount;
import com.ruoyi.project.business.dto.LiftMonthCount;
import com.ruoyi.project.business.dto.TaskGenerateParams;
import com.ruoyi.project.business.enums.AuditFlowEnum;
import com.ruoyi.project.business.mapper.TbCountryMapper;
import com.ruoyi.project.business.mapper.TbFileMapper;
import com.ruoyi.project.business.mapper.contract.TqContractLiftHistoryMapper;
import com.ruoyi.project.business.mapper.contract.TqContractLiftMapper;
import com.ruoyi.project.business.mapper.contract.TqContractMapper;
import com.ruoyi.project.business.service.ITbContractCurrencyService;
import com.ruoyi.project.business.service.ITbFileService;
import com.ruoyi.project.business.service.ITqContractHistoryService;
import com.ruoyi.project.business.service.flow.IFlowService;
import com.ruoyi.project.system.domain.SysDictData;
import com.ruoyi.project.system.mapper.SysDictDataMapper;
import fr.opensagres.xdocreport.document.images.FileImageProvider;
import fr.opensagres.xdocreport.template.formatter.NullImageBehaviour;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import com.ruoyi.project.business.service.ITqContractService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import static com.ruoyi.common.utils.DateUtils.getMonthEnd;
import static com.ruoyi.common.utils.DateUtils.getMonthStart;
import static com.ruoyi.common.utils.DecimalUtils.add;
import static com.ruoyi.project.business.enums.AuditFlowEnum.*;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.commons.lang3.StringUtils.isBlank;

/**
 * 合同列表Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-08-13
 */
@Service
public class TqContractServiceImpl implements ITqContractService 
{
    @Resource
    private TqContractMapper tqContractMapper;
    @Resource
    private RedisCache redisCache;
    @Resource
    private TbFileMapper tbFileMapper;

    @Resource
    private TqContractLiftMapper tqContractLiftMapper;

    @Resource
    private ITbFileService tbFileService;

    @Resource
    private ITqContractHistoryService tqContractHistoryService;

    @Resource
    IFlowService flowService;

    @Resource
    SysDictDataMapper sysDictDataMapper;

    public static final String APPROVE_STATUS_SUCCESS = "2";

    public static final String GENERATE_TASKS_FLAG = "1";
    @Resource
    TqContractLiftHistoryMapper tqContractLiftHistoryMapper;

    @Resource
    TbCountryMapper tbCountryMapper;

    @Resource
    ITbContractCurrencyService tbContractCurrencyService;

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

    /**
     * 查询合同列表
     * 
     * @param id 合同列表主键
     * @return 合同列表
     */
    @Override
    public TqContract selectTqContractById(Long id)
    {
        return tqContractMapper.selectTqContractById(id);
    }

    public TqContractVo getContractById(Long id){
        TqContractBo tqContractBo = new TqContractBo();
        tqContractBo.setId(id);
        TqContractVo returnTqContractBo = tqContractMapper.selectTqContractBoListApp(tqContractBo).get(0);

        //查询字典returnTqContractBo


        List<TbFile> annex = tbFileService.list(Wrappers.<TbFile>lambdaQuery().eq(TbFile::getBusinessId, id)
                .eq(TbFile::getBusinessType, FileBuzType.CONTRACT.getType()));
        if (nonNull(tqContractBo)) {
            returnTqContractBo.setFile(annex.stream().map(TbFile::getFilePath).collect(Collectors.joining(",")));
        } else {
            throw new ServiceException(MessageUtils.message("common.dataDeleted"));
        }
        return returnTqContractBo;

    }

    /**
     * 查询合同列表列表
     * 
     * @param tqContract 合同列表
     * @return 合同列表
     */
    @Override
    public List<TqContract> selectTqContractList(TqContract tqContract)
    {
        return tqContractMapper.selectTqContractList(tqContract);
    }

    public List<TqContractVo> selectTqContractBoList(TqContractBo tqContract){
        List<TqContractVo> tqContractVoList = tqContractMapper.selectTqContractBoList(tqContract);
        if(CollectionUtils.isNotEmpty(tqContractVoList)){
            List<Long> collect = tqContractVoList.stream().map(TqContractVo::getId)
                    .collect(Collectors.toList());
            Map<Long, Flow> flowMap = flowService.getFlowMap(collect, Arrays.asList(CONTRACT_FINANCE_YES, CONTRACT_FINANCE_NO));
            tqContractVoList.forEach(item -> {
                item.setFlow(flowMap.get(item.getId()));
            });
        }
        return tqContractVoList;
    }
    @Override
    public List<TqContractVo> selectTqContractBoListApp(TqContractBo tqContract){
        return tqContractMapper.selectTqContractBoListApp(tqContract);
    }
    /**
     * 新增合同列表
     * 
     * @param tqContractDto 合同列表
     * @return 结果
     */
    @Override
    @Transactional
    public int insertTqContract(TqContractDto tqContractDto)
    {
        //补充创建日期和权限
        tqContractDto.setCreateTime(DateUtils.getNowDate());
        tqContractDto.setPermissionChar(SecurityUtils.getPermissionCharIns());
        //获取国家缩写
        TbCountry tbCountry = tbCountryMapper.selectTbCountryByCountryId(tqContractDto.getCountryId());
        if(ObjectUtils.isEmpty(tbCountry)){
            throw new ServiceException("未找到该国家的信息！");
        }
        //将前缀和国家信息补充完整
        String contractNo = redisCache.generateSerialNumberNew(SerialNumberPrefix.C.getPrefix(), tbCountry.getCountryAbbr());
        tqContractDto.setContractNo(contractNo);
        //根据币种获取签单时币种汇率
        List<ContractCurrencyTime> contractCurrencyTimeList = new ArrayList<>();
        contractCurrencyTimeList.add(new ContractCurrencyTime(
                Long.valueOf(tqContractDto.getCurrencyId()),
                tqContractDto.getSigningDate()
        ));
        Map<Long, BigDecimal> idAndRateMap = tbContractCurrencyService.selectExchangeRateByCurrencyId(contractCurrencyTimeList);
        //将签单币种汇率赋值
        if(idAndRateMap.containsKey(Long.parseLong(tqContractDto.getCurrencyId()))){
            tqContractDto.setRate4SigningContracts(idAndRateMap.get((Long.parseLong(tqContractDto.getCurrencyId()))));
        }
        //将合同的
        tqContractMapper.insertTqContract(tqContractDto);
        //附件上传
        tbFileService.saveOrUpdateFile(tqContractDto.getFile(),tqContractDto.getId(),FileBuzType.CONTRACT.getType());
        // 梯形 子表   采用批量导入的形式
        List<TqContractLift> tqContractLiftList = tqContractDto.getTqContractLiftList();
        if(CollectionUtils.isNotEmpty(tqContractLiftList)){
            //补充完整信息
            tqContractLiftList = attachTqContractLift(tqContractDto,tqContractLiftList);
            tqContractLiftMapper.insertTqContractLiftBatch(tqContractLiftList);
        }
        //生成对应审批流
        this.generateTasks(tqContractDto);
        return 1;
    }

    /**
     * 修改合同列表
     * 
     * @param tqContractDto 合同列表
     * @return 结果
     */
    @Override
    @Transactional
    public int updateTqContract(TqContractDto tqContractDto)
    {
        List<TqContractLift> tqContractLiftList = tqContractDto.getTqContractLiftList();
        if(CollectionUtils.isNotEmpty(tqContractLiftList)){
            //获取设备更新List
            List<TqContractLift> tqContractLiftUpdateList = tqContractLiftList.stream().filter(item-> item.getId() != null).collect(Collectors.toList());
            List<Long> idList = tqContractLiftUpdateList.stream().map(item->item.getId()).collect(Collectors.toList());
            //删除当前合同下不存在的设备番号
            if(CollectionUtils.isNotEmpty(idList)){
                tqContractLiftMapper.deleteTqContractLiftByNoId(tqContractDto.getContractNo(),idList);
            }
            if(CollectionUtils.isNotEmpty(tqContractLiftUpdateList)){
                tqContractLiftUpdateList = attachTqContractLift(tqContractDto,tqContractLiftUpdateList);
                tqContractLiftMapper.updateTqContractLiftBatch(tqContractLiftUpdateList);
            }
            //获取设备新增List
            List<TqContractLift> tqContractLiftAddList = tqContractLiftList.stream().filter(item-> item.getId() == null).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(tqContractLiftAddList)){
                tqContractLiftAddList = attachTqContractLift(tqContractDto,tqContractLiftAddList);
                tqContractLiftMapper.insertTqContractLiftBatch(tqContractLiftAddList);
            }
        }
        tqContractDto.setUpdateTime(DateUtils.getNowDate());
        if(tqContractDto.getNeedFileFlag() != null && "1".equals(tqContractDto.getNeedFileFlag())){
            //附件上传
            tbFileService.saveOrUpdateFile(tqContractDto.getFile(), tqContractDto.getId(),FileBuzType.CONTRACT.getType());
        }

        //附件上传完毕后  新增履历表(存在履历信息就上传履历表)
        if(ObjectUtils.isNotEmpty(tqContractDto.getTqContractHistory())){
            tqContractHistoryService.insertTqContractHistory(tqContractDto.getTqContractHistory());
        }
        //在合同变更或者编辑页面操作的   （设备的审批流要重新恢复到status的初始状态）audit_status
        this.generateTasks(tqContractDto);

        return tqContractMapper.updateTqContract(tqContractDto);
    }



    private void generateTasks(TqContractDto tqContractDto){
        //付款方式是信用证  || 付款比例不是是30/70  走财务流程
        AuditFlowEnum contract = null;
        contract = "1".equals(tqContractDto.getPaymentMethod()) || !"1".equals(tqContractDto.getPaymentRatio())? CONTRACT_FINANCE_YES : CONTRACT_FINANCE_NO;
        //判断是不是变更或者编辑界面操作的数据
        if(GENERATE_TASKS_FLAG.equals(tqContractDto.getGenerateTasksFlag())){
            flowService.generateTasks(
                    new TaskGenerateParams(contract, tqContractDto, SecurityUtils.getUserId(),
                            tqContractDto.getContractNo()));
        }
    }
    private void updateFlow(TqContract tqContract){
        FlowAuditParam taskGenerateParams = new FlowAuditParam();
        taskGenerateParams.setAuditFlow(3L);
        taskGenerateParams.setBusinessId(tqContract.getId());
        taskGenerateParams.setStatus(0);
        taskGenerateParams.setRemark("重新审批");
        flowService.audit(taskGenerateParams);
    }

     /**
      * @Author Chenj
      * @Description 将合同信息补充完整
      * @Date 9:13 2024/8/21
      **/
    private List<TqContractLift>  attachTqContractLift(TqContractDto tqContractDto, List<TqContractLift>  tqContractLiftList){
        //根据实际排产日期查询汇率
        List<ContractCurrencyTime> scheduleList = tqContractLiftList.stream()
                .filter(tqContractLift -> tqContractLift.getSigningDate() != null) // Filter out null signing dates
                .map(tqContractLift -> new ContractCurrencyTime(
                        Long.parseLong(tqContractLift.getCurrencyId()), // Assuming this returns a long
                        tqContractLift.getActualProductionScheduleDate()
                ))
                .collect(Collectors.toList());
        Map<Long, BigDecimal> scheduleListIdAndRateMap = tbContractCurrencyService.selectExchangeRateByCurrencyId(scheduleList);
        //根据实际发货排产日期查询汇率
        List<ContractCurrencyTime> deliveryList = tqContractLiftList.stream()
                .filter(tqContractLift -> tqContractLift.getSigningDate() != null) // Filter out null signing dates
                .map(tqContractLift -> new ContractCurrencyTime(
                        Long.parseLong(tqContractLift.getCurrencyId()), // Assuming this returns a long
                        tqContractLift.getActualDeliveryDate()
                ))
                .collect(Collectors.toList());
        Map<Long, BigDecimal> deliveryListIdAndRateMap = tbContractCurrencyService.selectExchangeRateByCurrencyId(deliveryList);

        //获取版本
        Long version = tqContractLiftHistoryMapper.selectVersionMaxFromHistory(tqContractDto.getContractNo());
        String contractNoVersionNo = version == null ? "1": String.valueOf(version+1L);
        tqContractLiftList.forEach(item -> {
            item.setContractNo(tqContractDto.getContractNo());
            item.setContractName(tqContractDto.getContractName());
            item.setAreaId(tqContractDto.getAreaId());
            item.setCountryId(tqContractDto.getCountryId());
            item.setCity(tqContractDto.getCity());
            item.setSalesman(tqContractDto.getSalesman());
            item.setSalesModel(tqContractDto.getSalesModel());
            item.setEndCustomers(tqContractDto.getEndCustomers());
            item.setTradeTerms(tqContractDto.getTradeTerms());
            item.setAgentId(tqContractDto.getAgentId());
            item.setPaymentMethod(tqContractDto.getPaymentMethod());
            item.setAmountOfMoney(tqContractDto.getAmount());
            item.setSigningDate(tqContractDto.getSigningDate());
            item.setContractAmendmentDate(new Date());
            item.setPaymentRatio(tqContractDto.getPaymentRatio());
            item.setContractNoVersionNo(tqContractDto.getContractNo()+"-"+contractNoVersionNo);
            item.setPermissionChar(SecurityUtils.getPermissionCharIns());
            item.setRate4SigningContracts(tqContractDto.getRate4SigningContracts());
            //将签单币种汇率赋值
            if(scheduleListIdAndRateMap.containsKey(Long.parseLong(item.getCurrencyId()))){
                item.setRate4ProductionScheduling(scheduleListIdAndRateMap.get(Long.parseLong(item.getCurrencyId())));
            }
            if(deliveryListIdAndRateMap.containsKey(Long.parseLong(item.getCurrencyId()))){
                item.setRate4Shipment(deliveryListIdAndRateMap.get(Long.parseLong(item.getCurrencyId())));
            }
        });
        return tqContractLiftList;
    }



    /**
     * 批量删除合同列表
     * 
     * @param ids 需要删除的合同列表主键
     * @return 结果
     */
    @Override
    public int deleteTqContractByIds(Long[] ids)
    {
        return tqContractMapper.deleteTqContractByIds(ids);
    }

    /**
     * 删除合同列表信息
     * 
     * @param id 合同列表主键
     * @return 结果
     */
    @Override
    public int deleteTqContractById(Long id)
    {
        return tqContractMapper.deleteTqContractById(id);
    }

    @Transactional
    @Override
    public void exportContract(Long id){
        //1.获取基础数据
        //1.1合同
        TqContract tqContract = this.getContractById(id);
        List<JSONObject> contractLift = Lists.newArrayList();
        //1.2电梯
        TqContractLiftBo tqContractLiftBo = new TqContractLiftBo();
        tqContractLiftBo.setContractNo(tqContract.getContractNo());
        List<TqContractLiftVo> tqContractLiftList = tqContractLiftMapper.selectTqContractLiftList(tqContractLiftBo);
        //货币单位
        SysDictData sysDictData =  sysDictDataMapper.selectSysDictDataByTypeAndValue("currency_type",tqContract.getCurrencyId());
        if(ObjectUtils.isEmpty(sysDictData) && StringUtils.isEmpty(sysDictData.getRemark())){
            throw new ServiceException("未找到该合同的单位");
        }
        String currencyUnit =  String.valueOf(sysDictData.getRemark().charAt(sysDictData.getRemark().length() - 1));

        // 2. 转换数据格式
        int i = 1;
        BigDecimal totalPrice = new BigDecimal(BigDecimal.ROUND_UP);
        for (TqContractLiftVo item : tqContractLiftList) {
            JSONObject data = new JSONObject();
            data.put("index",i);
            data.put("elevatorSpecifie", item.getProjectName()+item.getSpecification());
            data.put("unitPrice",currencyUnit + item.getUnitPrice());
            data.put("count",item.getCount());
            data.put("elvPrice",currencyUnit + item.getUnitPrice().multiply(BigDecimal.valueOf(item.getCount())));
            totalPrice  = totalPrice.add(item.getUnitPrice().multiply(BigDecimal.valueOf(item.getCount())));
            contractLift.add(data);
            i++;
        }
        Map<String, Object> map = Maps.newHashMap();
        map.put("buyers",tqContract.getContractName());
        map.put("address",tqContract.getAddress());
        map.put("telephone",tqContract.getShippingMark());
        map.put("totalPrice",currencyUnit +totalPrice);
        map.put("email",tqContract.getEmail());
        map.put("destinationPort",tqContract.getDestinationPort());
        map.put("shippingMark",tqContract.getShippingMark());
        map.put("shipmentPort",tqContract.getShipmentPort());
        map.put("shipmentDeadline", DateUtils.parseDateToStr("yyyy-MM-dd", tqContract.getShipmentDeadline()));
        map.put("contractLift", contractLift);


//        String path = CollectionUtils.isNotEmpty(previewList) ? RuoYiConfig.getProfile() + StringUtils.substringAfter(previewList.get(0).getFilePath(), Constants.RESOURCE_PREFIX): "/null";
//        FileImageProvider file = new FileImageProvider(new File(path), true);
        //只有审核通过的才会盖章
        if(APPROVE_STATUS_SUCCESS.equals(tqContract.getApproveStatus())){
            String path = "src/main/resources/wordTemplate/章.png";
            FileImageProvider file = new FileImageProvider(new File(path), true);
            file.setBehaviour(NullImageBehaviour.RemoveImageTemplate);
            file.setWidth(100f);
            file.setResize(true);
            map.put("photoSeal", file);
        }

        // 3. 填充模板并返回
        new CommonDocUtils()
                .loadFromClasspath("/wordTemplate/国际部销售合同模版2024.docx")
                .replaceData(map)
                .downloadDocx();

    }

    @Override
    public ContractSigningStatistic contractSigningStatistic(TqContractDto params) {
        String begin = params.getBeginTime();
        String end = params.getEndTime();
        if (isBlank(begin) || isBlank(end)) {
            throw new ServiceException("时间范围不能为空");
        }

        ContractSigningStatistic result = new ContractSigningStatistic();
        int year = DateUtils.getYear(end);
        result.setYear(year);
        result.setWeek(DateUtils.getWeekNumber(end));
        // 1. 各区域本周、月电梯（签单、排产、发货）数量统计
        List<LiftCount> weekCountList = tqContractLiftMapper.countStatistic(begin, end);
        List<LiftCount> monthCountList = tqContractLiftMapper.countStatistic(getMonthStart(end), getMonthEnd(end));
        result.setWeekCountList(weekCountList);
        weekCountList.forEach(count -> {
            result.setWeekSignCountTotal(add(result.getWeekSignCountTotal(), count.getSignCount()));
            result.setWeekProductionCountTotal(add(result.getWeekProductionCountTotal(), count.getProductionCount()));
            result.setWeekDeliveryCountTotal(add(result.getWeekDeliveryCountTotal(), count.getDeliveryCount()));
        });
        monthCountList.forEach(count -> {
            result.setMonthSignCountTotal(add(result.getMonthSignCountTotal(), count.getSignCount()));
            result.setMonthProductionCountTotal(add(result.getMonthProductionCountTotal(), count.getProductionCount()));
            result.setMonthDeliveryCountTotal(add(result.getMonthDeliveryCountTotal(), count.getDeliveryCount()));
        });

        // 2. 全年月度（签单、排产、发货）数量统计
        List<LiftCount> monthCountListAll = tqContractLiftMapper.countStatisticByMonthAll(year);
        result.setMonthCountListAll(monthCountListAll);
        monthCountListAll.forEach(count -> {
            result.setMonthSignCountTotalAll(add(result.getMonthSignCountTotalAll(), count.getSignCount()));
            result.setMonthProductionCountTotalAll(add(result.getMonthProductionCountTotalAll(), count.getProductionCount()));
            result.setMonthDeliveryCountTotalAll(add(result.getMonthDeliveryCountTotalAll(), count.getDeliveryCount()));
        });

        // 3. 全年周（签单、排产、发货）数量统计
        List<LiftCount> weekCountListAll = tqContractLiftMapper.countStatisticByWeekAll(year);
        result.setWeekCountListAll(weekCountListAll);
        weekCountListAll.forEach(count -> {
            result.setWeekSignCountTotalAll(add(result.getWeekSignCountTotalAll(), count.getSignCount()));
            result.setWeekProductionCountTotalAll(add(result.getWeekProductionCountTotalAll(), count.getProductionCount()));
            result.setWeekDeliveryCountTotalAll(add(result.getWeekDeliveryCountTotalAll(), count.getDeliveryCount()));
        });

        // 4. 全年各区域签约金额
        List<LiftMonthCount> signingAmountAll = tqContractLiftMapper.countSigningStatisticAll(year);
        result.setSigningAreaColStatistics(getAreaColList(signingAmountAll));
        // 5. 全年各区域排产金额
        List<LiftMonthCount> productionAmountAll = tqContractLiftMapper.countProductionStatisticAll(year);
        result.setProductionAreaColStatistics(getAreaColList(productionAmountAll));
        // 6. 全年各区域发货金额
        List<LiftMonthCount> deliveryAmountAll = tqContractLiftMapper.countDeliveryStatisticAll(year);
        result.setDeliveryMonthColStatistics(getMonthColList(deliveryAmountAll));
        // 7. 全年各区域排产金额
        result.setProductionMonthColStatistics(getMonthColList(productionAmountAll));

        return result;
    }

    private List<List<String>> getAreaColList(List<LiftMonthCount> amountAll) {
        List<List<String>> result = Lists.newArrayList();
        if (CollectionUtils.isEmpty(amountAll)){
            return result;
        }

        List<String> areaColHeader = Lists.newArrayList("月份");
        result.add(areaColHeader);

        // 底部区域合计行
        List<String> areaSum = Lists.newArrayList("总计");
        amountAll.forEach(item -> {
            areaColHeader.add(item.getKey());
            // 1. 添加各区域每月的数据
            for (int i = 1; i <= 12; i++) {
                List<String> monthAreaCount;
                if (i < result.size()){
                    monthAreaCount = result.get(i);
                } else {
                    monthAreaCount = Lists.newArrayList(i + "月");
                    result.add(monthAreaCount);
                }
                BigDecimal current = BigDecimal.ZERO;
                switch (i) {
                    case 1:
                        current = item.getJanuary();
                        break;
                    case 2:
                        current = item.getFebruary();
                        break;
                    case 3:
                        current = item.getMarch();
                        break;
                    case 4:
                        current = item.getApril();
                        break;
                    case 5:
                        current = item.getMay();
                        break;
                    case 6:
                        current = item.getJune();
                        break;
                    case 7:
                        current = item.getJuly();
                        break;
                    case 8:
                        current = item.getAugust();
                        break;
                    case 9:
                        current = item.getSeptember();
                        break;
                    case 10:
                        current = item.getOctober();
                        break;
                    case 11:
                        current = item.getNovember();
                        break;
                    case 12:
                        current = item.getDecember();
                        break;
                }
                monthAreaCount.add(MONEY.format(current));
            }
            // 区域合计
            BigDecimal areaTotal = item.getJanuary()
                    .add(item.getFebruary())
                    .add(item.getMarch())
                    .add(item.getApril())
                    .add(item.getMay())
                    .add(item.getJune())
                    .add(item.getJuly())
                    .add(item.getAugust())
                    .add(item.getSeptember())
                    .add(item.getOctober())
                    .add(item.getNovember())
                    .add(item.getDecember());;
            areaSum.add(MONEY.format(areaTotal));
        });
        result.add(areaSum);

        // 2. 添加右侧合计列
        areaColHeader.add("合计");
        for (int i = 1; i < result.size(); i++) {
            List<String> row = result.get(i);
            BigDecimal total = BigDecimal.ZERO;
            for (int j = 1; j < row.size(); j++) {
                total = total.add(new BigDecimal(row.get(j).replaceAll(",", "")));
            }
            row.add(MONEY.format(total));
        }

        return result;
    }

    private List<List<String>> getMonthColList(List<LiftMonthCount> amountAll) {
        List<List<String>> result = Lists.newArrayList();
        if (CollectionUtils.isEmpty(amountAll)){
            return result;
        }
        List<String> header = Lists.newArrayList("月份", "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月", "合计", "占比");
        result.add(header);

        List<BigDecimal> sum = Lists.newArrayList();
        amountAll.forEach(item -> {
            // 1. 添加各区域每月的数据
            List<BigDecimal> list = Lists.newArrayList(item.getJanuary(), item.getFebruary(), item.getMarch(), item.getApril(), item.getMay(),
                    item.getJune(), item.getJuly(), item.getAugust(), item.getSeptember(), item.getOctober(), item.getNovember(),
                    item.getDecember());
            BigDecimal total = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
            List<String> row = Lists.newArrayList(item.getKey());
            list.forEach(amount -> row.add(MONEY.format(amount)));
            row.add(MONEY.format(total));
            list.add(total);

            // 2. 计算底部合计
            for (int i = 0; i < list.size(); i++) {
                if (sum.size() < list.size()){
                    sum.add(list.get(i));
                } else {
                    sum.set(i, DecimalUtils.add(sum.get(i), list.get(i)));
                }
            }

            result.add(row);
        });
        List<String> footer = Lists.newArrayList("合计");
        footer.addAll(sum.stream().map(amount -> MONEY.format(amount)).collect(Collectors.toList()));
        result.add(footer);

        // 3. 计算各区域比重
        BigDecimal total = sum.get(sum.size() - 1);
        for (int i = 1; i < result.size() - 1; i++) {
            List<String> row = result.get(i);
            BigDecimal ratio = new BigDecimal(row.get(row.size() - 1).replaceAll(",", EMPTY)).multiply(new BigDecimal(100)).divide(total, 2, BigDecimal.ROUND_HALF_UP);
            row.add(ratio.toString() + "%");
        }
        return result;
    }
}
