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.distributed.print.business.service.TeachCourseService;
import com.qmth.teachcloud.common.bean.dto.DataPermissionRule;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.entity.BasicRoleDataPermission;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.LocalCatalogEnum;
import com.qmth.teachcloud.common.enums.UploadFileEnum;
import com.qmth.teachcloud.common.service.BasicRoleDataPermissionService;
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 org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
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;

    @Resource
    BasicRoleDataPermissionService basicRoleDataPermissionService;

    @Resource
    TeachCourseService teachCourseService;

    /**
     * 同步成绩查询列表
     *
     * @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) {
        if (semesterId == null) {
            throw ExceptionResultEnum.ERROR.exception("请选择学期");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(sysUser.getSchoolId(), sysUser.getId(), ServletUtil.getRequest().getServletPath());
        IPage<TSyncExamStudentScoreResult> list = tSyncExamStudentScoreMapper.list(iPage, sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode, dpr);
        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 sysUser
     * @param semesterId
     * @param clazzId
     * @param courseCode
     * @return
     */
    @Override
    public List<TSyncExamStudentScoreResult> export(SysUser sysUser, Long semesterId, Long examId, Long clazzId, String courseCode, String servletPath) {
        Long schoolId = sysUser.getSchoolId();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, sysUser.getId(), servletPath);
        return tSyncExamStudentScoreMapper.export(schoolId, semesterId, examId, clazzId, courseCode, dpr);
    }

    /**
     * 成绩导出计数
     *
     * @param schoolId
     * @param semesterId
     * @param clazzId
     * @param courseCode
     * @return
     */
    @Override
    public int exportCount(Long schoolId, Long semesterId, Long examId, Long clazzId, String courseCode) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        DataPermissionRule dpr = basicRoleDataPermissionService.findDataPermission(schoolId, sysUser.getId(), ServletUtil.getRequest().getServletPath());
        return tSyncExamStudentScoreMapper.exportCount(schoolId, semesterId, examId, clazzId, courseCode, dpr);
    }

    /**
     * 创建动态轨迹图
     *
     * @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("");
            if (!oss && Objects.nonNull(dictionaryConfig.fssPublicDomain()) && !StringUtils.isBlank(dictionaryConfig.fssPublicDomain().getConfig()) && !dictionaryConfig.fssPublicDomain().getConfig().startsWith(SystemConstant.START_PARENT)) {
                stringJoiner.add(dictionaryConfig.fssPublicDomain().getConfig()).add(File.separator);
            }
            stringJoiner = SystemConstant.getDirName(stringJoiner, UploadFileEnum.FILE, true);
            stringJoiner.add(SystemConstant.getNanoId()).add(File.separator);

            String dirName = stringJoiner.toString();
            List<String> trailUrlsList = tSyncExamStudentScore.getTrailUrls();

            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, oss ? SystemConstant.OSS : SystemConstant.LOCAL);
                    } 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(SystemConstant.ORG_SPLIT) + 1);
                        StringJoiner dirJpgName = new StringJoiner("");
                        dirJpgName.add(dirName).add(tSyncExamStudentScore.getExamNumber()).add(File.separator).add("sheet").add(File.separator).add(sheetName);

                        File fileSource = SystemConstant.getFileTempDirVar(dirJpgName.toString(), null);
                        fileSource = HttpUtil.httpDownload(url, fileSource.getPath());
                        fileSourceList.add(fileSource);
                        JSONObject sheetObject = new JSONObject();
                        sheetObject.put(SystemConstant.PATH, dirJpgName.toString());
                        String jpgFileMd5 = DigestUtils.md5Hex(new FileInputStream(fileSource));
                        if (oss || (!oss && dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT))) {
                            fileStoreUtil.ossUpload(dirJpgName.toString(), fileSource, jpgFileMd5, UploadFileEnum.FILE.getFssType());
                            sheetObject.put(SystemConstant.TYPE, oss ? SystemConstant.OSS : SystemConstant.LOCAL);
                        } else {
                            fileStoreUtil.localUpload(dirJpgName.toString(), new FileInputStream(fileSource), jpgFileMd5, LocalCatalogEnum.LOCAL_FILE);
                            sheetObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                        }
                        sheetObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
                        jsonImageSourcePathArray.add(sheetObject);

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

                        StringJoiner dirTargetJpgName = new StringJoiner("");
                        dirTargetJpgName.add(dirName).add(tSyncExamStudentScore.getExamNumber()).add(File.separator).add("trail").add(File.separator).add(sheetName);
                        File fileTarget = SystemConstant.getFileTempDirVar(dirTargetJpgName.toString(), null);

                        ImageTrajectoryUtil.createImage(fileSource, fileTarget, markTagJsonArray);
                        fileTargetList.add(fileTarget);
                        String dirTargetName = FileUtil.replaceSplit(dirTargetJpgName.toString());
                        String jpgTargetFileMd5 = DigestUtils.md5Hex(new FileInputStream(fileTarget));
                        jsonImageTrajectoryPathArray.add(dirTargetName);
                        if (oss || (!oss && dictionaryConfig.fssPrivateDomain().getConfig().startsWith(SystemConstant.START_PARENT))) {
                            fileStoreUtil.ossUpload(dirTargetName, fileTarget, jpgTargetFileMd5, UploadFileEnum.FILE.getFssType());
                            trailUrlsList.add(fileStoreUtil.getPrivateUrl(dirTargetName, UploadFileEnum.FILE.getFssType()));
                        } else {
                            fileStoreUtil.localUpload(dirTargetName, new FileInputStream(fileTarget), jpgTargetFileMd5, LocalCatalogEnum.LOCAL_FILE);
                            String finalUrl = null;
                            if (dirTargetName.contains(dictionaryConfig.fssPrivateDomain().getServer())) {
                                finalUrl = dirTargetName.substring(dirTargetName.indexOf(dictionaryConfig.fssPrivateDomain().getServer()), dirTargetName.length());
                            } else if (dirTargetName.contains(dictionaryConfig.fssPublicDomain().getServer())) {
                                finalUrl = dirTargetName.substring(dirTargetName.indexOf(dictionaryConfig.fssPublicDomain().getServer()), dirTargetName.length());
                            }
                            trailUrlsList.add(finalUrl);
                        }
                    }
                    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) {
                            String sheetName = url.substring(url.lastIndexOf(SystemConstant.ORG_SPLIT) + 1);
                            File fileSource = SystemConstant.getFileTempDirVar(stringJoiner.toString() + sheetName, null);
                            fileTargetList.add(fileStoreUtil.ossDownload(url, fileSource, 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 finalUrl = null;
                            if (url.contains(dictionaryConfig.fssPrivateDomain().getServer())) {
                                finalUrl = url.substring(url.indexOf(dictionaryConfig.fssPrivateDomain().getServer()), url.length());
                            } else if (url.contains(dictionaryConfig.fssPublicDomain().getServer())) {
                                finalUrl = url.substring(url.indexOf(dictionaryConfig.fssPublicDomain().getServer()), url.length());
                            }
                            trailUrlsList.add(finalUrl);
                        }
                    }
                }
            }
            tSyncExamStudentScore.setTrailUrls(trailUrlsList);
            if (!CollectionUtils.isEmpty(fileTargetList)) {
                tSyncExamStudentScore.setTrajectoryFileList(fileTargetList);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            tSyncExamStudentScore.setErrorInfo();
        } finally {
            if (oss && imageTrajectoryEnum == ImageTrajectoryEnum.PREVIEW) {
                if (!CollectionUtils.isEmpty(fileSourceList)) {
                    for (File f : fileSourceList) {
                        f.delete();
                    }
                }
                if (!CollectionUtils.isEmpty(fileTargetList)) {
                    for (File f : fileTargetList) {
                        f.delete();
                    }
                }
            } else {
                if (oss && !CollectionUtils.isEmpty(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;
        List<File> fileList = null;
        boolean oss = dictionaryConfig.sysDomain().isOss();
        try {
            if (Objects.nonNull(tSyncExamStudentScore.getTrajectoryFileList())) {
                zipFile = SystemConstant.getFileTempDirVar(SystemConstant.ZIP_PREFIX);

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

                Zip4jUtil.zipEncryptFile(zipFile.getPath(), fileList, SystemConstant.ZIP_ENCRYPT_PWD);

                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)) {
                zipFile.delete();
            }
            if (oss && !CollectionUtils.isEmpty(fileList)) {
                for (File file : fileList) {
                    file.delete();
                }
            }
        }
    }
}
