package com.bofeng.excel;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.ExcelColumnProperty;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.excel.util.TypeUtil;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.*;
import net.sf.cglib.beans.BeanMap;
import org.joda.time.DateTime;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Getter
@Setter
public class ExcelBuilder {

    private List<List<?>> sheetList = Lists.newArrayList();
    private List<Class> sheetClazzList = Lists.newArrayList();
    private List<String> sheetNameList = Lists.newArrayList();

    public <T> ExcelBuilder writeSheet(Class<T> clazz, List<T> data, String sheetName) {
        sheetList.add(data);
        sheetClazzList.add(clazz);
        sheetNameList.add(sheetName);
        return this;
    }

    public <T> ExcelBuilder writeSheet(Class<T> clazz, List<T> data) {
        return writeSheet(clazz, data, "");
    }

    @SneakyThrows
    public void export(HttpServletResponse response) {
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(("file.xlsx").getBytes(), "iso-8859-1"));
        try (OutputStream outputStream = response.getOutputStream()) {

            ExcelWriter writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLSX);

            var z = 0;
            for (val dataBean : sheetList) {
                //建立Sheet
                Sheet sheet = new Sheet(z + 1, 0);
                if (!Strings.isNullOrEmpty(sheetNameList.get(z))) {
                    sheet.setSheetName(sheetNameList.get(z));
                } else {
                    sheet.setSheetName("Sheet" + (z + 1));
                }

                //获取表头注解
                ExcelHeadProperty2 head = new ExcelHeadProperty2<>(sheetClazzList.get(z));

                //获取数据
                List<List<String>> data = new ArrayList<>();
                for (Object d : dataBean) {
                    BeanMap beanMap = BeanMap.create(d);

                    List<String> item = new ArrayList<>();
                    for (Object obj : head.getColumnPropertyList()) {
                        ExcelColumnProperty excelHeadProperty = (ExcelColumnProperty) obj;
                        String cellValue = getFieldStringValue(beanMap, excelHeadProperty.getField().getName(),
                                excelHeadProperty.getFormat());
                        item.add(cellValue);
                    }
                    data.add(item);
                }

                //构造表头
                List<List<String>> h = Lists.newArrayList();
                int size = 0;
                int trows = head.getRowNum();
                for (int i = 0; i < trows; i++) {
                    h.add(head.getHeadByRowNum(i));
                    if (i == 0) {
                        size = head.getHeadByRowNum(i).size();
                    }
                }
                List<List<String>> v = Lists.newArrayList();
                for (int i = 0; i < size; i++) {
                    v.add(new ArrayList<>(trows));
                }
                for (int i = 0; i < size; i++) {
                    for (int j = 0; j < trows; j++) {
                        v.get(i).add(h.get(j).get(i));
                    }
                }

                Table table = new Table(z);
                table.setHead(v);

                //以数组方式生成数据
                writer.write0(data, sheet, table);
                z++;
            }

            writer.finish();
        }
    }

    // 导出excel如果遇到 Date 格式自动格式化年月日,DateTime 格式自动格式化年月日时分秒
    public static String getFieldStringValue(BeanMap beanMap, String fieldName, String format) {
        String cellValue = null;
        Object value = beanMap.get(fieldName);
        if (value != null) {
            if (value instanceof Date) {
                cellValue = formatDate((Date)value, format);
            } else if (value instanceof DateTime) {
                cellValue = formatDate((DateTime)value, format);
            } else {
                cellValue = value.toString();
            }
        }
        return cellValue;
    }

    public static String formatDate(Date cellValue, String format) {
        SimpleDateFormat simpleDateFormat;
        if(!StringUtils.isEmpty(format)) {
            simpleDateFormat = new SimpleDateFormat(format);
        }else {
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        }
        return simpleDateFormat.format(cellValue);
    }

    public static String formatDate(DateTime cellValue, String format) {
        SimpleDateFormat simpleDateFormat;
        Date date = new Date(cellValue.getMillis());
        if(!StringUtils.isEmpty(format)) {
            simpleDateFormat = new SimpleDateFormat(format);
        }else {
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
        return simpleDateFormat.format(date);
    }
}
