package com.qmth.jkserver.templete.syncCloudMarkData;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.qmth.jkserver.constant.SpringContextHolder;
import com.qmth.jkserver.constant.SystemConstant;
import com.qmth.jkserver.core.SystemResult;
import com.qmth.jkserver.core.exception.JkServerException;
import com.qmth.jkserver.enums.TaskResultEnum;
import com.qmth.jkserver.enums.UploadFileEnum;
import com.qmth.jkserver.model.ExamTask;
import com.qmth.jkserver.model.User;
import com.qmth.jkserver.service.ExamTaskService;
import com.qmth.jkserver.templete.callback.CallbackSyncCloudMark;
import com.qmth.jkserver.util.FileStoreUtil;
import com.qmth.jkserver.util.ResultUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * @Description: 异步同步云阅卷模版
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/3/29
 */
public abstract class AsyncCloudMarkTaskTemplete {
    private final static Logger log = LoggerFactory.getLogger(AsyncCloudMarkTaskTemplete.class);

    public static final String BEGIN_TITLE = "->开始准备同步";
    public static final String EXCEPTION_TITLE = "->数据处理发生异常!";
    public static final String EXCEPTION_DATA = "错误信息:";
    public static final String FINISH_TITLE = "->数据处理结束，共处理了";
    public static final String FINISH_SIZE = "条数据";
    public static final String TXT_PREFIX = ".txt";
    public static final String EXCEPTION_CREATE_TXT_TITLE = "->创建导出日志时发生异常!";

    /**
     * 同步云阅卷数据
     *
     * @param map
     * @return
     * @throws IOException
     * @throws Exception
     */
    @Async
    public abstract SystemResult cloudMarkTask(Map<String, Object> map, CallbackSyncCloudMark callbackSyncCloudMark) throws IOException, Exception;

    /**
     * 创建txt文件
     *
     * @param examTask
     * @param user
     */
    public void createTxt(ExamTask examTask, User user) {
        ExamTaskService examTaskService = SpringContextHolder.getBean(ExamTaskService.class);
        ByteArrayOutputStream out = null;
        InputStream inputStream = null;
        try {
            LocalDateTime nowTime = LocalDateTime.now();
            StringJoiner stringJoiner = new StringJoiner("");
            stringJoiner.add(UploadFileEnum.FILE.getTitle()).add(File.separator);
            stringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
                    .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                    .add(String.format("%02d", nowTime.getDayOfMonth()))
                    .add(File.separator).add(SystemConstant.getNanoId()).add(TXT_PREFIX);
            FileStoreUtil fileStoreConfig = SpringContextHolder.getBean(FileStoreUtil.class);

            out = new ByteArrayOutputStream();
            out.write(examTask.getSummary().getBytes(StandardCharsets.UTF_8));
            byte[] bookByteAry = out.toByteArray();
            inputStream = new ByteArrayInputStream(bookByteAry);

            String type = SystemConstant.OSS;
            if (fileStoreConfig.storageIsOss()) {
                InputStream inputStreamMd5 = new ByteArrayInputStream(bookByteAry);
                fileStoreConfig.ossUpload(stringJoiner.toString(), inputStream, DigestUtils.md5Hex(inputStreamMd5), fileStoreConfig.getStorageRoot());
            } else {//上传至服务器
                type = SystemConstant.LOCAL;
                File finalFile = new File(fileStoreConfig.getStorageRoot() + File.separator + stringJoiner.toString());
                if (!finalFile.exists()) {
                    finalFile.getParentFile().mkdirs();
                    finalFile.createNewFile();
                }
                FileUtils.copyInputStreamToFile(inputStream, finalFile);
            }
            JSONObject json = new JSONObject();
            json.put(SystemConstant.PATH, stringJoiner.toString());
            json.put(SystemConstant.TYPE, type);
            json.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);

            examTask.setReportFilePath(json.toJSONString());
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            StringJoiner stringJoinerSummary = new StringJoiner("").add(examTask.getSummary()).add("\n");
            stringJoinerSummary.add(MessageFormat.format("{0}{1}{2}{3}", DateUtil.format(new Date(), SystemConstant.DEFAULT_DATE_PATTERN), EXCEPTION_CREATE_TXT_TITLE, EXCEPTION_DATA, e.getMessage()));
            examTask.setSummary(stringJoinerSummary.toString());
            examTask.setResult(TaskResultEnum.ERROR);
            if (Objects.nonNull(examTask.getTotalProgress()) && Objects.nonNull(examTask.getCompleteProgress())) {
                //计算已完成的进度
                BigDecimal completeProgress = new BigDecimal(examTask.getCompleteProgress()).divide(examTask.getTotalProgress(), 2, BigDecimal.ROUND_HALF_UP);
                examTask.setProgress(completeProgress.multiply(SystemConstant.RATE_BIG_DECIMAL));
            }
            if (e instanceof JkServerException) {
                ResultUtil.error((JkServerException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        } finally {
            try {
                if (Objects.nonNull(inputStream)) {
                    inputStream.close();
                }
                if (Objects.nonNull(out)) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            examTaskService.finishExamTask(examTask, user);
        }
    }
}
