package com.qmth.distributed.print.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.distributed.print.business.bean.result.TSyncExamStudentScoreResult;
import com.qmth.distributed.print.business.entity.TSyncExamStudentScore;
import com.qmth.distributed.print.business.enums.ImageTrajectoryEnum;
import com.qmth.distributed.print.business.mapper.TSyncExamStudentScoreMapper;
import com.qmth.distributed.print.business.service.TSyncExamStudentScoreService;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.util.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 同步考生成绩表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2021-10-28
 */
@Service
public class TSyncExamStudentScoreServiceImpl extends ServiceImpl<TSyncExamStudentScoreMapper, TSyncExamStudentScore> implements TSyncExamStudentScoreService {

    @Resource
    TSyncExamStudentScoreMapper tSyncExamStudentScoreMapper;

    @Resource
    DictionaryConfig dictionaryConfig;

    @Resource
    FileStoreUtil fileStoreUtil;

    /**
     * 同步成绩查询列表
     *
     * @param iPage
     * @param semesterId
     * @param orgId
     * @param majorId
     * @param clazzId
     * @param courseCode
     * @return
     */
    @Override
    public IPage<TSyncExamStudentScoreResult> list(IPage<Map> iPage, Long semesterId, Long examId, Long clazzId, String courseCode) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        return tSyncExamStudentScoreMapper.list(iPage, sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode);
    }

    /**
     * 成绩导出
     *
     * @param schoolId
     * @param semesterId
     * @param orgId
     * @param majorId
     * @param clazzId
     * @param courseCode
     * @return
     */
    @Override
    public List<TSyncExamStudentScoreResult> export(Long schoolId, Long semesterId, Long examId, Long clazzId, String courseCode) {
        return tSyncExamStudentScoreMapper.export(schoolId, semesterId, examId, clazzId, courseCode);
    }

    /**
     * 成绩导出计数
     *
     * @param schoolId
     * @param semesterId
     * @param orgId
     * @param majorId
     * @param clazzId
     * @param courseCode
     * @return
     */
    @Override
    public int exportCount(Long schoolId, Long semesterId, Long examId, Long clazzId, String courseCode) {
        return tSyncExamStudentScoreMapper.exportCount(schoolId, semesterId, examId, clazzId, courseCode);
    }

    /**
     * 创建动态轨迹图
     *
     * @param tSyncExamStudentScore
     * @param imageTrajectoryEnum
     * @return
     */
    @Override
    public TSyncExamStudentScore createImageTrajectory(TSyncExamStudentScore tSyncExamStudentScore, ImageTrajectoryEnum imageTrajectoryEnum) {
        List<File> fileSourceList = new ArrayList<>(), fileTargetList = new ArrayList<>();
        try {
            Optional.ofNullable(tSyncExamStudentScore.getSheetUrls()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生原卷地址"));
            Optional.ofNullable(tSyncExamStudentScore.getSyncData()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生作答数据"));
            StringJoiner stringJoiner = new StringJoiner("");
            stringJoiner.add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
            List<String> trailUrlsList = tSyncExamStudentScore.getTrailUrls();
            if (Objects.isNull(tSyncExamStudentScore.getTrajectoryUrls())) {
                JSONArray jsonArray = JSONArray.parseArray(tSyncExamStudentScore.getSheetUrls());
                JSONObject syncDataJson = JSONObject.parseObject(tSyncExamStudentScore.getSyncData());
                Optional.ofNullable(syncDataJson.get("markTags")).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生轨迹坐标数据"));
                JSONObject markTagsJson = JSONObject.parseObject(syncDataJson.get("markTags").toString());
                boolean oss = dictionaryConfig.sysDomain().isOss();
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
                if (oss) {
                    jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                } else {
                    jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                }
                JSONArray jsonImageTrajectoryPathArray = new JSONArray();
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONArray markTagJsonArray = (JSONArray) markTagsJson.get(i + 1);
                    if (Objects.isNull(markTagJsonArray) || markTagJsonArray.size() == 0) {
                        continue;
                    }
                    String url = (String) jsonArray.get(i);
                    String format = url.substring(url.lastIndexOf("."), url.length());
                    LocalDateTime nowTime = LocalDateTime.now();
                    StringJoiner dirJpgName = new StringJoiner("");
                    dirJpgName.add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                            .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(tSyncExamStudentScore.getExamNumber())
                            .add(File.separator).add(SystemConstant.getUuid()).add(format);
                    File fileSource = new File(stringJoiner.toString() + dirJpgName.toString());
                    if (!fileSource.exists()) {
                        fileSource.getParentFile().mkdirs();
                        fileSource.createNewFile();
                    }
                    fileSource = HttpUtil.httpDownload(url, fileSource.getPath());
                    fileSourceList.add(fileSource);

                    StringJoiner dirTargetJpgName = new StringJoiner("");
                    dirTargetJpgName.add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                            .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(tSyncExamStudentScore.getExamNumber())
                            .add(File.separator).add(SystemConstant.getUuid()).add(format);
                    File fileTarget = new File(stringJoiner.toString() + dirTargetJpgName.toString());
                    if (!fileTarget.exists()) {
                        fileTarget.getParentFile().mkdirs();
                        fileTarget.createNewFile();
                    }

                    ImageTrajectoryUtil.createImage(fileSource, fileTarget, markTagJsonArray);
                    fileTargetList.add(fileTarget);
                    if (oss) {
                        fileStoreUtil.ossUpload(dirTargetJpgName.toString(), fileTarget, DigestUtils.md5Hex(new FileInputStream(fileTarget)), UploadFileEnum.FILE.getFssType());
                        if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                            trailUrlsList.add(fileStoreUtil.getPrivateUrl(dirTargetJpgName.toString(), UploadFileEnum.FILE.getFssType()));
                        }
                    } else {
                        if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                            trailUrlsList.add(fileTarget.getPath());
                        }
                    }
                    jsonImageTrajectoryPathArray.add(dirTargetJpgName.toString());
                }
                if (Objects.nonNull(jsonImageTrajectoryPathArray) && jsonImageTrajectoryPathArray.size() > 0) {
                    jsonObject.put(SystemConstant.PATH, jsonImageTrajectoryPathArray.toJSONString());
                    tSyncExamStudentScore.setTrajectoryUrls(jsonObject.toJSONString());
                }
            } else {
                JSONObject jsonObject = JSONObject.parseObject(tSyncExamStudentScore.getTrajectoryUrls());
                String ossType = (String) jsonObject.get(SystemConstant.TYPE);
                JSONArray jsonArray = JSONArray.parseArray(jsonObject.get(SystemConstant.PATH).toString());
                if (Objects.equals(ossType, SystemConstant.OSS)) {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        String url = (String) jsonArray.get(i);
                        if (imageTrajectoryEnum == ImageTrajectoryEnum.DOWNLOAD) {
                            fileTargetList.add(fileStoreUtil.ossDownload(url, stringJoiner.toString() + url, UploadFileEnum.FILE.getFssType()));
                        } else {
                            trailUrlsList.add(fileStoreUtil.getPrivateUrl(url, UploadFileEnum.convertToFssType((String) jsonObject.get(SystemConstant.UPLOAD_TYPE))));
                        }
                    }
                } else {
                    for (int i = 0; i < jsonArray.size(); i++) {
                        String url = (String) jsonArray.get(i);
                        if (imageTrajectoryEnum == ImageTrajectoryEnum.DOWNLOAD) {
                            fileTargetList.add(new File(stringJoiner.toString() + url));
                        } else {
                            trailUrlsList.add(stringJoiner.toString() + url);
                        }
                    }
                }
            }
            tSyncExamStudentScore.setTrailUrls(trailUrlsList);
            if (Objects.nonNull(fileTargetList) && fileTargetList.size() > 0) {
                tSyncExamStudentScore.setTrajectoryFileList(fileTargetList);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            tSyncExamStudentScore.setErrorInfo();
            if (Objects.nonNull(fileTargetList)) {
                for (File f : fileTargetList) {
                    f.delete();
                }
            }
        } finally {
            if (Objects.nonNull(fileSourceList)) {
                for (File f : fileSourceList) {
                    f.delete();
                }
            }
        }
        return tSyncExamStudentScore;
    }

    /**
     * 生成zip文件
     *
     * @param tSyncExamStudentScore
     * @throws IOException
     */
    @Override
    public void createZipFile(TSyncExamStudentScore tSyncExamStudentScore) throws IOException {
        File zipFile = null;
        OutputStream outputStream = null;
        try {
            if (Objects.nonNull(tSyncExamStudentScore.getTrajectoryFileList())) {
                StringJoiner stringJoiner = new StringJoiner("");
                stringJoiner.add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
                LocalDateTime nowTime = LocalDateTime.now();
                StringJoiner dirZipName = new StringJoiner("");
                dirZipName.add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                        .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.getUuid()).add(SystemConstant.ZIP_PREFIX);
                zipFile = new File(stringJoiner.toString() + dirZipName.toString());
                if (!zipFile.exists()) {
                    zipFile.getParentFile().mkdirs();
                    zipFile.createNewFile();
                }
                File[] files = tSyncExamStudentScore.getTrajectoryFileList().get(0).getParentFile().listFiles();
                List<File> fileList = new ArrayList<>(Arrays.asList(files));
                fileList.removeAll(tSyncExamStudentScore.getTrajectoryFileList());
                if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                    for (File file : fileList) {
                        file.delete();
                    }
                }
                FileUtil.doZip(zipFile, Arrays.asList(tSyncExamStudentScore.getTrajectoryFileList().get(0).getParentFile()));
                HttpServletResponse response = ServletUtil.getResponse();
//                response.setContentType("image/jpeg");
//                outputStream = new BufferedOutputStream(response.getOutputStream());
//                IOUtils.copy(new FileInputStream(zipFile), outputStream);
                response.reset();
                response.setHeader("Content-Disposition", "attachment;fileName=" + zipFile.getName());
                response.addHeader("Content-Length", "" + zipFile.length());
                response.setContentType("application/octet-stream;charset=UTF-8");
                outputStream = new BufferedOutputStream(response.getOutputStream());
                IOUtils.copy(new FileInputStream(zipFile), outputStream);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(outputStream)) {
                outputStream.flush();
                outputStream.close();
            }
            if (Objects.nonNull(zipFile)) {
                zipFile.delete();
            }
        }
    }
}
