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

import com.alibaba.fastjson.JSON;
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.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

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

/**
 * <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;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    /**
     * 同步成绩查询列表
     *
     * @param iPage
     * @param semesterId
     * @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();
        IPage<TSyncExamStudentScoreResult> list = tSyncExamStudentScoreMapper.list(iPage, sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode);
        list.getRecords().stream().map(m -> {
            String localSheetUrls = m.getLocalSheetUrls();
            if (StringUtils.isNotBlank(localSheetUrls)) {
                List<String> trailUrlsList = new ArrayList<>();
                List<String> jsonArray = JSON.parseArray(localSheetUrls, String.class);
                for (String s : jsonArray) {
                    trailUrlsList.add(teachcloudCommonService.filePreview(s));
                }
                m.setSheetUrls(JSON.toJSONString(trailUrlsList));
            }
            return m;
        }).collect(Collectors.toList());

        return list;
    }

    /**
     * 成绩导出
     *
     * @param schoolId
     * @param semesterId
     * @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 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, boolean needSync, Long userId) {
        List<File> fileSourceList = new ArrayList<>(), fileTargetList = new ArrayList<>();
        boolean oss = dictionaryConfig.sysDomain().isOss();
        try {
            Optional.ofNullable(tSyncExamStudentScore.getSheetUrls()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生原卷地址"));
            Optional.ofNullable(tSyncExamStudentScore.getSyncData()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生作答数据"));
            StringJoiner stringJoiner = new StringJoiner("");
            stringJoiner.add(dictionaryConfig.fssLocalFileDomain().getConfig()).add(File.separator);
            List<String> trailUrlsList = tSyncExamStudentScore.getTrailUrls();

            String hostUrl = SystemConstant.getLocalFileHostByUserId(dictionaryConfig.fssLocalFileDomain().getServer(), userId);

            if (needSync || Objects.isNull(tSyncExamStudentScore.getLocalSheetUrls()) || Objects.isNull(tSyncExamStudentScore.getTrajectoryUrls())) {
                JSONArray jsonArray = JSONArray.parseArray(tSyncExamStudentScore.getSheetUrls());
                if (!jsonArray.isEmpty()) {
                    JSONObject syncDataJson = JSON.parseObject(tSyncExamStudentScore.getSyncData());
                    Optional.ofNullable(syncDataJson.get("markTags")).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("未获取到考生轨迹坐标数据"));
                    JSONObject markTagsJson = JSON.parseObject(syncDataJson.get("markTags").toString());

                    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 jsonImageSourcePathArray = new JSONArray();
                    JSONArray jsonImageTrajectoryPathArray = new JSONArray();
                    for (int i = 0; i < jsonArray.size(); i++) {
                        String url = (String) jsonArray.get(i);
                        String sheetName = url.substring(url.lastIndexOf("/") + 1);
                        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("sheet").add(File.separator).add(sheetName);
                        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);
                        JSONObject sheetObject = new JSONObject();
                        if (oss) {
                            String dirName = dirJpgName.toString().replaceAll("\\\\", "/");
                            fileStoreUtil.ossUpload(dirName, fileSource, DigestUtils.md5Hex(new FileInputStream(fileSource)), UploadFileEnum.FILE.getFssType());
                            if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                                fileStoreUtil.getPrivateUrl(dirName, UploadFileEnum.FILE.getFssType());
                            }
                            sheetObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                            sheetObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
                            sheetObject.put(SystemConstant.PATH, dirName);
                        } else {
                            if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                                String filePath = fileSource.getPath();
                            }
                            sheetObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                            sheetObject.put(SystemConstant.PATH, (stringJoiner.toString() + dirJpgName.toString()).replaceAll("\\\\", "/"));
                        }
                        jsonImageSourcePathArray.add(sheetObject);

                        // 轨迹
                        if (markTagsJson.isEmpty()) {
                            continue;
                        }
                        JSONArray markTagJsonArray = (JSONArray) markTagsJson.get(i + 1);

                        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("trail").add(File.separator).add(sheetName);
                        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) {
                            String dirTargetName = dirTargetJpgName.toString().replaceAll("\\\\", "/");
                            fileStoreUtil.ossUpload(dirTargetName, fileTarget, DigestUtils.md5Hex(new FileInputStream(fileTarget)), UploadFileEnum.FILE.getFssType());
                            if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                                trailUrlsList.add(fileStoreUtil.getPrivateUrl(dirTargetName, UploadFileEnum.FILE.getFssType()));
                            }
                            jsonImageTrajectoryPathArray.add(dirTargetName);
                        } else {
                            if (imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                                String filePath = fileTarget.getPath();
                                String trailUrl;
                                if (filePath.startsWith("/")) {
                                    trailUrl = hostUrl + filePath;
                                } else {
                                    trailUrl = hostUrl + File.separator + filePath;
                                }
                                trailUrlsList.add(trailUrl);
                            }
                            jsonImageTrajectoryPathArray.add((stringJoiner.toString() + dirTargetJpgName.toString()).replaceAll("\\\\", "/"));
                        }
                    }
                    if (!jsonImageSourcePathArray.isEmpty()) {
                        tSyncExamStudentScore.setLocalSheetUrls(jsonImageSourcePathArray.toJSONString());
                    }
                    if (!jsonImageTrajectoryPathArray.isEmpty()) {
                        jsonObject.put(SystemConstant.PATH, jsonImageTrajectoryPathArray.toJSONString());
                        tSyncExamStudentScore.setTrajectoryUrls(jsonObject.toJSONString());
                    }
                    this.updateById(tSyncExamStudentScore);
                }
            } 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(url));
                        } else {
                            String trailUrl;
                            if (url.startsWith("/")) {
                                trailUrl = hostUrl + url;
                            } else {
                                trailUrl = hostUrl + File.separator + url;
                            }
                            trailUrlsList.add(trailUrl);
                        }
                    }
                }
            }
            tSyncExamStudentScore.setTrailUrls(trailUrlsList);
            if (!fileTargetList.isEmpty()) {
                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 (oss && 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(dictionaryConfig.fssLocalFileDomain().getConfig()).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();
                }

                List<File> fileList = tSyncExamStudentScore.getTrajectoryFileList();
                if (fileList.isEmpty()) {
                    throw ExceptionResultEnum.ERROR.exception("没有可下载文件");
                }

                FileUtil.doZip(zipFile, fileList);

                if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                    for (File file : fileList) {
                        file.delete();
                    }
                }

                HttpServletResponse response = ServletUtil.getResponse();
                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);
            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
        } finally {
            if (Objects.nonNull(outputStream)) {
                outputStream.flush();
                outputStream.close();
            }
            if (Objects.nonNull(zipFile)) {
                System.out.println(zipFile.delete());
            }
        }
    }
}
