package com.qmth.teachcloud.report.business.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.BasicCourse;
import com.qmth.teachcloud.common.entity.SysOrg;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.BasicCourseService;
import com.qmth.teachcloud.common.service.SysOrgService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.util.ExcelUtil;
import com.qmth.teachcloud.report.business.bean.dto.excel.BasicCourseChangeDto;
import com.qmth.teachcloud.report.business.bean.dto.excel.SysOrgChangeDto;
import com.qmth.teachcloud.report.business.bean.dto.excel.SysUserChangeDto;
import com.qmth.teachcloud.report.business.bean.params.CollegeCombineParams;
import com.qmth.teachcloud.report.business.entity.TAExamCourseRecord;
import com.qmth.teachcloud.report.business.entity.TBStudent;
import com.qmth.teachcloud.report.business.service.*;
import com.qmth.teachcloud.report.business.utils.RandomNameUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 课程单元操作服务实现类
 * @Author: CaoZixuan
 * @Date: 2022-02-25
 */
@Service
public class CourseUnitOperateServiceImpl implements CourseUnitOperateService {
    @Resource
    private BasicCourseService basicCourseService;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private TBStudentService tbStudentService;
    @Resource
    private ChangNamesService changNamesService;
    @Resource
    private TAExamCourseRecordService taExamCourseRecordService;
    @Resource
    private InsteadOrgService insteadOrgService;

    private static final Logger log = LoggerFactory.getLogger(CourseUnitOperateServiceImpl.class);


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String changeBasicCourse(MultipartFile file, Long schoolId) throws IOException, NoSuchFieldException {
        // 基础课程数据源
        List<BasicCourse> basicCourseDatasource = basicCourseService.list(new QueryWrapper<BasicCourse>().lambda().eq(BasicCourse::getSchoolId, schoolId));

        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(BasicCourseChangeDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            if (finalExcelErrorList.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(finalExcelErrorList));
            }
            return finalExcelList;
        });
        List<BasicCourse> updateData = new ArrayList<>();
        if (Objects.nonNull(finalList) && finalList.size() > 0) {
            for (int i = 0; i < finalList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> map = finalList.get(i);
                List<Object> dataSource = map.get(i);
                for (int y = 0; y < Objects.requireNonNull(dataSource).size(); y++) {
                    if (dataSource.get(y) instanceof BasicCourseChangeDto) {
                        BasicCourseChangeDto basicCourseChangeDto = (BasicCourseChangeDto) dataSource.get(y);
                        Long id = SystemConstant.convertIdToLong(basicCourseChangeDto.getId());


                        List<BasicCourse> basicCourseVerifyList = basicCourseDatasource.stream().filter(e -> e.getId().equals(id)).collect(Collectors.toList());
                        if (basicCourseVerifyList.size() > 0) {
                            BasicCourse basicCourse = basicCourseVerifyList.get(0);
                            Long excelSchoolId = SystemConstant.convertIdToLong(basicCourseChangeDto.getSchoolId());
                            String courseCode = basicCourseChangeDto.getCourseCode();
                            String historicName = basicCourseChangeDto.getHistoricName();
                            String newName = basicCourseChangeDto.getNewName();
                            if (!SystemConstant.strNotNull(newName)) {
                                continue;
                            }

                            // 数据校验
                            if (!basicCourse.getSchoolId().equals(excelSchoolId) || !basicCourse.getCode().equals(courseCode) || !basicCourse.getName().equals(historicName)) {
                                throw ExceptionResultEnum.ERROR.exception("第【" + (y + 2) + "】行数据不对应");
                            }
                            // 基础数据替换
                            basicCourse.setName(newName);
                            basicCourse.setHistoricName(historicName);
                            updateData.add(basicCourse);
                        }
                    }
                }
            }
        }
        basicCourseService.updateBatchById(updateData);
        return "'basic_course' 基础课程表完成更新【" + updateData.size() + "】课次";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String changeSysOrg(MultipartFile file, Long schoolId) throws IOException, NoSuchFieldException {
        // 基础机构数据
        List<SysOrg> sysOrgDatasource = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId));
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(SysOrgChangeDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            if (finalExcelErrorList.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(finalExcelErrorList));
            }
            return finalExcelList;
        });
        List<SysOrg> updateData = new ArrayList<>();
        Map<String, Integer> nameCheck = new HashMap<>();

        if (Objects.nonNull(finalList) && finalList.size() > 0) {
            for (int i = 0; i < finalList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> map = finalList.get(i);
                List<Object> dataSource = map.get(i);
                for (int y = 0; y < Objects.requireNonNull(dataSource).size(); y++) {
                    if (dataSource.get(y) instanceof SysOrgChangeDto) {
                        SysOrgChangeDto sysOrgChangeDto = (SysOrgChangeDto) dataSource.get(y);
                        Long id = SystemConstant.convertIdToLong(sysOrgChangeDto.getId());


                        List<SysOrg> sysOrgVerifyList = sysOrgDatasource.stream().filter(e -> e.getId().equals(id)).collect(Collectors.toList());
                        if (sysOrgVerifyList.size() > 0) {
                            SysOrg sysOrg = sysOrgVerifyList.get(0);
                            Long excelSchoolId = SystemConstant.convertIdToLong(sysOrgChangeDto.getSchoolId());
                            String orgCode = sysOrgChangeDto.getOrgCode();
                            String historicName = sysOrgChangeDto.getHistoricName();
                            String newName = sysOrgChangeDto.getNewName();
                            if (!SystemConstant.strNotNull(newName)) {
                                continue;
                            }

                            // 数据校验
                            if (nameCheck.containsKey(newName)) {
                                throw ExceptionResultEnum.ERROR.exception("第【" + (y + 2) + "】行变更的机构名称【" + newName + "】和第【" + nameCheck.get(newName) + "】行重复");
                            } else {
                                nameCheck.put(newName, (y + 2));
                            }
                            if (!sysOrg.getSchoolId().equals(excelSchoolId) || !sysOrg.getCode().equals(orgCode) || !sysOrg.getName().equals(historicName)) {
                                throw ExceptionResultEnum.ERROR.exception("第【" + (y + 2) + "】行数据不对应");
                            }
                            // 基础数据替换
                            sysOrg.setName(newName);
                            sysOrg.setHistoricName(historicName);
                            updateData.add(sysOrg);
                        }
                    }
                }
            }
        }
        sysOrgService.updateBatchById(updateData);
        return "'sys_org' 系统机构表完成更新【" + updateData.size() + "】次";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String changeSysUser(MultipartFile file, Long schoolId) throws IOException, NoSuchFieldException {
        // 基础机构数据
        List<SysOrg> sysOrgDatasource = sysOrgService.list(new QueryWrapper<SysOrg>().lambda().eq(SysOrg::getSchoolId, schoolId));
        // 基础用户数据
        List<SysUser> sysUserDatasource = sysUserService.list(new QueryWrapper<SysUser>().lambda().eq(SysUser::getSchoolId, schoolId));

        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(file.getInputStream(), Lists.newArrayList(SysUserChangeDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            if (finalExcelErrorList.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(finalExcelErrorList));
            }
            return finalExcelList;
        });

        List<SysUser> updateData = new ArrayList<>();

        if (Objects.nonNull(finalList) && finalList.size() > 0) {
            for (int i = 0; i < finalList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> map = finalList.get(i);
                List<Object> dataSource = map.get(i);
                for (int y = 0; y < Objects.requireNonNull(dataSource).size(); y++) {
                    if (dataSource.get(y) instanceof SysUserChangeDto) {
                        SysUserChangeDto sysUserChangeDto = (SysUserChangeDto) dataSource.get(y);
                        Long id = SystemConstant.convertIdToLong(sysUserChangeDto.getId());


                        List<SysUser> sysUserVerifyList = sysUserDatasource.stream().filter(e -> e.getId().equals(id)).collect(Collectors.toList());
                        if (sysUserDatasource.size() > 0) {
                            SysUser sysUser = sysUserVerifyList.get(0);
                            Long excelSchoolId = SystemConstant.convertIdToLong(sysUserChangeDto.getSchoolId());
                            String historicName = sysUserChangeDto.getHistoricName();
                            String newName = sysUserChangeDto.getNewName();
                            if (!SystemConstant.strNotNull(newName)) {
                                continue;
                            }
                            // 如果该用户是机构表中自动创建的考察学院院长用户，则同步更新用户名为机构表名称
                            List<SysOrg> sysOrgList = sysOrgDatasource.stream().filter(e -> e.getHistoricName().equals(historicName)).collect(Collectors.toList());
                            if (sysOrgList.size() == 1) {
                                sysUser.setRealName(sysOrgList.get(0).getName());
                                sysUser.setLoginName(sysOrgList.get(0).getName());
                            } else {
                                // 数据校验
                                if (!sysUser.getSchoolId().equals(excelSchoolId) || !sysUser.getRealName().equals(historicName)) {
                                    throw ExceptionResultEnum.ERROR.exception("第【" + (y + 2) + "】行数据不对应");
                                }
                                // 基础数据替换
                                sysUser.setRealName(newName);
                                sysUser.setLoginName(newName);
                            }
                            sysUser.setHistoricName(historicName);
                            updateData.add(sysUser);
                        }
                    }
                }
            }
        }
        sysUserService.updateBatchById(updateData);
        return "'sys_user' 系统用户表完成更新【" + updateData.size() + "】次";
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void changeStudent(Long schoolId) {
        List<TBStudent> historicData = tbStudentService.list(new QueryWrapper<TBStudent>().lambda().eq(TBStudent::getSchoolId,schoolId));
        for (TBStudent historicDatum : historicData) {
            historicDatum.setName(RandomNameUtil.getName());
        }
        tbStudentService.updateBatchById(historicData);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createDemoData() throws InterruptedException {
        log.info("该表线程开始执行");
        changNamesService.changeBasicTables();
        changNamesService.changeTableTAExamCourse();
        changNamesService.changeTableTAExamCourseClazz();
        changNamesService.changeTableTAExamCourseCollegeInspect();
        changNamesService.changeTableTAExamCourseCollegeInspectDio();
        changNamesService.changeTableTAExamCourseCollegePaperStruct();
        changNamesService.changeTableTAExamCourseCollegeTeacher();
        changNamesService.changeTableTAExamCourseDifficultService();
        changNamesService.changeTableTAExamCourseDio();
        changNamesService.changeTableTAExamCourseRecordDio();
        changNamesService.changeTableTAExamCourseRecordMod();
        changNamesService.changeTableTAExamCourseTeacher();
        changNamesService.changeTableTAExamCourseTeacherCollegeDifficult();
        changNamesService.changeTableTAExamCourseTeacherCollegeDio();
        changNamesService.changeTableTAExamCourseTeacherCollegePaperStruct();
        changNamesService.changeTableTAExamCourseTeacherDifficult();
        changNamesService.changeTableTAExamCourseTeacherDio();
        changNamesService.changeTableTAExamCourseTeacherPaperStruct();
        changNamesService.changeTableTAExamTotal();
        changNamesService.changeTableTAPaperStruct();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void combineCollegeInspectToTeach(Long schoolId, List<CollegeCombineParams> collegeCombineParamsList) {
        // 构建被替换学院id - 替换学院id 键值对
        Map<Long, Long> orgIdMap = new HashMap<>();
        // 构建被替换学院名称 - 替换学院名称 键值对
        Map<String, String> orgNameMap = new HashMap<>();

        for (CollegeCombineParams collegeCombineParams : collegeCombineParamsList) {
            Long inspectCollegeId = collegeCombineParams.getInspectCollegeId();
            Long teachCollegeId = collegeCombineParams.getTeachCollegeId();

            // 考察学院判断
            SysOrg inspectCollege = sysOrgService.getById(inspectCollegeId);
            if (Objects.isNull(inspectCollege)) {
                throw ExceptionResultEnum.ERROR.exception("考察学院不存在 id = " + inspectCollegeId);
            }
            if (taExamCourseRecordService.count(new QueryWrapper<TAExamCourseRecord>().lambda().eq(TAExamCourseRecord::getSchoolId, schoolId).eq(TAExamCourseRecord::getInspectCollegeId, inspectCollegeId)) == 0) {
                throw ExceptionResultEnum.ERROR.exception("考察学院【" + inspectCollege.getName() + "】不存在数据");
            }

            // 开课学院判断
            SysOrg teachCollege = sysOrgService.getById(teachCollegeId);
            if (Objects.isNull(teachCollege)) {
                throw ExceptionResultEnum.ERROR.exception("开课学院不存在 id= " + teachCollegeId);
            }
            if (taExamCourseRecordService.count(new QueryWrapper<TAExamCourseRecord>().lambda().eq(TAExamCourseRecord::getSchoolId, schoolId).eq(TAExamCourseRecord::getTeachCollegeId, teachCollegeId)) == 0) {
                throw ExceptionResultEnum.ERROR.exception("开课学院【" + teachCollege.getName() + "】不存在数据");
            }

            if (!Objects.equals(inspectCollege.getParentId(), teachCollege.getParentId())) {
                throw ExceptionResultEnum.ERROR.exception("考察学院【" + inspectCollege.getName() + "】和开课学院【" + teachCollege.getName() + "】不在同一个父机构下");
            }

            orgIdMap.put(inspectCollegeId, teachCollegeId);
            orgNameMap.put(inspectCollege.getName(), teachCollege.getName());
        }
        insteadOrgService.insteadOrgBasicTable(schoolId, orgIdMap);
        insteadOrgService.insteadOrgTAExamCourse(schoolId, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseClazz(schoolId, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseCollegeInspect(schoolId, orgIdMap);
        insteadOrgService.insteadOrgTAExamCourseCollegeInspectDio(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseCollegePaperStruct(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseCollegeTeacher(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseDifficult(schoolId, orgIdMap);
        insteadOrgService.insteadOrgTAExamCourseRecord(schoolId, orgIdMap);
        insteadOrgService.insteadOrgTAExamCourseRecordDio(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseRecordMod(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseTeacherCollegeDifficult(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseTeacherCollegeDio(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamCourseTeacherCollegePaperStruct(schoolId, orgIdMap, orgNameMap);
        insteadOrgService.insteadOrgTAExamTotal(schoolId, orgNameMap);
    }
}
