package com.bonus.canteen.core.common.utils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.Function;
import java.util.function.LongFunction;
import java.util.stream.Collectors;

public class EasyExcelUtil {
   private static final Logger log = LoggerFactory.getLogger(EasyExcelUtil.class);
   private static final int MAX_SHEET_SIZE = 1000000;

   public static <T> void writeExcelByStream(OutputStream stream, Class<T> tClass, String sheetName, List<T> data, List<Converter> converters, List<String> include) {
      ExcelWriterBuilder write = EasyExcel.write(stream, tClass);
      if (ObjectUtil.isNotEmpty(converters)) {
         Iterator var7 = converters.iterator();

         while(var7.hasNext()) {
            Converter converter = (Converter)var7.next();
            write.registerConverter(converter);
         }
      }

      if (include != null) {
         write.includeColumnFiledNames(include);
      }

      write.sheet(sheetName).doWrite(data);
   }

   public static <T> void writeExcelByStreamIncludeWrite(OutputStream stream, Class<T> tClass, String sheetName, List<T> data, List<String> includeColumnFiledNames) {
      ((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)EasyExcel.write(stream, tClass).registerConverter(new LongStringConverter())).registerConverter(new CustomLocalDateStringConverter())).registerConverter(new CustomLocalDateConverter())).includeColumnFiledNames(includeColumnFiledNames)).sheet(sheetName).doWrite(data);
   }

   public static <T> void writeExcelByDownLoad(HttpServletResponse response, String fileName, Class<T> tClass, String sheetName, List<T> data) throws IOException {
      writeExcelByDownLoad(response, fileName, tClass, sheetName, data, new ArrayList(), (List)null);
   }

   public static <T> void writeExcelByDownLoad(HttpServletResponse response, String fileName, Class<T> tClass, String sheetName, List<T> data, List<Converter> converters) throws IOException {
      writeExcelByDownLoad(response, fileName, tClass, sheetName, data, converters, (List)null);
   }

   public static <T> void writeExcelByDownLoad(HttpServletResponse response, String fileName, Class<T> tClass, String sheetName, List<T> data, List<Converter> converters, List<String> include) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      writeExcelByStream(response.getOutputStream(), tClass, sheetName, data, converters, include);
   }

   public static <T> void writeExcelByDownLoadDynamic(HttpServletResponse response, String fileName, String sheetName, List<List<String>> head, List<List<String>> data) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      ((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)EasyExcel.write(response.getOutputStream()).registerConverter(new CustomNumberConverter())).registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))).head(head)).sheet(sheetName).doWrite(data);
   }

   public static <T> void writeExcelByDownLoadDynamic(HttpServletResponse response, String fileName, String sheetName, List<List<String>> head, List<List<String>> data, File tmpFile) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      ((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)EasyExcel.write(tmpFile).registerConverter(new CustomNumberConverter())).registerWriteHandler(new SimpleColumnWidthStyleStrategy(20))).head(head)).sheet(sheetName).doWrite(data);
   }

   public static <T> void writeExcelByDownLoadIncludeWrite(HttpServletResponse response, String fileName, Class<T> tClass, String sheetName, List<T> data, List<String> includeColumnFiledNames) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      writeExcelByStreamIncludeWrite(response.getOutputStream(), tClass, sheetName, data, includeColumnFiledNames);
   }

   public static <T> void writeExcelByDownLoadIncludeWriteByPage(HttpServletResponse response, String fileName, String sheetName, Class<T> tClass, List<String> includeColumnFiledNames, LongFunction<Collection<T>> dataQueryFunc) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replace("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      ExcelWriter excelWriter = ((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)EasyExcelFactory.write(response.getOutputStream()).registerConverter(new LongStringConverter())).registerConverter(new CustomLocalDateStringConverter())).registerConverter(new CustomLocalDateConverter())).includeColumnFiledNames(includeColumnFiledNames)).build();
      writeExcelByDownLoadIncludeWriteByPage(excelWriter, sheetName, tClass, dataQueryFunc, (Function)null);
   }

   public static <T> void writeExcelByDownLoadIncludeWriteByPage(ExcelWriter excelWriter, String sheetName, Class<T> tClass, LongFunction<Collection<T>> dataQueryFunc, Function<T, String> sheetNameFunc) {
      int currentTotal = 0;
      WriteSheet writeSheet = null;
      Collection<T> data = null;
      Map<String, List<T>> sheetNameGroup = null;
      List<String> sheetNameList = CollUtil.newArrayList(new String[0]);

      do {
         data = (Collection)dataQueryFunc.apply((long)currentTotal);
         if (sheetNameFunc != null) {
            sheetNameGroup = (Map)data.stream().collect(Collectors.groupingBy(sheetNameFunc));
         } else {
            int newSheetNo = (currentTotal + data.size()) / 1000000;
            sheetNameGroup = MapUtil.newHashMap();
            ((Map)sheetNameGroup).put(newSheetNo == 0 ? sheetName : sheetName + "_" + newSheetNo, CollUtil.newArrayList(data));
         }

         Iterator var14 = ((Map)sheetNameGroup).entrySet().iterator();

         while(var14.hasNext()) {
            Map.Entry<String, List<T>> groupEntry = (Map.Entry)var14.next();
            String newSheetName = (String)groupEntry.getKey();
            int newSheetNo;
            if (!sheetNameList.contains(newSheetName)) {
               newSheetNo = sheetNameList.size();
               sheetNameList.add(newSheetName);
            } else {
               newSheetNo = sheetNameList.indexOf(newSheetName);
            }

            writeSheet = ((ExcelWriterSheetBuilder)((ExcelWriterSheetBuilder)((ExcelWriterSheetBuilder)EasyExcelFactory.writerSheet(newSheetNo, newSheetName).head(tClass)).needHead(true)).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())).build();
            excelWriter.write((Collection)groupEntry.getValue(), writeSheet);
         }

         currentTotal += CollUtil.size(data);
      } while(!CollUtil.isEmpty(data));

      excelWriter.finish();
   }

   public static void downloadExcel(HttpServletResponse response, Object mainInfo, Object detailList, String fileTitle, InputStream inputStream) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileName = URLEncoder.encode(fileTitle, "UTF-8").replaceAll("\\+", "%20");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
      ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
      WriteSheet writeSheet = EasyExcel.writerSheet().build();
      excelWriter.fill(mainInfo, writeSheet);
      excelWriter.fill(detailList, writeSheet);
      excelWriter.finish();
   }

   public static void writeExcelMerge(HttpServletResponse response, String fileName, Class<?> clazz, List<?> list, String sheetName, List<CellWriteHandler> cellWriteHandlerList, File tempFile) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      ExcelWriterBuilder excelWriterBuilder = (ExcelWriterBuilder)EasyExcel.write(tempFile, clazz).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
      if (!CollectionUtils.isEmpty(cellWriteHandlerList)) {
         Iterator var9 = cellWriteHandlerList.iterator();

         while(var9.hasNext()) {
            CellWriteHandler cellWriteHandler = (CellWriteHandler)var9.next();
            excelWriterBuilder.registerWriteHandler(cellWriteHandler);
         }
      }

      excelWriterBuilder.sheet(sheetName).doWrite(list);
   }

   public static void writeExcelMergeDynamicColumns(HttpServletResponse response, List<String> includeColumnFiledNames, String fileName, Class<?> clazz, List<?> list, String sheetName, List<CellWriteHandler> cellWriteHandlerList, File tempFile) throws IOException {
      response.setContentType("application/json");
      response.setCharacterEncoding("utf-8");
      String fileNameEnCode = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "+");
      response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameEnCode + ".xlsx");
      ExcelWriterBuilder excelWriterBuilder = (ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)((ExcelWriterBuilder)EasyExcelFactory.write(tempFile, clazz).registerConverter(new LongStringConverter())).registerConverter(new CustomLocalDateStringConverter())).registerConverter(new CustomLocalDateConverter())).includeColumnFiledNames(includeColumnFiledNames)).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy());
      if (!CollectionUtils.isEmpty(cellWriteHandlerList)) {
         Iterator var10 = cellWriteHandlerList.iterator();

         while(var10.hasNext()) {
            CellWriteHandler cellWriteHandler = (CellWriteHandler)var10.next();
            excelWriterBuilder.registerWriteHandler(cellWriteHandler);
         }
      }

      excelWriterBuilder.sheet(sheetName).doWrite(list);
   }
}
