package com.yunyan.business.document.y22;


import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.enums.WriteDirectionEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.yunyan.business.document.y22.pojo.finalExcelY22.*;
import com.yunyan.common.utils.StringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

@Slf4j
public class GenerateFinalExcelY22Utils {

    /** 导出 的 excel 文件 */

    public static String templateFileName = "template/".concat("y2022ft2_template.2.xls");


    /**
     * 2022年度崇左的模板(2th模板)
     * @param dataVo
     * @param targetFileName
     * @return
     */
    public static boolean generateExcel(FinalExcelDataVo dataVo, String targetFileName) {

        //.withTemplate(templateFileName)就是读取模板
        //.write(ExcelUtil.getOutputStream(outFileName, response))是将数据写入文件，并交给response
//        try (InputStream templateInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templateFileName)) {
            InputStream templateInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templateFileName);
            ExcelWriter excelWriter = EasyExcel.write(targetFileName).withTemplate(templateInputStream).build();

            // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
            // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
            // 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
            //.direction(WriteDirectionEnum.VERTICAL)这个是设置list填入的时候是纵向填入
            FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.VERTICAL).forceNewRow(Boolean.TRUE).build();

            //表 1 - 7的数据列表
            setSheetData(excelWriter, fillConfig, 0, dataVo.getT1Z01Vo().getList(), null, dataVo, null);
            setSheetData(excelWriter, fillConfig, 1, dataVo.getT2Z03Vo().getList(), dataVo.getT2Z03Vo(), dataVo, null);
            setSheetData(excelWriter, fillConfig, 2, dataVo.getT3Z04Vo().getList(), dataVo.getT3Z04Vo(), dataVo, null);
            setSheetData(excelWriter, fillConfig, 3, dataVo.getT4Z01S1Vo().getList(), null, dataVo, null);
            setSheetData(excelWriter, fillConfig, 4, dataVo.getT5Z07Vo().getList(), dataVo.getT5Z07Vo(), dataVo, null);
            setSheetData(excelWriter, fillConfig, 5, dataVo.getT6VZ08S1Vo().getList(), null, dataVo, null);
            setSheetData(excelWriter, fillConfig, 6, dataVo.getT7F03Vo().getList(), null, dataVo, GenerateFinalExcelY22Utils.checkT7Remark(dataVo.getT7F03Vo().getList()));
            setSheetData(excelWriter, fillConfig, 7, dataVo.getT8Z09Vo().getList(), dataVo.getT8Z09Vo().getTotalRow(), dataVo,  GenerateFinalExcelY22Utils.checkT8Remark(dataVo.getT8Z09Vo().getList()));
            setSheetData(excelWriter, fillConfig, 8, dataVo.getT9Z11Vo().getList(), dataVo.getT9Z11Vo().getTotalRow(), dataVo, GenerateFinalExcelY22Utils.checkT9Remark(dataVo.getT9Z11Vo().getList()));
//            setT1(excelWriter, dataVo, fillConfig)

            /*WriteSheet writeSheet  = EasyExcel.writerSheet(0).build();
            excelWriter.fill(dataVo.getT1Z01Vo().getList(),  fillConfig, writeSheet);*/
            //setSheetData(excelWriter, fillConfig, 1, dataVo.getT1Z01Vo().getList());


//        excelWriter.write(dataVo.getT1Z01Vo().getList(), writeSheet);

            /**
             * 这里是将一些普通数据放到map中，方便填入，可以看getStringObjectMap()。
             * map的String是对应的名称，Object就是数据了。
             * 将数据填入
             */
//            excelWriter.fill(map, writeSheet);
            //关闭
            excelWriter.finish();
            return true;
        /*} catch (IOException e) {
            log.error("excel表格生成 IO 异常 [{}], [{}]", e.getMessage(), e);
        }*/
    }

    /**
     * 设置 excel的data数据
     * @param excelWriter excel的写类
     * @param fillConfig 配置
     * @param sheetNo sheetno
     * @param list 数据List
     */
    public static void setSheetData(ExcelWriter excelWriter, FillConfig fillConfig, Integer sheetNo, Collection list) {
        //创建Sheet 设置excel Sheet为第几张并设置名称
        //.writerSheet(0,"第一个")中前面的参数为sheetNo,就是第几张sheet
        //第二参数为sheet名称, 不写就是默认
        WriteSheet writeSheet  = EasyExcel.writerSheet(sheetNo).build();

        /*
        这里是将list填充到excel中。
        会去找模板上对应的数据填入，例如模板中的{list.getGoodsName}就是下面List集合中名为goodsName字段对应的数据
        new FillWrapper("list", selectOrderDTO.getSelectOrderGoodsDTOS())前面的参数是设置一个填入的list名
        后面的参数是获得的list，里面就包含了要填入的数据
        .fill()主要就是将数据填入excel中*/
//        excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);
    }

    /**
     * 设置 excel的data数据
     * @param excelWriter excel的写类
     * @param fillConfig 配置
     * @param sheetNo sheetno
     * @param list 数据List
     * @param data 数据List
     * @param dataVo 总的
     */
    public static void setSheetData(ExcelWriter excelWriter, FillConfig fillConfig, Integer sheetNo, Collection list, Object data, Object dataVo, ExcelFillVo fillVo) {
        //创建Sheet 设置excel Sheet为第几张并设置名称
        //.writerSheet(0,"第一个")中前面的参数为sheetNo,就是第几张sheet
        //第二参数为sheet名称, 不写就是默认
        WriteSheet writeSheet  = EasyExcel.writerSheet(sheetNo).build();

        /*
        这里是将list填充到excel中。
        会去找模板上对应的数据填入，例如模板中的{list.getGoodsName}就是下面List集合中名为goodsName字段对应的数据
        new FillWrapper("list", selectOrderDTO.getSelectOrderGoodsDTOS())前面的参数是设置一个填入的list名
        后面的参数是获得的list，里面就包含了要填入的数据
        .fill()主要就是将数据填入excel中*/
//        excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);

        //设置传数据
        if(null != data) {
            excelWriter.fill(data, fillConfig, writeSheet);
        }

        if(null != dataVo) {
            excelWriter.fill(dataVo, fillConfig, writeSheet);
            excelWriter.fill(dataVo, fillConfig, writeSheet);
        }

        if(null != fillVo) {
            excelWriter.fill(fillVo, fillConfig, writeSheet);
        }

    }

    /**
     * 设置表一的数据
     * @param excelWriter
     * @param dataVo
     */
    public static void setT1(ExcelWriter excelWriter, FinalExcelDataVo dataVo, FillConfig fillConfig) {
        //创建Sheet 设置excel Sheet为第几张并设置名称
        //.writerSheet(0,"第一个")中前面的参数为sheetNo,就是第几张sheet
        //第二参数为sheet名称, 不写就是默认
        WriteSheet writeSheet0  = EasyExcel.writerSheet(0).build();

        /*
        这里是将list填充到excel中。
        会去找模板上对应的数据填入，例如模板中的{list.getGoodsName}就是下面List集合中名为goodsName字段对应的数据
        new FillWrapper("list", selectOrderDTO.getSelectOrderGoodsDTOS())前面的参数是设置一个填入的list名
        后面的参数是获得的list，里面就包含了要填入的数据
        .fill()主要就是将数据填入excel中*/
//        excelWriter.fill(new FillWrapper(list), fillConfig, writeSheet);
        excelWriter.fill(new FillWrapper( dataVo.getT1Z01Vo().getList()), fillConfig, writeSheet0);
    }

    /**
     * 判断是否为空， 2个总计值都判断 为0 时， 返回 备注
     * @param list
     * @return
     */
    public static ExcelFillVo checkT7Remark(List<FinalF03ItemVo> list) {
        if(!list.isEmpty()) {
            return null;
        }

        FinalF03ItemVo itemVo = list.get(0);

        String valNum1 = FinalY22Utils.strFormaTtoNum(itemVo.getTotal());
        String valNum2 = FinalY22Utils.strFormaTtoNum(itemVo.getTotal2());

        String remark = "备注：本部门没有一般公共预算财政拨款“三公”经费收入，也没有一般公共预算财政拨款“三公”经费支出，故本表无数据。";
        BigDecimal total =  BigDecimal.ZERO;
        BigDecimal total2 =  BigDecimal.ZERO;

        if(StringUtils.isNotBlank(valNum1) ) {
            total =  new BigDecimal(itemVo.getTotal());
        }

        if(StringUtils.isNotBlank(valNum2) ) {
            total2 =  new BigDecimal(itemVo.getTotal2());
        }

        if(total.compareTo(BigDecimal.ZERO) != 0 && total2.compareTo(BigDecimal.ZERO) != 0 ) {
            ExcelFillVo fillVo = new ExcelFillVo();
            fillVo.setRemark(remark);
            return fillVo;
        }

        return null;
    }


    /**
     * 设置 表8的 备注
     * @param list
     * @return
     */
    public static ExcelFillVo checkT8Remark(List<FinalZ09ItemVo> list) {
        String remark = "备注：本部门没有政府性基金预算财政拨款收入，也没有政府性基金预算财政拨款支出，故本表无数据。";

        if(list.isEmpty()) {
            ExcelFillVo fillVo = new ExcelFillVo();
            fillVo.setRemark(remark);
            return fillVo;
        }

        return null;
    }

    /**
     * 设置 表9的备注
     * @param list
     * @return
     */
    public static ExcelFillVo checkT9Remark(List<FinalZ11ItemVo> list) {
        String remark = "备注：本部门没有国有资本经营预算财政拨款收入，也没有国有资本经营预算财政拨款支出，故本表无数据。";

        if(list.isEmpty()) {
            ExcelFillVo fillVo = new ExcelFillVo();
            fillVo.setRemark(remark);
            return fillVo;
        }

        return null;
    }

}
