package com.qmth.themis.business.templete.impl;

import cn.hutool.core.date.DateUtil;
import com.qmth.themis.business.annotation.ExcelNote;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.RoomCodeExportDto;
import com.qmth.themis.business.service.TBExamInvigilateUserService;
import com.qmth.themis.business.templete.TaskExportCommon;
import com.qmth.themis.business.templete.TaskExportTemplete;
import com.qmth.themis.business.templete.service.TempleteLogicService;
import com.qmth.themis.business.util.JacksonUtil;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Description: 考场导出任务
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/7/20
 */
@Service
public class TaskRoomCodeExportTemplete implements TaskExportTemplete {
    private final static Logger log = LoggerFactory.getLogger(TaskRoomCodeExportTemplete.class);

    @Resource
    TempleteLogicService templeteLogicService;

    @Resource
    TBExamInvigilateUserService tbExamInvigilateUserService;

    /**
     * 考场导出模版
     *
     * @param map
     * @return
     */
    @Override
    public Result exportTask(Map<String, Object> map) throws IOException {
        log.info("开始导出考场数据");
        long start = System.currentTimeMillis();
        TaskExportCommon taskExportCommon = new TaskExportCommon(map);
        taskExportCommon.init();
        String timeFormat = taskExportCommon.getTimeFormat();
        taskExportCommon.setTxtList(new ArrayList());
        FileOutputStream fos = null;
        SXSSFWorkbook wb = null;
        File mkdir = null, file = null;
        int y = 0, min = 0;
        try {
            taskExportCommon.getTxtList().add(DateUtil.format(new Date(), timeFormat) + "->开始准备处理导出的考场数据");
            List<RoomCodeExportDto> roomCodeExportDtoList = tbExamInvigilateUserService.examInvigilateUserExport();

            boolean oss = (boolean) taskExportCommon.getOssEnv().get(SystemConstant.OSS);
            StringJoiner stringJoiner = new StringJoiner("");
            if (!oss) {
                stringJoiner.add(SystemConstant.FILES_DIR).add(File.separator);
            }
            LocalDateTime nowTime = LocalDateTime.now();
            String uploadType = String.valueOf(taskExportCommon.getOssEnv().get(SystemConstant.UPLOAD_TYPE));
            stringJoiner.add(uploadType).add(File.separator).add(String.valueOf(nowTime.getYear()))
                    .add(File.separator).add(String.valueOf(nowTime.getMonthValue()))
                    .add(File.separator).add(String.valueOf(nowTime.getDayOfMonth()));
            mkdir = new File(stringJoiner.toString());
            if (!mkdir.exists()) {
                mkdir.mkdirs();
            }
            //创建excel
            wb = new SXSSFWorkbook();
            Sheet sheet = wb.createSheet("考场导出");
            CellStyle style = wb.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER); // 水平居中格式
            style.setVerticalAlignment(VerticalAlignment.CENTER); //垂直居中
            Row row = sheet.createRow(0);
            Field[] fields = RoomCodeExportDto.class.getDeclaredFields();
            //绘制表头
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                field.setAccessible(true);
                Cell cell = row.createCell(i);
                cell.setCellValue(field.getAnnotation(ExcelNote.class).value());
                cell.setCellStyle(style);
//                sheet.setColumnWidth(i, 15 * 256);
            }
            int cellIndex = 0, max = SystemConstant.MAX_EXPORT_SIZE, size = roomCodeExportDtoList.size();
            if (max >= size) {
                max = size;
            }
            while (max <= size) {
                List subList = roomCodeExportDtoList.subList(min, max);
                //绘制数据
                for (; y < subList.size(); y++) {
                    RoomCodeExportDto roomCodeExportDto = (RoomCodeExportDto) subList.get(y);
                    int firstRow = y + 1;
                    cellIndex = 0;
                    Row sxssfRow = sheet.createRow(firstRow);
                    for (Field field : fields) {
                        field.setAccessible(true);
                        taskExportCommon.createExcelCell(sxssfRow, cellIndex, field.get(roomCodeExportDto), style);
                        cellIndex++;
                    }
                }
                map.put("max", max);
                map.put("min", min);
                map.put("size", size);
                map = templeteLogicService.execExportRoomCodeLogic(map);
                if (max == size) {
                    break;
                }
                min = max;
                max += SystemConstant.MAX_EXPORT_SIZE;
                if (max >= size) {
                    max = size;
                }
            }
            file = taskExportCommon.createExcel(mkdir.getPath());
            //写入excel并上传附件
            fos = new FileOutputStream(file);
            wb.write(fos);
            taskExportCommon.ossUpload(file);
            long end = System.currentTimeMillis();
            log.info("导出考场数据结束,============耗时============:{}秒", (end - start) / 1000);
        } catch (Exception e) {
            log.error("导出报错", e);
            taskExportCommon.exception(min, y, e, taskExportCommon.getTxtList());
        } finally {
            if (Objects.nonNull(wb)) {
                wb.dispose();
            }
            if (Objects.nonNull(fos)) {
                fos.flush();
                fos.close();
            }
            //这里写入txt文件
            taskExportCommon.writeExportResultTxt(mkdir.getPath(), taskExportCommon.getTxtList().toString(), file);
        }
        return ResultUtil.ok(Collections.singletonMap("success", true));
    }
}
