/*
 * *************************************************
 * Copyright (c) 2018 QMTH. All Rights Reserved.
 * Created by Deason on 2018-07-06 15:33:50.
 * *************************************************
 */

package cn.com.qmth.examcloud.core.questions.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;

import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.core.questions.base.BeanCopierUtil;
import cn.com.qmth.examcloud.core.questions.base.CommonUtils;
import cn.com.qmth.examcloud.core.questions.base.IoUtils;
import cn.com.qmth.examcloud.core.questions.base.Model;
import cn.com.qmth.examcloud.core.questions.base.exception.PaperException;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperDetailUnitRepo;
import cn.com.qmth.examcloud.core.questions.dao.PaperRepo;
import cn.com.qmth.examcloud.core.questions.dao.QuesRepo;
import cn.com.qmth.examcloud.core.questions.dao.entity.Course;
import cn.com.qmth.examcloud.core.questions.dao.entity.Paper;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetail;
import cn.com.qmth.examcloud.core.questions.dao.entity.PaperDetailUnit;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
import cn.com.qmth.examcloud.core.questions.dao.entity.QuestionAudio;
import cn.com.qmth.examcloud.core.questions.service.config.SysProperty;
import cn.com.qmth.examcloud.core.questions.service.impl.CourseService;
import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;

/**
 * 复制试卷接口类
 */
@Service
public class ClonePaperService {
    private static final Logger log = LoggerFactory.getLogger(ClonePaperService.class);
    @Autowired
    private PaperService paperService;
    @Autowired
    private PaperRepo paperRepo;
    @Autowired
    private PaperDetailRepo paperDetailRepo;
    @Autowired
    private PaperDetailUnitRepo paperDetailUnitRepo;
    @Autowired
    private QuestionAudioService questionAudioService;
//    @Autowired
//    private QuesPkgPathRepo quesPkgPathRepo;
    @Autowired
    private QuesRepo quesRepo;
    @Autowired
    private QuesTypeNameService quesTypeNameService;
    @Autowired
    private SysProperty sysProperty;
    @Autowired
    private CourseService courseService;

    /**
     * 克隆试卷
     *
     * @param paperId   待复制的试卷ID
     * @param paperName 新试卷名称
     * @param courseNo  课程编码
     * @param user      当前用户
     * @return
     */
    public void clonePaper(String paperId, String paperName, String courseNo, User user) throws PaperException {
        if (StringUtils.isBlank(paperId)) {
            throw new PaperException("待复制的试卷ID不能为空！");
        }

        if (StringUtils.isBlank(courseNo)) {
            throw new PaperException("课程编码不能为空！");
        }

        if (user == null) {
            throw new PaperException("当前用户信息不能为空！");
        }

        if (user.getRootOrgId() == null) {
            throw new PaperException("当前用户的顶级机构ID不能为空！");
        }

        if (StringUtils.isBlank(paperName)) {
            throw new PaperException("新试卷名称不能为空！");
        }

        boolean existName = paperService.checkPaperName(paperName, user.getRootOrgId().toString());
        if (existName) {
            throw new PaperException("当前试卷名称重复，请重新命名！");
        }

        Paper oldPaper = Model.of(paperRepo.findById(paperId));
        if (oldPaper == null) {
            throw new PaperException("待复制的试卷不存在！");
        }

        Course course = courseService.getCourse(user.getRootOrgId(), courseNo);
        if (course == null) {
            throw new PaperException("课程信息不存在！");
        }

        //复制原试卷的所有试题信息
        Map<PaperDetail, List<PaperDetailUnit>> detailMaps = this.copyPaperDetails(oldPaper, user, course);

        //处理试题的音频(下载上传到云存储)
        try {
            this.dealQuestionAudios(detailMaps, user.getDisplayName());
        } catch (Exception e) {
            throw new PaperException("复制音频失败！");
        }

        //复制原试卷的信息
        Paper newPaper = this.copyPaper(oldPaper, paperName, course, user);
        newPaper.setTitle(paperName);
        //保存新试卷
        paperRepo.save(newPaper);
        try {
            //保存新试卷的所有试题信息
            this.savePaperDetails(detailMaps, newPaper, user);
        } catch (Exception e) {
            //如果试题保存失败，则还原数据
            paperService.deletePapers(Lists.newArrayList(newPaper.getId()),user);
            throw new PaperException("克隆试卷失败！");
        }
    }

    /**
     * 保存新试卷的所有试题信息
     */
    private void savePaperDetails(Map<PaperDetail, List<PaperDetailUnit>> detailMaps, Paper newPaper, User user) throws PaperException {
        log.info("new paperId:" + newPaper.getId());
        if (StringUtils.isEmpty(newPaper.getId())) {
            throw new PaperException("试卷保存失败！");
        }
        for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : detailMaps.entrySet()) {
            PaperDetail detail = entry.getKey();
            detail.setPaper(newPaper);
        }
        //批量保存大题
        paperDetailRepo.saveAll(detailMaps.keySet());
        List<PaperDetailUnit> newDetailUnits = new ArrayList<>();
        List<Question> newQuestions = new ArrayList<>();
        for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : detailMaps.entrySet()) {
            PaperDetail detail = entry.getKey();
            log.info("new paperDetailId:" + detail.getId());
            List<PaperDetailUnit> detailUnits = entry.getValue();
            for (PaperDetailUnit detailUnit : detailUnits) {
                detailUnit.setPaper(newPaper);
                detailUnit.setPaperDetail(detail);
                newDetailUnits.add(detailUnit);
                newQuestions.add(detailUnit.getQuestion());
            }
        }
        //更新试题的PkgPath
//        for (Question question : newQuestions) {
//            this.updateQuestionPkgPath(question);
//        }
        //批量新增试题
        quesRepo.saveAll(newQuestions);

        for (Question question : newQuestions) {
            List<QuestionAudio> audioList = question.getAudioList();
            if (audioList != null && audioList.size() > 0) {
                for (QuestionAudio audio : audioList) {
                    audio.setQuestionId(question.getId());
                    questionAudioService.saveQuestionAudio(audio, user);
                    log.info("new questionAudioId:" + audio.getId());
                }
                this.updateQuestionBody(question, audioList);
                //如果试题存在音频，则更新试题的音频信息
                quesRepo.save(question);
            }
        }

        //批量保存试题单元
        paperDetailUnitRepo.saveAll(newDetailUnits);
        //复制来源大题的名称
        quesTypeNameService.saveCloneQuesTypeName(newDetailUnits, newPaper.getCourseNo());
    }

    /**
     * 更新试题题干或选项中的音频存储ID
     */
    private void updateQuestionBody(Question question, List<QuestionAudio> audioList) {
        Map<String, String> audioMaps = new HashMap<>();
        for (QuestionAudio audio : audioList) {
            audioMaps.put(audio.getFileName(), audio.getId());
        }

        //在题干html片段中替换音频存储ID
        String body = question.getQuesBody();
        List<String> ids = CommonUtils.getTagANames(body);
        List<String> names = CommonUtils.getTagANames2(body);
        Map<String, String> oldBodyMap = new HashMap<>();
        for (int i = 0; i < ids.size(); i++) {
            oldBodyMap.put(names.get(i), ids.get(i));
        }
        for (String key : oldBodyMap.keySet()) {
            body = body.replace(oldBodyMap.get(key), audioMaps.get(key));
        }
        question.setQuesBody(body);

        if (question.getQuesOptions() == null || question.getQuesOptions().size() == 0) {
            return;
        }

        //替换选项中的音频存储ID
        for (QuesOption option : question.getQuesOptions()) {
            String newOptionBody = option.getOptionBody();
            List<String> optionIds = CommonUtils.getTagANames(newOptionBody);
            List<String> optionNames = CommonUtils.getTagANames2(newOptionBody);

            Map<String, String> oldOptionMap = new HashMap<>();
            for (int i = 0; i < optionIds.size(); i++) {
                oldOptionMap.put(optionNames.get(i), optionIds.get(i));
            }
            for (String key : oldOptionMap.keySet()) {
                newOptionBody = newOptionBody.replace(oldOptionMap.get(key), audioMaps.get(key));
            }
            option.setOptionBody(newOptionBody);
        }
    }

    /**
     * 更新试题的“word package path”
     */
//    private void updateQuestionPkgPath(Question question) {
//        QuestionPkgPath pkgPath = quesPkgPathRepo.findFirstById(question.getQuesPkgPathId());
//        pkgPath.setId(null);
//        quesPkgPathRepo.save(pkgPath);
//        question.setQuesPkgPathId(pkgPath.getId());
//    }

    /**
     * 处理试题的音频(下载上传到云存储)
     */
    private void dealQuestionAudios(Map<PaperDetail, List<PaperDetailUnit>> detailMaps, String userName) throws PaperException {
//        UpYun upYun = upYunService.getInstance();
        String copyAudioPath = UpYunService.TEMP_FILE_EXP + File.separator + userName + "_copyAudioPath";
        File copyAudioDir = new File(copyAudioPath);
        if (!copyAudioDir.exists()) {
            copyAudioDir.mkdirs();
        }
        for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : detailMaps.entrySet()) {
            List<PaperDetailUnit> detailUnits = entry.getValue();
            for (PaperDetailUnit detailUnit : detailUnits) {
                Question question = detailUnit.getQuestion();
                List<QuestionAudio> audioList = question.getAudioList();
                if (audioList == null || audioList.size() == 0) {
                    continue;
                }
                for (QuestionAudio audio : audioList) {
                    //定义文件下载名称，并下载音频文件
                    String newAudioFileName = randomUUID() + "_" + audio.getFileName();
                    File audioFile = new File(copyAudioPath + File.separator + newAudioFileName);

                    log.info("-->start readAudioFile:" + newAudioFileName);
//                    upYun.readFile(audio.getFileUrl(), audioFile);
                  //通用存储
                    FileStorageUtil.saveUrlAs(FileStorageUtil.realPath(audio.getFileUrl()), audioFile);
                    log.info("-->end readAudioFile:" + newAudioFileName);

                    //重新上传新的音频文件
                    String newPath = sysProperty.getRadioUploadPath() + newAudioFileName;
                    try {
//                        upYun.writeFile(newPath, audioFile, true);
                        //通用存储
                		FileStoragePathEnvInfo env=new FileStoragePathEnvInfo();
                		env.setRelativePath(newPath);
                		YunPathInfo pi=FileStorageUtil.saveFile("audioFile", env, audioFile,null);
                        audio.setFileUrl(pi.getRelativePath());//设置新路径
                    } catch (Exception e) {
                        throw new PaperException("上传音频文件失败！");
                    } finally {
                        IoUtils.removeFile(audioFile);
                    }
                }
            }
        }

        IoUtils.removeFile(copyAudioDir);
    }

    /**
     * 复制试卷的所有试题信息
     */
    private Map<PaperDetail, List<PaperDetailUnit>> copyPaperDetails(Paper oldPaper, User user, Course course) throws PaperException {
        //批量查询原试卷的所有试题
        List<PaperDetailUnit> allDetailUnits = paperDetailUnitRepo.findByPaperOrderByNumber(oldPaper);
        if (allDetailUnits == null || allDetailUnits.size() == 0) {
            throw new PaperException("原试卷的试题不存在！");
        }
        //按大题有序封装对应的试题列表
        Map<PaperDetail, List<PaperDetailUnit>> oldDetailMaps = new TreeMap<>();
        for (PaperDetailUnit detailUnit : allDetailUnits) {
            PaperDetail detail = detailUnit.getPaperDetail();
            if (!oldDetailMaps.containsKey(detail)) {
                oldDetailMaps.put(detail, new ArrayList<>());
            }
            List<PaperDetailUnit> detailUnits = oldDetailMaps.get(detail);
            detailUnits.add(detailUnit);
        }
        //开始复制
        Map<PaperDetail, List<PaperDetailUnit>> detailMaps = new TreeMap<>();
        for (Map.Entry<PaperDetail, List<PaperDetailUnit>> entry : oldDetailMaps.entrySet()) {
            //复制大题信息
            PaperDetail oldPaperDetail = entry.getKey();
            PaperDetail paperDetail = this.copyPaperDetail(oldPaperDetail, user.getDisplayName());
            //复制大题下的所有试题单元
            List<PaperDetailUnit> oldDetailUnits = entry.getValue();
            List<PaperDetailUnit> detailUnits = new ArrayList<>();
            for (PaperDetailUnit oldDetailUnit : oldDetailUnits) {
                PaperDetailUnit detailUnit = this.copyPaperDetailUnit(oldDetailUnit, course, user.getDisplayName());
                detailUnits.add(detailUnit);
            }
            detailMaps.put(paperDetail, detailUnits);
        }
        return detailMaps;
    }

    /**
     * 复制试题的音频
     */
    private QuestionAudio copyQuestionAudio(QuestionAudio oldAudio, String createUser) {
        QuestionAudio audio = new QuestionAudio();
        audio.setId(null);
        audio.setQuestionId(null);
        audio.setFileUrl(oldAudio.getFileUrl());
        audio.setFileName(oldAudio.getFileName());
        audio.setFileSuffixes(oldAudio.getFileSuffixes());
        audio.setCreateTime(new Date());
        audio.setCreateUser(createUser);
        return audio;
    }

    /**
     * 复制试题信息
     */
    private Question copyQuestion(Question oldQuestion, String createUser) {
        Question question = BeanCopierUtil.copyProperties(oldQuestion, Question.class);
        question.setId(null);
        question.setCourse(null);
        question.setQuesProperties(null);
        question.setPropertyGroup(null);
        if (oldQuestion.getHasAudio() == null || !oldQuestion.getHasAudio()) {
            question.setHasAudio(false);
            return question;
        }
        //复制试题的音频
        List<QuestionAudio> audioList = questionAudioService.findQuestionAudiosByQuestionId(oldQuestion.getId());
        if (audioList != null && audioList.size() > 0) {
            for (QuestionAudio oldAudio : audioList) {
                QuestionAudio audio = this.copyQuestionAudio(oldAudio, createUser);
                question.addAudio(audio);
            }
        }
        return question;
    }

    /**
     * 复制试题单元信息
     */
    private PaperDetailUnit copyPaperDetailUnit(PaperDetailUnit oldDetailUnit, Course course, String createUser) throws PaperException {
        Question oldQuestion = oldDetailUnit.getQuestion();
        if (oldQuestion == null) {
            throw new PaperException("原试题详细信息不存在！");
        }
        PaperDetailUnit detailUnit = new PaperDetailUnit();
        detailUnit.setNumber(oldDetailUnit.getNumber());
        detailUnit.setScore(oldDetailUnit.getScore());
        detailUnit.setSubScoreList(oldDetailUnit.getSubScoreList());
        detailUnit.setQuestionType(oldDetailUnit.getQuestionType());
        detailUnit.setOptionOrder(oldDetailUnit.getOptionOrder());
        detailUnit.setPaperType(oldDetailUnit.getPaperType());
        detailUnit.setCreator(createUser);
        detailUnit.setCreateTime(CommonUtils.getCurDateTime());
        detailUnit.setPaper(null);
        detailUnit.setPaperDetail(null);
        //复制试题信息
        Question question = this.copyQuestion(oldQuestion, createUser);
        question.setCourse(course);
        detailUnit.setQuestion(question);
        return detailUnit;
    }

    /**
     * 复制大题信息
     */
    private PaperDetail copyPaperDetail(PaperDetail oldPaperDetail, String createUser) {
        PaperDetail paperDetail = new PaperDetail();
        paperDetail.setNumber(oldPaperDetail.getNumber());
        paperDetail.setName(oldPaperDetail.getName());
        paperDetail.setTitle(oldPaperDetail.getTitle());
        paperDetail.setScore(oldPaperDetail.getScore());
        paperDetail.setUnitCount(oldPaperDetail.getUnitCount());
        paperDetail.setCreator(createUser);
        paperDetail.setCreateTime(CommonUtils.getCurDateTime());
        paperDetail.setPaper(null);
        return paperDetail;
    }

    /**
     * 复制试卷信息
     */
    private Paper copyPaper(Paper oldPaper, String paperName, Course course, User user) {
        Paper newPaper = BeanCopierUtil.copyProperties(oldPaper, Paper.class);
        newPaper.setName(paperName);
        newPaper.setCourse(course);
        newPaper.setCourseNo(course.getCode());
        newPaper.setCourseName(course.getName());
        newPaper.setOrgId(String.valueOf(user.getRootOrgId()));
        newPaper.setCreateTime(CommonUtils.getCurDateTime());
        newPaper.setLastModifyName(user.getDisplayName());
        newPaper.setId(null);
        return newPaper;
    }
    private String randomUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
}