package com.ym.mec.biz.service.impl;


import static com.ym.mec.biz.dal.enums.ClientTypeEnum.SMART_PRACTICE;

import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.SysMusicScoreMetronomeTranscod;
import com.ym.mec.biz.dal.dto.SysMusicScoreTranscod;
import com.ym.mec.biz.dal.entity.SysMusicScoreChangeLog;
import com.ym.mec.biz.service.OrganizationService;
import com.ym.mec.biz.service.UploadFileService;
import com.ym.mec.common.entity.UploadReturnBean;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.util.file.FileUtil;
import com.ym.mec.util.shell.ScriptUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dto.MusicScoreDto;
import com.ym.mec.biz.dal.entity.SysMusicScore;
import com.ym.mec.biz.dal.entity.SysMusicScoreAccompaniment;
import com.ym.mec.biz.dal.entity.SysMusicScoreCategories;
import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
import com.ym.mec.biz.service.SysMusicScoreCategoriesService;
import com.ym.mec.biz.service.SysMusicScoreService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.collection.MapUtil;

@Service
public class SysMusicScoreServiceImpl extends BaseServiceImpl<Integer, SysMusicScore> implements SysMusicScoreService {

    @Autowired
    private SysMusicScoreDao sysMusicScoreDao;
    @Autowired
    private SysMusicScoreAccompanimentDao sysMusicScoreAccompanimentDao;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysMusicScoreCategoriesDao sysMusicScoreCategoriesDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private SysMusicScoreCategoriesService sysMusicScoreCategoriesService;
    @Autowired
    private SysMusicScoreChangeLogDao sysMusicScoreChangeLogDao;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private UploadFileService uploadFileService;
    @Autowired
    private OrganizationService organizationService;

    @Override
    public BaseDAO<Integer, SysMusicScore> getDAO() {
        return sysMusicScoreDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMusicScore(MusicScoreDto musicScoreDto) {
        SysMusicScore sysMusicScore = musicScoreDto.getSysMusicScore();
        sysMusicScoreDao.update(sysMusicScore);
        List<Integer> delExamSongAccompanimentIds = musicScoreDto.getDelExamSongAccompanimentIds();
        if (delExamSongAccompanimentIds != null && delExamSongAccompanimentIds.size() > 0) {
            sysMusicScoreAccompanimentDao.batchDel(delExamSongAccompanimentIds);
        }
        List<SysMusicScoreAccompaniment> sysMusicScoreAccompaniments = musicScoreDto.getSysMusicScoreAccompaniments();
        if (sysMusicScoreAccompaniments != null && sysMusicScoreAccompaniments.size() > 0) {
            List<Integer> subjectIdList = sysMusicScoreAccompaniments.stream().map(e -> e.getSubjectId()).collect(Collectors.toList());
            subjectIdList.removeAll(Collections.singleton(null));
            if (subjectIdList.size() > 0) {
                List<Integer> idList = sysMusicScoreAccompaniments.stream().map(e -> e.getId()).collect(Collectors.toList());
                List<Integer> subjectIds = sysMusicScoreAccompanimentDao.findSubjectByMusicScoreId(sysMusicScore.getId(), idList);
                int subjectSize = subjectIds.size() + subjectIdList.size();
                subjectIdList.addAll(subjectIds);
                int size = new HashSet<>(subjectIdList).size();
                if (size < subjectSize) {
                    throw new BizException("操作失败：请勿提交重复的伴奏声部");
                }
            }
            //获取需要修改的伴奏
            List<SysMusicScoreAccompaniment> updateCollect = sysMusicScoreAccompaniments.stream().filter(e -> e.getId() != null).collect(Collectors.toList());
            if (updateCollect.size() > 0) {
                sysMusicScoreAccompanimentDao.batchUpdate(updateCollect, sysMusicScore.getIsOpenMetronome());
            }
            //获取需要新增的伴奏
            List<SysMusicScoreAccompaniment> addCollect = sysMusicScoreAccompaniments.stream().filter(e -> e.getId() == null).collect(Collectors.toList());
            if (addCollect.size() > 0) {
                sysMusicScoreAccompanimentDao.batchInsert(addCollect, sysMusicScore.getId(), sysMusicScore.getIsOpenMetronome());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(MusicScoreDto musicScoreDto) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        SysMusicScore sysMusicScore = musicScoreDto.getSysMusicScore();
        sysMusicScore.setCreateUserId(sysUser.getId());
        sysMusicScoreDao.insert(sysMusicScore);
        List<SysMusicScoreAccompaniment> sysMusicScoreAccompaniments = musicScoreDto.getSysMusicScoreAccompaniments();
        if (sysMusicScoreAccompaniments != null && sysMusicScoreAccompaniments.size() > 0) {
            sysMusicScoreAccompaniments.forEach(e -> {
                e.setIsOpenMetronome(sysMusicScore.getIsOpenMetronome());
            });
            sysMusicScoreAccompanimentDao.batchInsert(sysMusicScoreAccompaniments, sysMusicScore.getId(), sysMusicScore.getIsOpenMetronome());
        }
        Integer categoriesId = sysMusicScore.getMusicScoreCategoriesId();
        if (categoriesId != null && sysMusicScore.getClientType() == SMART_PRACTICE) {
            while (true) {
                SysMusicScoreCategories categories = sysMusicScoreCategoriesDao.get(categoriesId);
                if (categories.getParentId() == 0) {
                    categories.setMusicScoreNum(categories.getMusicScoreNum() + 1);
                    sysMusicScoreCategoriesDao.update(categories);
                    return;
                }
                categoriesId = categories.getParentId();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(Integer id) {
        SysMusicScore sysMusicScore = sysMusicScoreDao.get(id);
        if (sysMusicScore == null) {
            throw new BizException("曲目不存在");
        }
        sysMusicScoreDao.delete(id);
        sysMusicScoreAccompanimentDao.deleteBySongId(id);
        Integer categoriesId = sysMusicScore.getMusicScoreCategoriesId();
        if (categoriesId != null && sysMusicScore.getClientType() == SMART_PRACTICE) {
            while (true) {
                SysMusicScoreCategories categories = sysMusicScoreCategoriesDao.get(categoriesId);
                if (categories.getParentId() == 0) {
                    Integer musicScoreNum = categories.getMusicScoreNum() - 1;
                    if (musicScoreNum < 0) {
                        musicScoreNum = 0;
                    }
                    categories.setMusicScoreNum(musicScoreNum);
                    sysMusicScoreCategoriesDao.update(categories);
                    return;
                }
                categoriesId = categories.getParentId();
            }
        }
    }

    private String getParentTreeName(Integer categoriesId) {
        StringBuffer sb = new StringBuffer();
        while (true) {
            SysMusicScoreCategories categories = sysMusicScoreCategoriesDao.get(categoriesId);
            if (sb.length() == 0) {
                sb.append(categories.getName());
            } else {
                sb.insert(0, "/");
                sb.insert(0, categories.getName());
            }
            if (categories.getParentId() == 0) {
                return sb.toString();
            }
            categoriesId = categories.getParentId();
        }
    }

    private void dealMusicScoreParam(SysExamSongQueryInfo queryInfo){
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        if(queryInfo.getCategoriesId() != null){
            List<Integer> categoriesIdList = new ArrayList<>();
            Integer categoriesId = Integer.parseInt(queryInfo.getCategoriesId());

            SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(categoriesId);

            if(sysMusicScoreCategories == null){
                throw new BizException("分类找不到");
            }
            categoriesIdList.add(categoriesId);
            sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
            getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());

            queryInfo.setCategoriesIdList(categoriesIdList);
        }
    }

    private void dealMusicScoreData(List<SysMusicScore> rows){
        if (rows != null && rows.size() > 0) {
            Set<Integer> categoriesIds = rows.stream().map(e -> e.getMusicScoreCategoriesId()).collect(Collectors.toSet());
            //获取分部列表
            Map<Integer, String> organMap = MapUtil.convertMybatisMap(sysMusicScoreCategoriesDao.queryOrganByIds(categoriesIds));
            //获取声部列表
            Set<Integer> subjectIds = rows.stream().map(e -> e.getSubjectId()).collect(Collectors.toSet());
            subjectIds.removeAll(Collections.singleton(null));
            Map<Long, String> subjectMap = new HashMap();
            if (subjectIds.size() > 0) {
                String ids = StringUtils.join(subjectIds, ",");
                subjectMap = MapUtil.convertMybatisMap(subjectDao.findBySubjecIds(ids));
            }
            Map<Integer, String> map = new HashMap<>(categoriesIds.size());
            for (Integer categoriesId : categoriesIds) {
                if(null != categoriesId){
                    map.put(categoriesId, getParentTreeName(categoriesId));
                }
            }
            for (SysMusicScore row : rows) {
                row.setCategoriesName(map.get(row.getMusicScoreCategoriesId()));
                row.setOrganName(organMap.get(row.getMusicScoreCategoriesId()));
                row.setSubjectName(subjectMap.get(row.getSubjectId()));
            }
        }
    }

    @Override
    public List<SysMusicScore> queryMusicScoreAll(SysExamSongQueryInfo queryInfo) {
        //封装查询参数
        dealMusicScoreParam(queryInfo);
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<SysMusicScore> rows = findAll(params);
        //处理查询结果
        dealMusicScoreData(rows);
        return rows;
    }

    @Override
    public PageInfo<SysMusicScore> queryMusicScorePage(SysExamSongQueryInfo queryInfo) {
        //封装查询参数
        dealMusicScoreParam(queryInfo);

        PageInfo<SysMusicScore> sysMusicScorePageInfo = queryPage(queryInfo);
        List<SysMusicScore> rows = sysMusicScorePageInfo.getRows();
        //处理查询结果
        dealMusicScoreData(rows);
        return sysMusicScorePageInfo;
    }

    @Override
    public PageInfo<SysMusicScore> queryMusicScorePageInfo(SysExamSongQueryInfo queryInfo) {
        if (queryInfo.getCategoriesId() != null) {
            List<Integer> categoriesIdList = new ArrayList<>();
            Integer categoriesId = null;
            if (StringUtils.isNotEmpty(queryInfo.getCategoriesId())) {
                categoriesId = Integer.parseInt(queryInfo.getCategoriesId());
            }
            //List<SysMusicScoreCategories> scoreCategories = sysMusicScoreCategoriesService.queryTree(musicScoreQueryInfo);

            SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(categoriesId);

            if (sysMusicScoreCategories == null) {
                throw new BizException("分类找不到");
            }
            categoriesIdList.add(categoriesId);
            sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
            getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());

            queryInfo.setCategoriesIdList(categoriesIdList);
        }
        return this.queryPage(queryInfo);
    }

    @Override
    public void transcod(Integer sysMusicScoreId) {
        SysMusicScoreTranscod obj = sysMusicScoreDao.getTranscod(sysMusicScoreId);
        if (obj == null) {
            throw new BizException("曲目信息不存在");
        }
        List<SysMusicScoreMetronomeTranscod> metronomeTranscod = sysMusicScoreDao.getMetronomeTranscod(sysMusicScoreId);
        obj.setAccompanimentList(metronomeTranscod);
        //
        String old = JSONObject.toJSONString(obj);
        boolean flag = false;
        String url = doTranscod(obj.getUrl());
        if (StringUtils.isNotEmpty(url)) {
            obj.setUrl(url);
            flag = true;
        }
        String metronomeUrl = doTranscod(obj.getMetronomeUrl());
        if (StringUtils.isNotEmpty(metronomeUrl)) {
            obj.setMetronomeUrl(metronomeUrl);
            flag = true;
        }
        if (flag) {
            //更新obj
            SysMusicScore sysMusicScore = new SysMusicScore();
            sysMusicScore.setId(obj.getId());
            sysMusicScore.setUrl(obj.getUrl());
            sysMusicScore.setMetronomeUrl(obj.getMetronomeUrl());
            sysMusicScoreDao.update(sysMusicScore);
        }

        for (SysMusicScoreMetronomeTranscod o : metronomeTranscod) {
            Boolean subFlag = false;
            String mp3Url = doTranscod(o.getMp3Url());
            if (StringUtils.isNotEmpty(mp3Url)) {
                o.setMp3Url(mp3Url);
                flag = true;
                subFlag = true;
            }
            String metronomeMp3Url = doTranscod(o.getMetronomeMp3Url());
            if (StringUtils.isNotEmpty(metronomeMp3Url)) {
                o.setMetronomeMp3Url(metronomeMp3Url);
                flag = true;
                subFlag = true;
            }
            if (subFlag) {
                SysMusicScoreAccompaniment accompaniment = new SysMusicScoreAccompaniment();
                accompaniment.setExamSongId(o.getId());
                accompaniment.setMp3Url(o.getMp3Url());
                accompaniment.setMetronomeMp3Url(o.getMetronomeMp3Url());
                sysMusicScoreDao.updateAccompanimentBySongId(accompaniment);
            }
        }
        if (!flag) {
            return;
        }
        obj.setAccompanimentList(metronomeTranscod);
        String now = JSONObject.toJSONString(obj);

        //记录日志
        SysMusicScoreChangeLog log = new SysMusicScoreChangeLog();
        log.setSysMusicScoreId(obj.getId());
        log.setChangeBefore(old);
        log.setChangeAfter(now);
        sysMusicScoreChangeLogDao.insert(log);
    }

    /**
     * 进行转码
     *
     * @param fileUrl
     * @return
     */
    private String doTranscod(String fileUrl) {
        String transcodUrl = "";
        if (StringUtils.isEmpty(fileUrl)) {
            return transcodUrl;
        }
        //文件扩展名
        String expand = FileUtil.getFileExpandByPath(fileUrl);
        //将远程文件写入本地临时文件路径
        String tempFileName = getTempFileName(expand);
        File tempFile = new File(tempFileName);
        //转码后文件路径
        String tempTranscodFileName = getTempFileName(expand);
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

            FileUtil.inputStreamToFile(conn.getInputStream(), tempFile);

            String script = "ffmpeg -i " + tempFileName + " -vn -c:a libmp3lame -b:a 320k -ac 2 " + tempTranscodFileName;
            int i = ScriptUtil.callScript(script);
            if (i == 0) {
                //转码成功
                FileInputStream inputStream = new FileInputStream(tempTranscodFileName);
                UploadReturnBean uploadReturnBean = uploadFileService.uploadFile(inputStream, expand);
                transcodUrl = uploadReturnBean.getUrl();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //删除服务器中的文件
            if (tempFile.exists()) {
                tempFile.delete();
            }
            File tempTranscodFile = new File(tempTranscodFileName);
            if (tempTranscodFile.exists()) {
                tempTranscodFile.delete();
            }
        }
        return transcodUrl;
    }

    /**
     * 通过网络文件路径获取临时文件路径
     *
     * @param fileUrl
     * @return
     */
    String tempPath = "/usr/temp";

    private String getTempFileName(String expand) {
        //没有目录则创建
        File file = new File(tempPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        //.mp3
        String fileName = tempPath + File.separator + idGeneratorService.generatorId("tempFile");
        if (StringUtils.isNotEmpty(expand)) {
            fileName += "." + expand;
        }
        return fileName;
    }

    private void getAllCategoryIdList(List<Integer> categoryIdList, List<SysMusicScoreCategories> sysMusicScoreCategoriesList) {

        if (sysMusicScoreCategoriesList != null && sysMusicScoreCategoriesList.size() > 0) {
            for (SysMusicScoreCategories sysMusicScoreCategories : sysMusicScoreCategoriesList) {
                categoryIdList.add(sysMusicScoreCategories.getId());
                getAllCategoryIdList(categoryIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
            }
        }

    }

}