package com.artfess.yhxt.contract.manager.impl;


import com.artfess.base.context.BaseContext;
import com.artfess.base.query.*;
import com.artfess.poi.util.ExcelUtil;
import com.artfess.workflow.runtime.manager.IFlowManager;
import com.artfess.yhxt.contract.dao.BillOfQuantitiesDao;
import com.artfess.yhxt.contract.dao.WorkOrderInformationDao;
import com.artfess.yhxt.contract.manager.ContractManager;
import com.artfess.yhxt.contract.manager.WorkOrderExportManager;
import com.artfess.yhxt.contract.manager.WorkOrderInformationManager;
import com.artfess.yhxt.contract.model.BillOfQuantities;
import com.artfess.yhxt.contract.model.ContractItem;
import com.artfess.yhxt.contract.model.WorkOrderInformation;
import com.artfess.yhxt.contract.vo.ContractVo;
import com.artfess.yhxt.contract.vo.WorkOrderContractVo;
import com.artfess.yhxt.contract.vo.WorkOrderParamVo;
import com.artfess.yhxt.util.PoiStyleUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zhx
 * @create 2022/6/7
 */
@Service
public class WorkOrderExportManagerImpl implements WorkOrderExportManager {
    @Resource
    private ContractManager contractManager;
    @Resource
    private WorkOrderInformationManager workOrderInformationManager;
    @Resource
    private BillOfQuantitiesDao billOfQuantitiesDao;
    @Resource
    private IFlowManager iFlowManager;
    @Resource
    private BaseContext baseContext;
    @Resource
    private WorkOrderInformationDao workOrderInformationDao;


    /**
     * 工程(中期计量、完工结算)清单表 -已办工单
     * @param param
     * @param response
     * @throws Exception
     */
    @Override
    public void exportWorkOrdersConstruction(WorkOrderParamVo param, HttpServletResponse response) throws Exception {
        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //日常养护合同下的
        List<ContractItem> itemList = contractVo.getItemList();
        //工单清单
        List<WorkOrderInformation> orders = workOrderInformationManager.getWorkOrderContract(contractId, param);

        List<String> orderIds = orders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());


        List<String> ids = getConstructionOrderIds(orderIds);

        if (null ==ids || ids.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }

        List<WorkOrderInformation> workOrders = workOrderInformationDao.selectBatchIds(ids);




        setSheelInfoAndExport(response, contractId, contractVo, itemList, workOrders);
        return;

    }


    /**
     * 获得已办工单id
     * @param orderIds
     * @return
     * @throws Exception
     */
    private List<String> getConstructionOrderIds(List<String> orderIds) throws Exception {
        QueryFilter filter = QueryFilter.build();
        PageBean pageBean = new PageBean();
        pageBean.setPage(1);
        pageBean.setPageSize(-1);


        filter.setPageBean(pageBean);


        filter.addFilter("wfInst.biz_key_", orderIds, QueryOP.IN, FieldRelation.AND);

        filter.addFilter("type_id_", "1425741173624016896", QueryOP.IN, FieldRelation.AND);
        PageList<Map<String, Object>> mapPageList = iFlowManager.getDoneInstList(baseContext.getCurrentUserAccout(), filter, null).get();


        List<Map<String, Object>> rows = mapPageList.getRows();


        ArrayList<String> ids = new ArrayList<>();

        if (rows.size() > 0) {
            for (Map<String, Object> row : rows) {
                //procDefKey
                Object procDefKey = row.get("procDefKey");
                if (procDefKey.toString().equals("yhgd")) {
                    //业务主键
                    Object bizKey = row.get("bizKey");
                    if (ObjectUtils.isNotEmpty(bizKey)) {

                        ids.add(bizKey.toString());
                    }
                }
            }
        }

        return ids;
    }

    @Override
    public void exportWorkOrders(WorkOrderParamVo param, HttpServletResponse response) throws Exception {



        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //日常养护合同下的
        List<ContractItem> itemList = contractVo.getItemList();
        //工单清单
        List<WorkOrderInformation> workOrders = workOrderInformationManager.getWorkOrderContract(contractId, param);


        setSheelInfoAndExport(response, contractId, contractVo, itemList, workOrders);
        return;

    }


    /**
     * 设置样式导出 工程(中期计量、完工结算)清单
     * @param response
     * @param contractId
     * @param contractVo
     * @param itemList
     * @param workOrders
     * @throws IOException
     */
    private void setSheelInfoAndExport(HttpServletResponse response, String contractId, ContractVo contractVo, List<ContractItem> itemList, List<WorkOrderInformation> workOrders) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        //标题样式
        HSSFCellStyle cellStyleTitle = workbook.createCellStyle();
        //内容样式1
        HSSFCellStyle cellStyle1 = workbook.createCellStyle();
        //内容样式2
        HSSFCellStyle cellStyle2 = workbook.createCellStyle();
        //内容样式3
        HSSFCellStyle cellStyle3 = workbook.createCellStyle();
        HSSFCellStyle cellStyle4 = workbook.createCellStyle();
        PoiStyleUtil.setWorkOrderStyleTitle(cellStyleTitle, workbook);
        PoiStyleUtil.setWorkOrderCellStyle1(cellStyle1, workbook);
        PoiStyleUtil.setWorkOrderCellStyle2(cellStyle2, workbook);
        PoiStyleUtil.setWorkOrderCellStyle3(cellStyle3, workbook);
        PoiStyleUtil.setWorkOrderCellStyle4(cellStyle4, workbook);
        Integer num = 0;
        HSSFSheet sheet = workbook.createSheet("工程量汇总表");
        sheet.getPrintSetup().setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);
        //设置横向
        sheet.getPrintSetup().setLandscape(true);
        sheet.setColumnWidth(0, 5 * 256);
        sheet.setColumnWidth(1, 10 * 256);
        sheet.setColumnWidth(2, 5 * 256);
        sheet.setColumnWidth(3, 10 * 256);
        sheet.setColumnWidth(4, 5 * 256);
        sheet.setColumnWidth(5, 5 * 256);
        sheet.setColumnWidth(6, 5 * 256);
        sheet.setColumnWidth(7, 5 * 256);
        sheet.setColumnWidth(8, 5 * 256);
        sheet.setColumnWidth(9, 5 * 256);
        sheet.setColumnWidth(10, 5 * 256);
        sheet.setColumnWidth(11, 5 * 256);
        sheet.setColumnWidth(12, 5 * 256);
        sheet.setColumnWidth(13, 5 * 256);
        sheet.setColumnWidth(14, 5 * 256);
        sheet.setColumnWidth(15, 5 * 256);
        sheet.setColumnWidth(16, 8 * 256);
        sheet.setColumnWidth(17, 8 * 256);
        sheet.setColumnWidth(18, 8 * 256);
        sheet.setColumnWidth(19, 8 * 256);
        sheet.setColumnWidth(20, 8 * 256);


        List<String> workOrderIds = workOrders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());
        if (null ==workOrderIds || workOrderIds.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");}

        List<BillOfQuantities> billOfQuantities = billOfQuantitiesDao.listBillOfQuantities(workOrderIds);
        List<WorkOrderContractVo> workOrderContractVos = new ArrayList<WorkOrderContractVo>();
        itemList.forEach(s -> {

            billOfQuantities.forEach(a -> {
                if (s.getFineSubjectName().equals(a.getFineSubjectName()) && "".equals(s.getSonSubjectName())) {
                    WorkOrderContractVo vo = new WorkOrderContractVo();
                    vo.setIdContract(s.getId());
                    vo.setCodeContract(s.getCode());
                    vo.setSubjectNameContract(s.getSubjectName());
                    vo.setFineSubjectCodeContract(s.getFineSubjectCode());
                    vo.setFineSubjectNameContract(s.getFineSubjectName());
                    vo.setSonSubjectCodeContract(s.getSonSubjectCode());
                    vo.setSonSubjectNameContract(s.getSonSubjectName());
                    vo.setSpecContract(s.getSpec());
                    vo.setPriceContract(s.getPrice());
                    vo.setAmountContract(s.getAmount());
                    vo.setMontyContract(s.getMonty());
                    vo.setContractId(contractId);

                    vo.setIdBill(a.getId());
                    vo.setNumberBill(a.getNumber());
                    vo.setSubjectNameBill(a.getSubjectName());
                    vo.setFineSubjectCodeBill(a.getFineSubjectCode());
                    vo.setFineSubjectNameBill(a.getFineSubjectName());
                    vo.setSonSubjectCodeBill(a.getSonSubjectCode());
                    vo.setSonSubjectNameBill(a.getSonSubjectName());
                    vo.setAuditPriceBill(a.getAuditPrice());
                    vo.setAuditAmountBill(a.getAuditAmount());
                    vo.setAuditMoneyBill(a.getAuditMoney());
                    workOrderContractVos.add(vo);
                }
                if (s.getSonSubjectName().equals(a.getSonSubjectName()) && !"".equals(s.getSonSubjectName())) {
                    WorkOrderContractVo vo = new WorkOrderContractVo();
                    vo.setIdContract(s.getId());
                    vo.setCodeContract(s.getCode());
                    vo.setSubjectNameContract(s.getSubjectName());
                    vo.setFineSubjectCodeContract(s.getFineSubjectCode());
                    vo.setFineSubjectNameContract(s.getFineSubjectName());
                    vo.setSonSubjectCodeContract(s.getSonSubjectCode());
                    vo.setSonSubjectNameContract(s.getSonSubjectName());
                    vo.setSpecContract(s.getSpec());
                    vo.setPriceContract(s.getPrice());
                    vo.setAmountContract(s.getAmount());
                    vo.setMontyContract(s.getMonty());
                    vo.setContractId(contractId);


                    vo.setIdBill(a.getId());
                    vo.setNumberBill(a.getNumber());
                    vo.setSubjectNameBill(a.getSubjectName());
                    vo.setFineSubjectCodeBill(a.getFineSubjectCode());
                    vo.setFineSubjectNameBill(a.getFineSubjectName());
                    vo.setSonSubjectCodeBill(a.getSonSubjectCode());
                    vo.setSonSubjectNameBill(a.getSonSubjectName());
                    vo.setAuditPriceBill(a.getAuditPrice());
                    vo.setAuditAmountBill(a.getAuditAmount());
                    vo.setAuditMoneyBill(a.getAuditMoney());
                    workOrderContractVos.add(vo);
                }
            });

        });


        for (WorkOrderContractVo workOrderContractVo : workOrderContractVos) {
            itemList.removeIf(s -> workOrderContractVo.getIdContract().equals(s.getId()));
        }
        itemList.forEach(s -> {
            WorkOrderContractVo vo = new WorkOrderContractVo();
            vo.setIdContract(s.getId());
            vo.setCodeContract(s.getCode());
            vo.setSubjectNameContract(s.getSubjectName());
            vo.setFineSubjectCodeContract(s.getFineSubjectCode());
            vo.setFineSubjectNameContract(s.getFineSubjectName());
            vo.setSonSubjectCodeContract(s.getSonSubjectCode());
            vo.setSonSubjectNameContract(s.getSonSubjectName());
            vo.setSpecContract(s.getSpec());
            vo.setPriceContract(s.getPrice());
            vo.setAmountContract(s.getAmount());
            vo.setMontyContract(s.getMonty());
            vo.setContractId(contractId);
            workOrderContractVos.add(vo);
        });


        Map<String, List<WorkOrderContractVo>> collect = workOrderContractVos.stream().collect(Collectors.groupingBy(WorkOrderContractVo::getSonSubjectCodeContract));
        ArrayList<List<WorkOrderContractVo>> lists = new ArrayList<>();
        for (String key : collect.keySet()) {
            List<WorkOrderContractVo> vos = collect.get(key);
            if ("".equals(key)) {
                Map<String, List<WorkOrderContractVo>> listMap = vos.stream().collect(Collectors.groupingBy(WorkOrderContractVo::getSonSubjectCodeContract));
                for (String keyFine : listMap.keySet()) {
                    List<WorkOrderContractVo> e = listMap.get(keyFine);
                    lists.add(e);
                }
            } else {
                lists.add(vos);
            }
        }
        List<List<List<WorkOrderContractVo>>> listListWorkOrderContract = Stream.iterate(0, f -> f + 1).limit((lists.size() + 3) / 4).parallel().map(a -> lists.stream().skip(a * 4).limit(4).parallel().collect(Collectors.toList())).collect(Collectors.toList());


        for (int i = 0; i < listListWorkOrderContract.size(); i++) {
            sheetStyleAndValue(sheet, cellStyleTitle, num, 0, "中国铁建昆仑集团重庆运营总部工程(中期计量/完工结算)清单表");
            sheetSetHight(sheet, num, 69);
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 20));
            num++;
            sheetStyleAndValue(sheet, cellStyle1, num, 0, "本工程计量期数：第（ ）期                                                                                       金额单位：元");
            for (int a = 1; a <= 20; a++) {
                sheetStyleAndValue(sheet, cellStyle1, num, a,"");
            }
            sheetSetHight(sheet, num, 20);
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 20));
            num++;
            sheetStyleAndValue(sheet, cellStyle1, num, 0, "工程名称（承包合同号/项目编号）：");
            for (int a = 1; a <=15; a++) {
                sheetStyleAndValue(sheet, cellStyle1, num, a, "");
            }
            for (int a = 17; a <=20; a++) {
                sheetStyleAndValue(sheet, cellStyle1, num, a, "");
            }
            sheetStyleAndValue(sheet, cellStyle1, num, 16, "表格编号： JS/QD-XX");

            sheetSetHight(sheet, num, 20);
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 15));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 16, 20));

            num++;
            sheetStyleAndValue(sheet, cellStyle1, num, 0, "对方单位：");
            sheetStyleAndValue(sheet, cellStyle1, num, 16, "分包合同号/项目编号：" + contractVo.getContract().getUniqueNumber());
            for (int a = 1; a <=15; a++) {
                sheetStyleAndValue(sheet, cellStyle1, num, a, "");
            }
            for (int a = 17; a <=20; a++) {
                sheetStyleAndValue(sheet, cellStyle1, num, a, "");
            }
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 15));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 16, 20));
            sheetSetHight(sheet, num, 20);
            num++;
            sheetStyleAndValue(sheet, cellStyle3, num, 0, "原合同清单");
            sheetStyleAndValue(sheet, cellStyle3, num, 7, "本期计量金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 10, "本期增减变更");
            sheetStyleAndValue(sheet, cellStyle3, num, 13, "本工程累计增减变更");
            sheetStyleAndValue(sheet, cellStyle3, num, 16, "本工程累计计量金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 19, "工程量汇总表编号");
            sheetStyleAndValue(sheet, cellStyle3, num, 20, "备注");
            sheetStyleAndValue(sheet, cellStyle3, num, 1, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 2, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 3, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 4, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 8, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 9, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 11, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 12, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 14, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 15, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 17, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 18, "");

            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 6));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 7, 9));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 10, 12));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 13, 15));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 16, 18));
            sheetSetHight(sheet, num, 30);
            num++;
            sheetStyleAndValue(sheet, cellStyle3, num, 0, "序号");
            sheetStyleAndValue(sheet, cellStyle3, num, 1, "清单名称");
            sheetStyleAndValue(sheet, cellStyle3, num, 2, "单位");
            sheetStyleAndValue(sheet, cellStyle3, num, 3, "工程量");
            sheetStyleAndValue(sheet, cellStyle3, num, 4, "单价");
            sheetStyleAndValue(sheet, cellStyle3, num, 5, "金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 7, "工程量");
            sheetStyleAndValue(sheet, cellStyle3, num, 8, "单价");
            sheetStyleAndValue(sheet, cellStyle3, num, 9, "金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 10, "工程量");
            sheetStyleAndValue(sheet, cellStyle3, num, 11, "单价");
            sheetStyleAndValue(sheet, cellStyle3, num, 12, "金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 13, "工程量");
            sheetStyleAndValue(sheet, cellStyle3, num, 14, "单价");
            sheetStyleAndValue(sheet, cellStyle3, num, 15, "金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 16, "工程量");
            sheetStyleAndValue(sheet, cellStyle3, num, 17, "单价");
            sheetStyleAndValue(sheet, cellStyle3, num, 18, "金额");
            sheetStyleAndValue(sheet, cellStyle3, num, 19, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 20, "");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 5, 6));
            sheet.addMergedRegion(new CellRangeAddress(num - 1, num, 19, 19));
            sheet.addMergedRegion(new CellRangeAddress(num - 1, num, 20, 20));
            sheetSetHight(sheet, num, 30);

            List<List<WorkOrderContractVo>> workOrConVos = listListWorkOrderContract.get(i);
            for (int j = 0; j < workOrConVos.size(); j++) {
                List<WorkOrderContractVo> vos = workOrConVos.get(j);
                WorkOrderContractVo vo = vos.get(0);
                num++;
                sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j + 1));

                sheetStyleAndValue(sheet, cellStyle3, num, 1, StringUtils.isNotEmpty(vo.getSonSubjectNameContract()) ? vo.getSonSubjectNameContract() : vo.getFineSubjectNameContract());
                sheetStyleAndValue(sheet, cellStyle3, num, 2, vo.getSpecContract());
//                    sheetStyleAndValue(sheet,cellStyle2,num,3,String.valueOf(vos.stream().map(s -> new BigDecimal(String.valueOf(s.getAmountContract()))).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
                sheetStyleAndValue(sheet, cellStyle3, num, 3, String.valueOf(vo.getAmountContract()));
                sheetStyleAndValue(sheet, cellStyle3, num, 4, String.valueOf(vo.getPriceContract()));
                sheetStyleAndValue(sheet, cellStyle3, num, 5, String.valueOf(vo.getMontyContract()));
                sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 7
                        , String.valueOf(vos.stream().filter(s->!"".equals(s.getAuditAmountBill())).map(s -> new BigDecimal(String.valueOf(s.getAuditAmountBill()))).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
                sheetStyleAndValue(sheet, cellStyle3, num, 8, String.valueOf(vo.getAuditPriceBill()));
                sheetStyleAndValue(sheet, cellStyle3, num, 9
                        , String.valueOf(vos.stream().map(s -> new BigDecimal(String.valueOf(s.getAuditMoneyBill()))).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
                sheetStyleAndValue(sheet, cellStyle3, num, 10, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 11, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 12, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 13, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 14, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 15, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 16, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 17, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 18, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 19, "");
                sheetStyleAndValue(sheet, cellStyle3, num, 20, "");
                sheet.addMergedRegion(new CellRangeAddress(num, num, 5, 6));
                sheetSetHight(sheet, num, 50);
            }
            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位经办人：                  监理工程师：                       管理中心经办人：");
            sheetStyleAndValue(sheet, cellStyle4, num, 17, "经济管理部审核：");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 12));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 17, 20));
            sheetSetHight(sheet, num, 20);
            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位项目负责人：              总监理工程师：                      管理中心负责人：");
            sheetStyleAndValue(sheet, cellStyle4, num, 17, "经济管理部负责人：");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 12));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 17, 20));
            sheetSetHight(sheet, num, 20);
            num++;

        }
        ExcelUtil.downloadExcel(workbook, "工程(中期计量、完工结算)清单表", response);
    }



    @Override
    public void exportWorkOrdersQuantities(WorkOrderParamVo param, HttpServletResponse response) throws Exception {

        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //工单清单
        List<WorkOrderInformation> workOrders = workOrderInformationManager.getWorkOrderContract(contractId, param);
        if (null ==workOrders || workOrders.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }

        List<String> workOrderIds = workOrders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());


        setQuantitiesSheetAndExport(response, contractVo, workOrderIds);
        return;


    }


    /**
     * 工程量汇总表
     * @param response
     * @param contractVo
     * @param workOrderIds
     * @throws IOException
     */
    private void setQuantitiesSheetAndExport(HttpServletResponse response, ContractVo contractVo, List<String> workOrderIds) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        //标题样式
        HSSFCellStyle cellStyleTitle = workbook.createCellStyle();

        //内容样式1
        HSSFCellStyle cellStyle1 = workbook.createCellStyle();
        //内容样式2
        HSSFCellStyle cellStyle2 = workbook.createCellStyle();
        //内容样式3
        HSSFCellStyle cellStyle3 = workbook.createCellStyle();
        HSSFCellStyle cellStyle4 = workbook.createCellStyle();
        PoiStyleUtil.setWorkOrderStyleTitle(cellStyleTitle, workbook);
        PoiStyleUtil.setWorkOrderCellStyle1(cellStyle1, workbook);
        PoiStyleUtil.setWorkOrderCellStyle2(cellStyle2, workbook);
        PoiStyleUtil.setWorkOrderCellStyle3(cellStyle3, workbook);
        PoiStyleUtil.setWorkOrderCellStyle4(cellStyle4, workbook);


        List<BillOfQuantities> billOfQuantities = billOfQuantitiesDao.listBillOfQuantities(workOrderIds);
        Map<String, List<BillOfQuantities>> collect = billOfQuantities.stream().collect(Collectors.groupingBy(BillOfQuantities::getSonSubjectName));
        ArrayList<List<BillOfQuantities>> lists = new ArrayList<>();
        for (String key : collect.keySet()) {
            List<BillOfQuantities> billOfQuantitiesGroup = collect.get(key);
            if ("".equals(key)) {
                Map<String, List<BillOfQuantities>> listMap = billOfQuantitiesGroup.stream().collect(Collectors.groupingBy(BillOfQuantities::getFineSubjectName));
                for (String keyFine : listMap.keySet()) {
                    List<BillOfQuantities> e = listMap.get(keyFine);
                    lists.add(e);
                }
            } else {
                lists.add(billOfQuantitiesGroup);
            }
        }

        List<List<List<BillOfQuantities>>> splitList = Stream.iterate(0, f -> f + 1).limit((lists.size() + 2) / 3).parallel().map(a -> lists.stream().skip(a * 3).limit(3).parallel().collect(Collectors.toList())).collect(Collectors.toList());

        Integer num = 0;
        HSSFSheet sheet = workbook.createSheet("工程量汇总表");
        sheet.getPrintSetup().setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);
        //设置横向
        sheet.getPrintSetup().setLandscape(true);
        sheet.setColumnWidth(0, 10 * 256);
        sheet.setColumnWidth(1, 20 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);
        sheet.setColumnWidth(4, 20 * 256);
        sheet.setColumnWidth(5, 20 * 256);
        sheet.setColumnWidth(6, 15 * 256);

        for (int i = 0; i < splitList.size(); i++) {
            sheetStyleAndValue(sheet, cellStyleTitle, num, 0, "中国铁建昆仑集团重庆运营总部\n" +
                    "工程量汇总表");
            sheetSetHight(sheet, num, 69);
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 6));
            num++;
            sheetStyleAndValue(sheet, cellStyle1, num, 0, "计量期数：第（ ）期");
            sheetStyleAndValue(sheet, cellStyle1, num, 1, "");
            sheetStyleAndValue(sheet, cellStyle1, num, 2, "");
            sheetStyleAndValue(sheet, cellStyle1, num, 3, "");
            sheetStyleAndValue(sheet, cellStyle1, num, 4, "");
            sheetStyleAndValue(sheet, cellStyle1, num, 5, "");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 6));
            sheetSetHight(sheet, num, 21);
            num++;
            sheetStyleAndValue(sheet, cellStyle2, num, 0, "工程名称（承包合同号/项目编号）：");
            sheetStyleAndValue(sheet, cellStyle2, num, 1, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 2, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 3, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 4, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 6, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 5, "表格编号：JL/HZ-XX");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 4));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 5, 6));
            sheetSetHight(sheet, num, 21);
            num++;
            sheetStyleAndValue(sheet, cellStyle2, num, 0, "对方单位：");
            sheetStyleAndValue(sheet, cellStyle2, num, 1, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 2, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 3, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 4, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 6, "");
            sheetStyleAndValue(sheet, cellStyle2, num, 5, "合同号/项目编号：" + contractVo.getContract().getUniqueNumber());
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 4));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 5, 6));
            sheetSetHight(sheet, num, 21);
//            sheetStyleAndValue(sheet, cellStyle1, num, 6, contractVo.getContract().getUniqueNumber());
            num++;
            sheetStyleAndValue(sheet, cellStyle3, num, 0, "序号");
            sheetStyleAndValue(sheet, cellStyle3, num, 1, "清单名称");
            sheetStyleAndValue(sheet, cellStyle3, num, 2, "单位");
            sheetStyleAndValue(sheet, cellStyle3, num, 3, "数量");
            sheetStyleAndValue(sheet, cellStyle3, num, 4, "……");
            sheetStyleAndValue(sheet, cellStyle3, num, 5, "收方记录表编号");
            sheetStyleAndValue(sheet, cellStyle3, num, 6, "备注");
            sheetSetHight(sheet, num, 33);
            List<List<BillOfQuantities>> bills = splitList.get(i);
            if (bills.size() == 3) {
                for (int j = 0; j < bills.size(); j++) {
                    num++;
                    List<BillOfQuantities> billOfQuan = bills.get(j);


                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j + 1));
                    BillOfQuantities bill = billOfQuan.get(0);

                    sheetStyleAndValue(sheet, cellStyle3, num, 1, StringUtils.isNotEmpty(bill.getSonSubjectName()) ? bill.getSonSubjectName() : bill.getFineSubjectName());
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, bill.getSpec());
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, String.valueOf(billOfQuan.stream().map(s -> new BigDecimal(String.valueOf(s.getAuditAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, billOfQuan.stream().map(BillOfQuantities::getJobNumber).collect(Collectors.joining("、")));
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetSetHight(sheet, num, 60);


                }
            } else {
                for (int j = 0; j < bills.size(); j++) {
                    num++;
                    List<BillOfQuantities> billOfQuan = bills.get(j);
                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j + 1));
                    BillOfQuantities bill = billOfQuan.get(0);
                    sheetStyleAndValue(sheet, cellStyle3, num, 1, StringUtils.isNotEmpty(bill.getSonSubjectName()) ? bill.getSonSubjectName() : bill.getFineSubjectName());
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, bill.getSpec());
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, String.valueOf(billOfQuan.stream().map(s -> new BigDecimal(String.valueOf(s.getAuditAmount()))).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP)));
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, billOfQuan.stream().map(BillOfQuantities::getJobNumber).collect(Collectors.joining("、")));
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetSetHight(sheet, num, 60);
                }
                for (int j = 0; j < 3 - bills.size(); j++) {
                    num++;
                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j + bills.size() + 1));

                    sheetStyleAndValue(sheet, cellStyle3, num, 1, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetSetHight(sheet, num, 60);
                }
            }
            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位经办人：                            监理工程师：              管理中心经办人：                    总部业务部门经办人：");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 6));
            sheetSetHight(sheet, num, 25);
            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位项目负责人：                         总监理工程师：            管理中心负责人：                    总部业务部门负责人：");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 6));
            sheetSetHight(sheet, num, 25);
            num++;

        }

        ExcelUtil.downloadExcel(workbook, "工程量汇总表", response);
    }


    /**
     * 工程量汇总-已办工单
     * @param param
     * @param response
     * @throws Exception
     */
    @Override
    public void exportWorkOrdersQuantitiesConstruction(WorkOrderParamVo param, HttpServletResponse response) throws Exception {
        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //工单清单
        List<WorkOrderInformation> workOrders = workOrderInformationManager.getWorkOrderContract(contractId, param);
        if (null ==workOrders || workOrders.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }

        List<String> workOrderIds = workOrders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());

        List<String> orderIds = getConstructionOrderIds(workOrderIds);

        if (null ==orderIds || orderIds.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }

        setQuantitiesSheetAndExport(response, contractVo, orderIds);
        return;

    }

    @Override
    public void exportWorkOrdersDebitRecord(WorkOrderParamVo param, HttpServletResponse response) throws Exception {



        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //工单清单
        List<WorkOrderInformation> workOrders = workOrderInformationManager.getWorkOrderContract(contractId, param);
        if (null ==workOrders || workOrders.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }
        List<String> workOrderIds = workOrders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());


        setDebitRecordSheetAndExport(response, contractVo, workOrderIds);
        return;
    }


    /**
     * 工程收方记录表（施工类)
     * @param response
     * @param contractVo
     * @param workOrderIds
     * @throws IOException
     */
    private void setDebitRecordSheetAndExport(HttpServletResponse response, ContractVo contractVo, List<String> workOrderIds) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        //标题样式
        HSSFCellStyle cellStyleTitle = workbook.createCellStyle();

        //内容样式1
        HSSFCellStyle cellStyle1 = workbook.createCellStyle();
        //内容样式2
        HSSFCellStyle cellStyle2 = workbook.createCellStyle();
        //内容样式3
        HSSFCellStyle cellStyle3 = workbook.createCellStyle();
        HSSFCellStyle cellStyle4 = workbook.createCellStyle();
        PoiStyleUtil.setWorkOrderStyleTitle(cellStyleTitle, workbook);
        PoiStyleUtil.setWorkOrderCellStyle1(cellStyle1, workbook);
        PoiStyleUtil.setWorkOrderCellStyle2(cellStyle2, workbook);
        PoiStyleUtil.setWorkOrderCellStyle3(cellStyle3, workbook);
        PoiStyleUtil.setWorkOrderCellStyle4(cellStyle4, workbook);


        List<BillOfQuantities> billOfQuantities = billOfQuantitiesDao.listBillOfQuantitiesTime(workOrderIds);
        List<List<BillOfQuantities>> collect = Stream.iterate(0, f -> f + 1).limit((billOfQuantities.size() + 9) / 10).parallel().map(a -> billOfQuantities.stream().skip(a * 10).limit(10).parallel().collect(Collectors.toList())).collect(Collectors.toList());

        Integer num = 0;
        HSSFSheet sheet = workbook.createSheet("工程收方记录表（施工类）");
        sheet.getPrintSetup().setPaperSize(HSSFPrintSetup.A4_PAPERSIZE);
        //设置横向
        sheet.getPrintSetup().setLandscape(true);
        sheet.setColumnWidth(0, 8 * 256);
        sheet.setColumnWidth(1, 25 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 15 * 256);
        sheet.setColumnWidth(4, 5 * 256);
        sheet.setColumnWidth(5, 20 * 256);
        sheet.setColumnWidth(6, 9 * 256);
        sheet.setColumnWidth(7, 9 * 256);
        sheet.setColumnWidth(8, 9 * 256);
        sheet.setColumnWidth(9, 9 * 256);
        for (int i = 0; i < collect.size(); i++) {
            sheetStyleAndValue(sheet, cellStyleTitle, num, 0, "中国铁建昆仑集团重庆运营总部\n" +
                    "工程收方记录表（施工类）");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 9));
            sheetSetHight(sheet, num, 60);
            num++;
            sheetStyleAndValue(sheet, cellStyle2, num, 0, "工程名称（承包合同号/项目编号）：");
            sheetStyleAndValue(sheet, cellStyle2, num, 6, "表格编号： SF/JL-XX");
            for (int a = 1; a <= 5; a++) {
                sheetStyleAndValue(sheet, cellStyle2, num, a, "");
            }

            for (int a = 7; a <= 9; a++) {
                sheetStyleAndValue(sheet, cellStyle2, num, a, "");
            }
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 5));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 6, 9));
            sheetSetHight(sheet, num, 20);
            num++;
            sheetStyleAndValue(sheet, cellStyle2, num, 0, "对方单位：" + contractVo.getContract().getSecondParty());
            sheetStyleAndValue(sheet, cellStyle2, num, 6, "合同号/项目编号：" + contractVo.getContract().getUniqueNumber());
            for (int a = 1; a <= 5; a++) {
                sheetStyleAndValue(sheet, cellStyle2, num, a, "");
            }

            for (int a = 7; a <= 9; a++) {
                sheetStyleAndValue(sheet, cellStyle2, num, a, "");
            }
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 5));
            sheet.addMergedRegion(new CellRangeAddress(num, num, 6, 9));
            sheetSetHight(sheet, num, 20);
            num++;
            sheetStyleAndValue(sheet, cellStyle3, num, 0, "序号");
            sheetStyleAndValue(sheet, cellStyle3, num, 1, "清单名称");
            sheetStyleAndValue(sheet, cellStyle3, num, 2, "施工/收方日期");
            sheetStyleAndValue(sheet, cellStyle3, num, 3, "工程部位及桩号");
            sheetStyleAndValue(sheet, cellStyle3, num, 4, "收方示意图/计算式");
            sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
            sheetStyleAndValue(sheet, cellStyle3, num, 7, "单位");
            sheetStyleAndValue(sheet, cellStyle3, num, 8, "数量");
            sheetStyleAndValue(sheet, cellStyle3, num, 9, "备注");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 4, 6));
            sheetSetHight(sheet, num, 20);
            List<BillOfQuantities> bills = collect.get(i);
            if (bills.size() == 10) {
                for (int j = 0; j < bills.size(); j++) {
                    num++;
                    BillOfQuantities ofQuantities = bills.get(j);
                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j+1));
                    sheetStyleAndValue(sheet, cellStyle3, num, 1, StringUtils.isNotEmpty(ofQuantities.getSonSubjectName()) ? ofQuantities.getSonSubjectName() : ofQuantities.getFineSubjectName());
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, ofQuantities.getDebitTime() == null ? "" : new SimpleDateFormat("yyyy-MM-dd").format(ofQuantities.getDebitTime()));
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, ofQuantities.getPosition());
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, ofQuantities.getJobNumber());
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 7, ofQuantities.getSpec());
                    sheetStyleAndValue(sheet, cellStyle3, num, 8, String.valueOf(ofQuantities.getAuditAmount()));
                    sheetStyleAndValue(sheet, cellStyle3, num, 9, "");
                    sheet.addMergedRegion(new CellRangeAddress(num, num, 4, 6));
                    sheetSetHight(sheet, num, 30);
                }
            } else {
                for (int j = 0; j < bills.size(); j++) {
                    num++;
                    BillOfQuantities ofQuantities = bills.get(j);
                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j));
                    sheetStyleAndValue(sheet, cellStyle3, num, 1, StringUtils.isNotEmpty(ofQuantities.getSonSubjectName()) ? ofQuantities.getSonSubjectName() : ofQuantities.getFineSubjectName());
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, ofQuantities.getDebitTime() == null ? "" : new SimpleDateFormat("yyyy-MM-dd").format(ofQuantities.getDebitTime()));
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, ofQuantities.getPosition());
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, ofQuantities.getJobNumber());
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 7, ofQuantities.getSpec());
                    sheetStyleAndValue(sheet, cellStyle3, num, 8, String.valueOf(ofQuantities.getAuditAmount()));
                    sheetStyleAndValue(sheet, cellStyle3, num, 9, "");
                    sheet.addMergedRegion(new CellRangeAddress(num, num, 4, 6));
                    sheetSetHight(sheet, num, 30);
                }
                for (int j = 0; j < 10 - bills.size(); j++) {
                    num++;
                    sheetStyleAndValue(sheet, cellStyle3, num, 0, String.valueOf(j + bills.size() + 1));
                    sheetStyleAndValue(sheet, cellStyle3, num, 1, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 2, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 3, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 4, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 5, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 6, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 7, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 8, "");
                    sheetStyleAndValue(sheet, cellStyle3, num, 9, "");
                    sheet.addMergedRegion(new CellRangeAddress(num, num, 4, 6));
                    sheetSetHight(sheet, num, 30);
                }
            }

            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位经办人：                     监理工程师：                  管理中心经办人：                        总部业务部门经办人：   ");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 9));
            sheetSetHight(sheet, num, 20);
            num++;
            sheetStyleAndValue(sheet, cellStyle4, num, 0, "施工单位项目负责人：                  总监理工程师：                管理中心负责人：                       总部业务部门负责人：  ");
            sheet.addMergedRegion(new CellRangeAddress(num, num, 0, 9));
            sheetSetHight(sheet, num, 20);
            num++;
        }


        ExcelUtil.downloadExcel(workbook, "工程收方记录表", response);
    }


    /**
     * 工程收方记录表（施工类）-已办清单
     * @param param
     * @param response
     */
    @Override
    public void exportWorkOrdersDebitRecordConstruction(WorkOrderParamVo param, HttpServletResponse response)throws Exception {


        String contractId = param.getContractId();
        //日常养护合同
        ContractVo contractVo = contractManager.getContractById(contractId);
        //工单清单
        List<WorkOrderInformation> workOrders = workOrderInformationManager.getWorkOrderContract(contractId, param);
        if (null ==workOrders || workOrders.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }
        List<String> workOrderIds = workOrders.stream().map(WorkOrderInformation::getId).collect(Collectors.toList());

        List<String> orderIds = getConstructionOrderIds(workOrderIds);
        if (null ==orderIds || orderIds.size()==0){
            throw new RuntimeException("当前时间段没有工单信息");
        }

        setDebitRecordSheetAndExport(response, contractVo, orderIds);
        return;
    }

    //设置值和格式
    private synchronized void sheetStyleAndValue(HSSFSheet sheet, HSSFCellStyle cellStyle, Integer rowIndex, Integer cellIndex, String value) {
        HSSFRow row = sheet.getRow(rowIndex);
        if (row == null) {
            row = sheet.createRow(rowIndex);
        }
        HSSFCell cell = row.getCell(cellIndex);
        if (cell == null) {
            cell = row.createCell(cellIndex);
        }
        cell.setCellStyle(cellStyle);
        cell.setCellValue(value);
    }

    private synchronized void sheetSetHight(HSSFSheet sheet, Integer rowIndex, Integer height) {
        HSSFRow row = sheet.getRow(rowIndex);
        row.setHeight((short) (height * 20));
    }


}
