package com.keyware.shandan.bianmu.export;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.keyware.shandan.bianmu.entity.MetadataBasicVo;
import com.keyware.shandan.bianmu.service.MetadataService;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.frame.config.component.AppContext;
import com.keyware.shandan.system.entity.SysOrg;
import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.SysUserService;
import org.apache.poi.ss.usermodel.Font;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class MetaTableExport extends ExportProgress {
    private final MetadataBasicVo metadata;
    private final String fileName;
    private final MetadataService metadataService;
    private final SysUserService userService;

    // 所有行的集合
    private final List<List<String>> rowList = new ArrayList<>();
    // 字段列名集合
    private final List<String> colNameList = new ArrayList<>();
    private final List<Map<String, Object>> datas = new ArrayList<>();
    private Consumer<List<Map<String, Object>>> queryHandler;
    private boolean isDone = false;

    public MetaTableExport(String userId, MetadataBasicVo metadata) {
        super(userId);
        this.userService = AppContext.getContext().getBean(SysUserService.class);
        this.metadataService = AppContext.getContext().getBean(MetadataService.class);
        this.metadata = metadata;
        String name = metadata.getMetadataComment();
        if (!StringUtils.hasText(name)) {
            name = metadata.getMetadataName();
        }
        fileName = tempDir + File.separator + name + ".xlsx";
    }

    @Override
    public void run() {
        this.setTitle("正在读取数据表信息");
        JSONArray colsArray = metadataService.getColumns(metadata.getId());

        // 添加第一行，字段列名注释集合，当做表格的第一行
        rowList.add(colsArray.stream().map((json) -> {
            JSONObject field = (JSONObject) json;
            String colName = field.getString("columnName");
            colNameList.add(colName);
            return colName;
        }).collect(Collectors.toList()));
        rowList.add(colsArray.stream().map((json) -> {
            JSONObject field = (JSONObject) json;
            return field.getString("comment");
        }).collect(Collectors.toList()));


        try {
            this.setTitle("正在查询数据");
            this.autoAddStep();
            this.queryHandler.accept(this.datas);
            handleResult();


            File file = new File(fileName);
            if (file.exists()) {
                file.delete();
            }
            List<List<String>> rows = CollUtil.newArrayList(rowList);
            //通过工具类创建writer
            BigExcelWriter writer = ExcelUtil.getBigWriter(file);

            this.setTitle("正在写入缓存");
            this.autoAddStep();
            // 添加表头
            addTableHeader(writer);
            //一次性写出内容
            writer.write(rows, true);

            this.setTitle("正在写入文件");
            this.autoAddStep();
            //写入文件后关闭writer，释放内存
            writer.close();

            this.autoAddStep();
            this.setTitle("数据文件准备完毕，开始下载");
            isDone = true;
        } catch (Exception e) {
            e.printStackTrace();
            this.error = true;
            this.setTitle("准备数据时出现异常");
            this.clean();
        }
    }

    private void addTableHeader(BigExcelWriter writer) {
        SysUser user = userService.getById(getUserId());
        SysOrg org = user.getOrg();
        String tableName = metadata.getMetadataComment();
        if (!StringUtils.hasText(tableName)) {
            tableName = metadata.getMetadataName();
        }
        int middleOffset = Math.max(colNameList.size() / 2, 1);
        int rowIndex = writer.getCurrentRow();

        writer.merge(rowIndex, rowIndex + 1, 0, 0, "时间", true)
                .merge(rowIndex, rowIndex + 1, 1, middleOffset - 1, DateUtil.formatDateTime(new Date()), true)
                .merge(rowIndex, rowIndex + 1, middleOffset, middleOffset, "表名", true)
                .merge(rowIndex, rowIndex + 1, middleOffset + 1, colNameList.size() - 1, tableName, true)
                // 另起一行
                .passRows(2)
                .merge(rowIndex + 2, rowIndex + 3, 0, 0, "姓名", true)
                .merge(rowIndex + 2, rowIndex + 3, 1, middleOffset - 1, user.getUserName(), true)
                .merge(rowIndex + 2, rowIndex + 3, middleOffset, middleOffset, "部门", true)
                .merge(rowIndex + 2, rowIndex + 3, middleOffset + 1, colNameList.size() - 1, org.getOrgName(), true)
                .passRows(2);
    }

    @Override
    public long getStepTotal() {
        return 4;
    }

    @Override
    public String getDownloadPath() {
        return this.fileName;
    }

    public void handleResult() {
        for (Map<String, Object> data : this.datas) {
            // 遍历字段列名，获取对应数据并拼接成列的集合
            List<String> cells = colNameList.stream().map(col -> {
                Object value = data.get(col);
                value = value == null ? "" : value;
                return String.valueOf(value);
            }).collect(Collectors.toList());
            rowList.add(cells);
        }
    }

    public void setQueryHandler(Consumer<List<Map<String, Object>>> handler) {
        this.queryHandler = handler;
    }

    @Override
    public boolean getIsDone() {
        return isDone;
    }
}
