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

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.artfess.base.context.BaseContext;
import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.query.PageBean;
import com.artfess.base.query.PageList;
import com.artfess.base.query.QueryFilter;
import com.artfess.base.query.QueryOP;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.DateUtils;
import com.artfess.cqxy.completionAcceptance.model.RecordAcceptanceSpecial;
import com.artfess.cqxy.contract.dao.FundPlanDao;
import com.artfess.cqxy.contract.manager.ContractManager;
import com.artfess.cqxy.contract.manager.FundPlanManager;
import com.artfess.cqxy.contract.model.Contract;
import com.artfess.cqxy.contract.model.FundPlan;
import com.artfess.cqxy.contract.vo.ContractVo;
import com.artfess.cqxy.processManagermant.manager.ProgressManageManager;
import com.artfess.cqxy.processManagermant.manager.impl.ProgressManageManagerImpl;
import com.artfess.cqxy.processManagermant.model.ProgressManage;
import com.artfess.cqxy.projectManagement.enums.ProjectStatusEnum;
import com.artfess.cqxy.projectManagement.manager.ProjectManagementManager;
import com.artfess.cqxy.projectManagement.model.ProjectManagement;
import com.artfess.cqxy.search.enums.FunctionEnum;
import com.artfess.cqxy.search.manager.GlobalRetrievalManager;
import com.artfess.cqxy.search.model.GlobalRetrieval;
import com.artfess.cqxy.universal.manager.AccessoryManager;
import com.artfess.cqxy.universal.model.Accessory;
import com.artfess.cqxy.utils.BizUtils;
import com.artfess.poi.util.ExcelUtil;
import com.artfess.sysConfig.persistence.manager.SysDictionaryManager;
import com.artfess.sysConfig.persistence.param.DictModel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.checkerframework.checker.units.qual.K;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Description:
 * @Author: Rong Tao
 * @Date: 2022/7/7 11:35
 */
@Service
public class FundPlanManagerImpl extends BaseManagerImpl<FundPlanDao,FundPlan> implements FundPlanManager {

    @Autowired
    private AccessoryManager accessoryManager;

    @Autowired
    private ProjectManagementManager pm;

    @Autowired
    private SysDictionaryManager sdm;

    @Autowired
    private BaseContext baseContext;

    @Autowired
    private GlobalRetrievalManager grm;

    @Autowired
    private ProgressManageManager pgm;

    @Override
    public boolean saveOrUpdate(FundPlan entity) {
        boolean save = StringUtils.isEmpty(entity.getId());
        boolean savedMain = super.saveOrUpdate(entity);
        // 处理附件信息
        List<Accessory> flag = entity.getAccessoryInfo();//处理空指针
        List<Accessory> accessoryList = null == flag ? new ArrayList<>() : flag;
        for (Accessory ele : accessoryList) {
            ele.setSourceId(entity.getId());
            ele.setProjectId(entity.getProjectId());
            ele.setDirectory(ProjectStatusEnum.nine.getCode());
            ele.setGroup("FundPlan");
            ele.setNode(ProjectStatusEnum.nine.getCode());
            ele.setCreateBy(baseContext.getCurrentUserId());
            ele.setCreateName(baseContext.getCurrentUserName());
            ele.setCreateTime(LocalDateTime.now());
        }
        // 先清空该ID下的所有附件信息再添加
        accessoryManager.removeBySourceId(entity.getId());
        // 如果没有附件则返回true，不进入添加
        boolean saveAcc = accessoryList.size() == 0 || accessoryManager.saveAccess(accessoryList);
        //更新项目状态-单位工程验收时不作为竣工验收条件
        pm.updateStatusById(entity.getProjectId(), Integer.valueOf(ProjectStatusEnum.nine.getCode()));
        // 同步到检索表
        GlobalRetrieval globalRetrieval = grm.getByBizId(entity.getId());
        handleRetrieval(save || BeanUtils.isEmpty(globalRetrieval) ? new GlobalRetrieval() : globalRetrieval, entity);


        return savedMain && saveAcc;
    }

    private void handleRetrieval(GlobalRetrieval globalRetrieval, FundPlan entity) {
        ProjectManagement projectManagement = pm.getById(entity.getProjectId());
        globalRetrieval.setProjectId(entity.getProjectId());
        globalRetrieval.setProjectName(projectManagement.getProjectName());
        globalRetrieval.setPersonCharge(projectManagement.getProjectManager());
        globalRetrieval.setArchivesType(1);
        globalRetrieval.setBizDataId(entity.getId());
        globalRetrieval.setFunctionCode(FunctionEnum.thirtyFive.getCode());
        globalRetrieval.setFunctionName(FunctionEnum.thirtyFive.getName());
        globalRetrieval.setBizTableName(FunctionEnum.thirtyFive.getTableName());
        globalRetrieval.setDetailsRoteUrl(FunctionEnum.thirtyFive.getTableRoteUrl());
        globalRetrieval.setTableRoteUrl(FunctionEnum.thirtyFive.getTableRoteUrl());
        globalRetrieval.setTableApiUrl(FunctionEnum.thirtyFive.getTableApiUrl());
        globalRetrieval.setDetailsApiUrl(FunctionEnum.thirtyFive.getDetailsApiUrl());
        globalRetrieval.setFunctionPath(FunctionEnum.thirtyFive.getFunctionPath());
        globalRetrieval.setName(entity.getPurpose());
        globalRetrieval.setSearchTitle(entity.getPurpose() + "_" + entity.getUnitNname() + "_" + entity.getRemarks());
        grm.saveOrUpdate(globalRetrieval);
    }

    @Override
    public boolean deleteByIds(List<String> ids) {
        // 同步删除检索表中的信息
        for (String ele : ids) {
            grm.remove(1, ele);
        }
        return removeByIds(ids);
    }

    @Override
    public FundPlan getById(String id) {
        FundPlan result = baseMapper.getById(id);
        result.setAccessoryInfo(accessoryManager.getAccessoryBySourceId(id));
        return result;
    }

    @Override
    public PageList<FundPlan> queryAllByPage(QueryFilter<FundPlan> queryFilter) {
        BizUtils.handleFilter(queryFilter, "bfp", false);
        IPage<FundPlan> result =
                baseMapper.queryAllByPage(
                        convert2IPage(queryFilter.getPageBean()),
                        convert2Wrapper(queryFilter, currentModelClass()));
        // 附件信息处理
        List<FundPlan> records = result.getRecords();
        for (FundPlan ele : records) {
            ele.setAccessoryInfo(accessoryManager.getAccessoryBySourceId(ele.getId()));
        }

        return new PageList<>(result);
    }

    @Override
    public void importExcelData(MultipartFile file, String projectId, String contractId) {
        Assert.notNull(projectId, "项目ID不能为空");
        Assert.notNull(contractId, "合同ID不能为空");
        try (InputStream inputStream = file.getInputStream()) {
            // 获取数据
            List<FundPlan> data = ExcelImportUtil.importExcel(inputStream, FundPlan.class, new ImportParams());
            for (FundPlan ele : data) {
                ele.setProjectId(projectId);
                ele.setContractId(contractId);
                // 保存数据 & 同步到检索表
                save(ele);
                handleRetrieval(new GlobalRetrieval(), ele);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportDatatoExcel(QueryFilter<FundPlan> queryFilter, HttpServletResponse response) throws IOException {
        String fileName = "合同管理-资金计划-导出结果";

        // 字典
        List<DictModel> checkType = sdm.queryDictListItemsByCode("jdgl-yt");

        // 创建excel工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建excel表
        HSSFSheet sheet = workbook.createSheet(fileName);

        // 标题行
        HSSFRow titleRow = sheet.createRow(0);
        BizUtils.handelCell(workbook, fileName, titleRow.createCell(0), "资金计划表", true);
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 8));

        // 拼接标题行数据
        List<String> heards = new ArrayList<>();
        // 注意：Arrays.asList 将会返回一个不可修改的List，不能在初始化时调用
        heards.addAll(Arrays.asList(new String[]{"序号", "项目名称", "合同ID", "合同名称", "计划日期", "费用名称", "单位名称", "金额", "是否2022年新开工项目", "是否2022年专项债申报项目", "备注"}));

        // 创建标题行并写入数据
        titleRow = sheet.createRow(1);
        for (int i = 0; i < heards.size(); i++) {
            BizUtils.handelCell(workbook, fileName, titleRow.createCell(i), heards.get(i));
        }

        // 数据行,从1行开始,共data.size行
        int row = 2;

        // 获取数据
        BizUtils.handleFilter(queryFilter, "bfp", false);
        List<FundPlan> data = baseMapper.queryAllByPage(
                        convert2IPage(new PageBean(0, -1, false)),
                        convert2Wrapper(queryFilter, currentModelClass())).
                getRecords();
        if (null == data || data.size() == 0) {
            throw new RuntimeException("没有要导出的的数据！");
        }

        // 翻译字典
        for (FundPlan fp : data) {
            fp.setPurpose(BizUtils.getDicValueByCode(checkType, fp.getPurpose()));
        }


        //计数器，记录当前序号
        int counter = 1;

        // 处理数据
        exportToExcel(data, workbook, sheet, fileName, row, counter, new BigDecimal(0.00));
//        for (int i = 0; i < data.size(); i++) {
//            HSSFRow listRow = sheet.createRow(row);// 创建行
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(0), String.valueOf(counter));
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(1), data.get(i).getProjectInfo().getProjectName());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(2), data.get(i).getContractId());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(3), data.get(i).getContractName());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(4), DateUtils.date2Str(data.get(i).getContractDate(), new SimpleDateFormat("yyyy-MM")));
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(5), data.get(i).getPurpose());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(6), data.get(i).getUnitNname());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(7), String.valueOf(data.get(i).getContractAmount()));
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(8), data.get(i).getHasNew());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(9), data.get(i).getHasSpecial());
//            BizUtils.handelCell(workbook, fileName, listRow.createCell(10), data.get(i).getRemarks());
//            row++;
//            counter++;
//        }

        //设置序号列宽度
        sheet.setColumnWidth(0, 1500);

        //设置第一列序号之后每个单元格的宽度
        for(int i = 1;i<heards.size();i++){
            sheet.setColumnWidth(i,5000);
        }

        ExcelUtil.downloadExcel(workbook, fileName, response);

    }

    @Override
    public void exportDatatoExcel2(QueryFilter<FundPlan> queryFilter, HttpServletResponse response) throws IOException {
        // 字典
        List<DictModel> checkType = sdm.queryDictListItemsByCode("jdgl-yt");
        String fileName = "合同管理-本月资金计划-导出结果";

        //本月计划导出数据
        List<FundPlan> newList = new ArrayList<>();
        //以前计划导出数据
        List<FundPlan> oldList = new ArrayList<>();

        //获取当前的年份
        Calendar cYear = Calendar.getInstance();
        int nowYear = cYear.get(Calendar.YEAR);
        //获取当前的月份
        Calendar cMonth = Calendar.getInstance();
        int nowMonth = cMonth.get(Calendar.MONTH) + 1;

        BizUtils.handleFilter(queryFilter, "bfp", false);
        queryFilter.addFilter("YEAR(PLAN_DATE_)", nowYear, QueryOP.EQUAL);
        queryFilter.addFilter("MONTH(PLAN_DATE_)", nowMonth, QueryOP.LESS_EQUAL);

        List<FundPlan> data = baseMapper.queryAllByPage(
                        convert2IPage(new PageBean(0, -1, false)),
                        convert2Wrapper(queryFilter, currentModelClass())).
                getRecords();

        //以前计划月份的所有数据
        List<FundPlan> beforeList = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        // 处理数据是本月还是以前的
        if (null != data || data.size() != 0) {
            for (int i = 0; i < data.size(); i++) {
                String date2Str = DateUtils.date2Str(data.get(i).getContractDate(), simpleDateFormat);
                Calendar c = Calendar.getInstance();
                try {
                    c.setTime(simpleDateFormat.parse(date2Str));
                } catch (ParseException e) {
                    e.printStackTrace();
                }

                if (c.get(Calendar.MONTH) + 1 == nowMonth) {
                    newList.add(data.get(i));
                } else {
                    beforeList.add(data.get(i));
                }
            }
        }
        //处理以前月度的数据
        if (null != beforeList || beforeList.size() != 0) {
            for (int i = 0; i < beforeList.size(); i++) {
                String date2Str = DateUtils.date2Str(beforeList.get(i).getContractDate(), simpleDateFormat);
                LambdaQueryWrapper<ProgressManage> lambdaQueryWrapper = new LambdaQueryWrapper();
                lambdaQueryWrapper.eq(ProgressManage::getPurpose, beforeList.get(i).getPurpose());
                lambdaQueryWrapper.like(ProgressManage::getRegisterPersonName, beforeList.get(i).getUnitNname());
                lambdaQueryWrapper.eq(ProgressManage::getProjectId, beforeList.get(i).getProjectId());
                lambdaQueryWrapper.like(ProgressManage::getRegisterDate,date2Str);

                //从支付表中查询到符合条件的数据
                List<ProgressManage> progressManages = pgm.fundplanGetProgressManage(lambdaQueryWrapper);

                //如果没有查到数据,就加入以前月度需本月支付
                if (progressManages == null || progressManages.size() ==0) {
                    oldList.add(beforeList.get(i));
                }
            }
        }

        // 创建excel工作薄
        HSSFWorkbook workbook = new HSSFWorkbook();
        // 创建excel表
        HSSFSheet sheet = workbook.createSheet(fileName);
        // 标题行
        HSSFRow titleRow = sheet.createRow(0);
        BizUtils.handelCell(workbook, fileName, titleRow.createCell(0), "资金计划表", true);
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 10));
        // 拼接标题行数据
        List<String> heards = new ArrayList<>();
        // 注意：Arrays.asList 将会返回一个不可修改的List，不能在初始化时调用
        heards.addAll(Arrays.asList(new String[]{"序号", "项目名称", "合同ID", "合同名称", "计划日期", "费用名称", "单位名称", "金额", "是否2022年新开工项目", "是否2022年专项债申报项目", "备注"}));

        List<String> litTittle = new ArrayList<>();
        litTittle.addAll(Arrays.asList(new String[]{"（一）本月资金支出计划", "（二）以前月度已列支计划需本月收入"}));

        // 创建标题行并写入数据
        titleRow = sheet.createRow(1);
        for (int i = 0; i < heards.size(); i++) {
            BizUtils.handelCell(workbook, fileName, titleRow.createCell(i), heards.get(i));
        }

        //创建第一个小标题（一）本月资金支出计划
        titleRow = sheet.createRow(2);
        BizUtils.handelCell(workbook, fileName, titleRow.createCell(0), litTittle.get(0));
        sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 2));
        // 翻译字典
        for (FundPlan fp : data) {
            fp.setPurpose(BizUtils.getDicValueByCode(checkType, fp.getPurpose()));
        }
        //计数器，记录当前序号
        int counter = 1;
        // 数据行,从3行开始,共data.size行
        int row = 3;
        //总金额
        BigDecimal totalMoney = new BigDecimal(0.00);

        List temp1 = exportToExcel(newList, workbook, sheet, fileName, row, counter, totalMoney);
        row = (int)temp1.get(0);
        totalMoney = (BigDecimal) temp1.get(1);

        //显示第二个小标题（二）以前月度已列支计划需本月收入
        titleRow = sheet.createRow(row);
        BizUtils.handelCell(workbook, fileName, titleRow.createCell(0), litTittle.get(1));
        sheet.addMergedRegion(new CellRangeAddress(row, row, 0, 2));
        row++;

        List temp2 = exportToExcel(oldList, workbook, sheet, fileName, row, counter, totalMoney);
        row = (int)temp2.get(0);
        totalMoney = (BigDecimal) temp2.get(1);

        //写入总金额
        HSSFRow rows = sheet.createRow(row);
        BizUtils.handelCell(workbook, fileName, rows.createCell(7), String.valueOf(totalMoney));
        //设置序号列宽度
        sheet.setColumnWidth(0, 1500);

        //设置第一列序号之后每个单元格的宽度
        for(int i = 1;i<heards.size();i++){
            sheet.setColumnWidth(i,5000);
        }

        ExcelUtil.downloadExcel(workbook, fileName, response);

    }

    public List exportToExcel(List<FundPlan> list, HSSFWorkbook workbook, HSSFSheet sheet,String fileName,int row,int counter,BigDecimal totalMoney){

        //设置日期格式
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        HSSFDataFormat dataFormat = workbook.createDataFormat();
        cellStyle.setDataFormat(dataFormat.getFormat("yyyy-MM"));

        if (null != list || list.size() != 0) {
            for(int i = 0;i<list.size();i++){
                HSSFRow listRow = sheet.createRow(row);// 创建行
                BizUtils.handelCell(workbook, fileName, listRow.createCell(0), String.valueOf(counter));BizUtils.handelCell(workbook, fileName, listRow.createCell(1), list.get(i).getProjectInfo().getProjectName());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(2), list.get(i).getContractId());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(3), list.get(i).getContractName());
                HSSFCell cell4 = listRow.createCell(4);
                BizUtils.handelCell(workbook, fileName, cell4, DateUtils.date2Str(list.get(i).getContractDate(), new SimpleDateFormat("yyyy-MM")));
                cell4.setCellStyle(cellStyle);
                BizUtils.handelCell(workbook, fileName, listRow.createCell(5), list.get(i).getPurpose());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(6), list.get(i).getUnitNname());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(7), String.valueOf(list.get(i).getContractAmount()));
                BizUtils.handelCell(workbook, fileName, listRow.createCell(8), list.get(i).getHasNew());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(9), list.get(i).getHasSpecial());
                BizUtils.handelCell(workbook, fileName, listRow.createCell(10), list.get(i).getRemarks());
                if (list.get(i).getContractAmount() != null) {
                    totalMoney = totalMoney.add(list.get(i).getContractAmount());
                }
                row++;
                counter++;
            }
        }



        List result = new ArrayList();
        result.add(row);
        result.add(totalMoney);
        return result;
    }

}
