package com.ningdatech.pmapi.common.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.function.BiConsumer;

import javax.servlet.http.HttpServletResponse;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONObject;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.enumeration.ExportOptionEnum;
import com.ningdatech.pmapi.common.model.entity.ExcelExportWriter;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.wflow.workflow.enums.ProcessStatusEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.http.HttpStatus;

import com.alibaba.fastjson.JSON;
import com.ningdatech.basic.model.ApiResponse;
import com.ningdatech.basic.util.StrPool;

import cn.hutool.poi.excel.ExcelUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;

/**
 * <p>
 * ExcelDownUtil
 * </p>
 *
 * @author WendyYang
 * @since 00:48 2022/11/5
 */
@Slf4j
public class ExcelDownUtil {

    private static String encodeName(String name) {
        String fileName;
        try {
            fileName = URLEncoder.encode(name, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("文件名编码异常：", e);
            fileName = UUID.randomUUID().toString().replace("-", "");
        }
        return fileName;
    }

    @SneakyThrows
    private static <T> void down(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) {
        response.setCharacterEncoding("utf-8");
        try {
            consumer.accept(response, param);
        } catch (Exception e) {
            log.error("文件导出失败：", e);
            response.reset();
            response.setContentType(StrPool.CONTENT_TYPE);
            ApiResponse<Void> res = ApiResponse.of(HttpStatus.SC_BAD_REQUEST, "导出失败", null);
            response.setStatus(HttpStatus.SC_BAD_REQUEST);
            response.getWriter().println(JSON.toJSONString(res));
        }
    }

    public static <T> void downXls(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) {
        response.setContentType(ExcelUtil.XLS_CONTENT_TYPE);
        down(response, param, consumer);
    }

    public static <T> void downXlsx(HttpServletResponse response, T param, BiConsumer<HttpServletResponse, T> consumer) {
        response.setContentType(ExcelUtil.XLSX_CONTENT_TYPE);
        down(response, param, consumer);
    }

    public static void setFileName(String fileName, HttpServletResponse response) {
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".xls");
    }

    public static void excelExportFile(HttpServletResponse response, ExcelExportWriter excelExport) {
        try {
            if (Objects.isNull(excelExport)) {
                throw new BizException("导出失败！");
            }
            setExportResponseHeader(excelExport.getFileName(), response);

            ExcelWriter writer = null;
            //是否启用头部属性、头部属性类不能为空
            if (Objects.nonNull(excelExport.getHeadPropertyFlag()) && excelExport.getHeadPropertyFlag() && Objects.nonNull(excelExport.getHeadPropertyClass())) {
                writer = EasyExcel.write(response.getOutputStream(), excelExport.getHeadPropertyClass()).build();
            }else {
                writer = EasyExcel.write(response.getOutputStream()).build();
            }
            int sheetNum = 0;
            if (CollectionUtils.isNotEmpty(excelExport.getSheets())){
                sheetNum = excelExport.getSheets().size();
            }else if (CollectionUtils.isNotEmpty(excelExport.getHeads())) {
                sheetNum = excelExport.getHeads().size();
            }else if (CollectionUtils.isNotEmpty(excelExport.getDatas())) {
                sheetNum = excelExport.getDatas().size();
            }

            if (sheetNum == 0){
                sheetNum = 1;
            }

            for (int i = 0; i < sheetNum; i++) {
                WriteSheet sheet = EasyExcel.writerSheet(i).automaticMergeHead(false).build();
                if (CollectionUtils.isNotEmpty(excelExport.getSheets())){
                    sheet.setSheetName(excelExport.getSheets().get(i));
                }
                if (CollectionUtils.isNotEmpty(excelExport.getHeads())){
                    sheet.setHead(excelExport.getHeads().get(i));
                }

                if (CollectionUtils.isNotEmpty(excelExport.getDatas())) {
                    writer.write((Collection<?>) ((List)excelExport.getDatas()).get(i), sheet);
                }else {
                    writer.write((Collection<?>) null, sheet);
                }
            }
            // 最后 finish
            if (null != writer) {
                writer.finish();
            }
        }catch (Exception e){
            log.error("export file error!", e);
            throw new BizException("导出失败！");
        }
    }
    public static void setExportResponseHeader(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        // 设置响应头和保存文件名
        response.setContentType(ExcelUtil.XLS_CONTENT_TYPE);
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodeName(fileName) + ".xls");
    }

    public static List<List<String>> getExportDatas(List<ExportOptionEnum> columnList, List<Project> projects) {

        // 表体行数据集合
        List<List<String>> rowList = Lists.newArrayList();
        for (ExportOptionEnum column : columnList) {
            List<String> columnValues = Lists.newArrayList();
            columnValues.add(column.getDesc());
            projects.stream().sorted(Comparator.comparing(Project::getId)).forEach(record -> {
                String s = JSON.toJSONString(record);
                JSONObject jsonObject = JSON.parseObject(s);
                String columnValue = null;
                if (column.name().equals(ExportOptionEnum.processStatusName.name())){
                    columnValue = ProcessStatusEnum.getDescByCode(record.getProcessStatus());
                }else if (column.name().equals(ExportOptionEnum.processLaunchTime.name())){
                    columnValue = NdDateUtils.format(record.getCreateOn(), "yyyy-MM-dd HH:mm");
                }else if (column.name().equals(ExportOptionEnum.processHandleTime.name())){
                    columnValue = NdDateUtils.format(record.getUpdateOn(), "yyyy-MM-dd HH:mm");
                }else {
                    columnValue = String.valueOf(jsonObject.get(column.toString()));
                }
                columnValues.add(columnValue);
            });
            rowList.add(columnValues);
        }
        return rowList;
    }

}
