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.common.contanst.Constants;
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.*;
import java.lang.reflect.Field;
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();
        taskExportCommon.setTxtList(new ArrayList());
        SXSSFWorkbook wb = null;
        StringJoiner stringJoiner = null;
        String excelFilePath = null;
        InputStream inputStream = null;
        ByteArrayOutputStream out = null;
        int min = 0, line = 0;
        try {
            taskExportCommon.getTxtList()
                    .add(DateUtil.format(new Date(), Constants.DEFAULT_DATE_PATTERN) + "->开始准备处理导出的考场数据");
            Long examId = (Long) map.get(SystemConstant.EXAM_ID);
            String roomCode = (String) map.get(SystemConstant.ROOM_CODE);
            Long userId = (Long) map.get(SystemConstant.USER_ID);
            List<RoomCodeExportDto> roomCodeExportDtoList = tbExamInvigilateUserService
                    .examInvigilateUserExport(examId, roomCode, userId, taskExportCommon.getOrgId());

            boolean oss = (boolean) taskExportCommon.getOssEnv().get(SystemConstant.OSS);
            stringJoiner = new StringJoiner("");
            if (!oss) {
                stringJoiner.add(SystemConstant.FILES_DIR).add(File.separator);
            }
            stringJoiner = SystemConstant.getDirName(stringJoiner, false);
            //创建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 rowIndex = 0, 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 (int y = 0; y < subList.size(); y++) {
                    line++;
                    rowIndex++;
                    RoomCodeExportDto roomCodeExportDto = (RoomCodeExportDto) subList.get(y);
                    cellIndex = 0;
                    Row sxssfRow = sheet.createRow(rowIndex);
                    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;
                }
            }
            //临时缓冲区
            out = new ByteArrayOutputStream();
            wb.write(out);
            byte[] bookByteAry = out.toByteArray();
            inputStream = new ByteArrayInputStream(bookByteAry);
            excelFilePath = taskExportCommon.ossUpload(inputStream, stringJoiner.toString());
            long end = System.currentTimeMillis();
            log.info("导出考场数据结束,============耗时============:{}秒", (end - start) / 1000);
        } catch (Exception e) {
            log.error("导出报错", e);
            taskExportCommon.exception(line, e, taskExportCommon.getTxtList());
        } finally {
            //这里写入txt文件
            taskExportCommon.writeExportResultTxt(stringJoiner.toString(), taskExportCommon.getTxtList().toString(),
                    excelFilePath);
            if (Objects.nonNull(wb)) {
                wb.dispose();
            }
            if (Objects.nonNull(inputStream)) {
                inputStream.close();
            }
            if (Objects.nonNull(out)) {
                out.flush();
                out.close();
            }
        }
        return ResultUtil.ok(true);
    }
}

