package com.qmth.teachcloud.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.teachcloud.common.base.BaseEntity;
import com.qmth.teachcloud.common.bean.dto.CourseInfoDto;
import com.qmth.teachcloud.common.bean.dto.excel.BasicCourseImportDto;
import com.qmth.teachcloud.common.bean.dto.excel.DescribeImportDto;
import com.qmth.teachcloud.common.bean.params.BasicCourseParams;
import com.qmth.teachcloud.common.bean.result.BasicCourseResult;
import com.qmth.teachcloud.common.bean.result.ClazzDatasourceResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.OrgTypeEnum;
import com.qmth.teachcloud.common.mapper.BasicCourseMapper;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;

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

/**
 * <p>
 * 课程表 服务实现类
 * </p>
 *
 * @author xf
 * @since 2021-03-23
 */
@Service
public class BasicCourseServiceImpl extends ServiceImpl<BasicCourseMapper, BasicCourse> implements BasicCourseService {

    @Resource
    private BasicCourseMapper basicCourseMapper;
    @Resource
    private TeachcloudCommonService teachcloudCommonService;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private BasicUserCourseService basicUserCourseService;
    @Resource
    private BasicClazzService basicClazzService;
    @Resource
    private SysUserService sysUserService;


    @Override
    public List<BasicCourse> listCoursesByUserId(Long userId) {
        return this.baseMapper.listCoursesByUserId(userId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void verifyCourseInfo(Long schoolId, String courseCode, String courseName, Long userId) {
        QueryWrapper<BasicCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, courseCode).eq(BasicCourse::getEnable, true);

        BasicCourse tmp = this.getOne(queryWrapper);
        if (tmp != null) {
            if (!courseName.equals(tmp.getName())) {
                throw ExceptionResultEnum.ERROR
                        .exception("课程代码和课程名称不匹配,课程代码为 ：'" + courseCode + "',输入的课程名称 ：'" + courseName + "',实际该代码对应的课程名称 ：'" + tmp.getName() + "'。");
            }
        } else {
//            BasicCourse basicCourse = new BasicCourse();
//            basicCourse.setName(courseName);
//            basicCourse.setCode(courseCode);
//            basicCourse.setSchoolId(schoolId);
//            basicCourse.setId(SystemConstant.getDbUuid());
//            basicCourse.setCreateId(userId);
//            basicCourse.setOrgId(sysUserService.getById(userId).getOrgId());
//            basicCourse.setCreateTime(System.currentTimeMillis());
//            basicCourse.setTeachingRoomId();
//            this.saveOrUpdate(basicCourse);
            throw ExceptionResultEnum.ERROR.exception("考务文件中 【课程代码】为 ：" + courseCode + "，【课程名称】为 ： " + courseName + "，在基础课程信息中不存在，请先添加课程");
        }
    }

    @Override
    public List<CourseInfoDto> findByUserLoginNameAndRealName(String loginName, String realName) {
        System.out.println("---");
        if (loginName == null) {
            loginName = "";
        }
        if (realName == null) {
            realName = "";
        }
        return basicCourseMapper.findByUserLoginNameAndRealName(loginName, realName);
    }

    @Deprecated
    @Override
    public BasicCourse findByCourseCode(String courseCode) {
        return this.getOne(new QueryWrapper<BasicCourse>().lambda().eq(BasicCourse::getCode, courseCode));
    }

    @Override
    public BasicCourse findByCourseCode(String courseCode, Long schoolId) {
        BasicCourse basicCourse = this.getOne(new QueryWrapper<BasicCourse>().lambda().eq(BasicCourse::getCode, courseCode).eq(BasicCourse::getSchoolId,schoolId));
        if (Objects.isNull(basicCourse)){
            throw ExceptionResultEnum.ERROR.exception("未找到课程编号为【" + courseCode + "】的基础课程");
        }
        return basicCourse;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createCourse(Long schoolId, String courseCode, String courseName) {
        // 向'basic_course'表新增数据 - 教研分析用
        List<BasicCourse> basicCourseList = this.list(new QueryWrapper<BasicCourse>().lambda()
                .eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, courseCode));
        if (basicCourseList.size() == 0) {
            BasicCourse basicCourse = new BasicCourse();
            basicCourse.setId(SystemConstant.getDbUuid());
            basicCourse.setCode(courseCode);
            basicCourse.setName(courseName);
            basicCourse.setSchoolId(schoolId);
            this.save(basicCourse);
        }
    }

    @Override
    public IPage<BasicCourseResult> basicCoursePage(Long belongOrgId, String courseName, Long startCreateTime, Long endCreateTime, Boolean enable, int pageNumber, int pageSize) {
        Long schoolId = SystemConstant.convertIdToLong(ServletUtil.getRequestHeaderSchoolId().toString());
        Set<Long> orgIds = teachcloudCommonService.listSubOrgIds(null);
        courseName = SystemConstant.translateSpecificSign(courseName);
        IPage<BasicCourseResult> iPage = basicCourseMapper.findBasicCoursePage(new Page<>(pageNumber, pageSize), belongOrgId, courseName, startCreateTime, endCreateTime, enable, schoolId, orgIds);
        List<BasicCourseResult> list = iPage.getRecords();
        for (BasicCourseResult basicCourseResult : list) {
            Long courseId = basicCourseResult.getId();
            List<BasicUserCourse> basicUserCourseList = basicUserCourseService.list(new QueryWrapper<BasicUserCourse>().lambda().eq(BasicUserCourse::getCourseId, courseId));
            Set<Long> clazzIdSet = basicUserCourseList.stream().map(BasicUserCourse::getClazzId).collect(Collectors.toSet());
            List<ClazzDatasourceResult> clazzDatasourceResultList = new ArrayList<>();
            if (clazzIdSet.size() > 0) {
                List<BasicClazz> clazzList = basicClazzService.list(new QueryWrapper<BasicClazz>().lambda().in(BasicClazz::getId, clazzIdSet).orderByAsc(BasicClazz::getCreateTime));
                for (BasicClazz clazz : clazzList) {
                    ClazzDatasourceResult clazzDatasourceResult = new ClazzDatasourceResult();
                    clazzDatasourceResult.setId(clazz.getId());
                    clazzDatasourceResult.setCode(clazz.getClazzCode());
                    clazzDatasourceResult.setName(clazz.getClazzName());
                    clazzDatasourceResultList.add(clazzDatasourceResult);
                }
                basicCourseResult.setClazzList(clazzDatasourceResultList);
            } else {
                basicCourseResult.setClazzList(new ArrayList<>());
            }
        }
        return iPage;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveBasicCourse(BasicCourseParams basicCourseParams, SysUser sysUser) {
        List<BasicCourseParams> basicCourseParamsList = new ArrayList<>();
        basicCourseParamsList.add(basicCourseParams);
        BasicCourse editBasicCourse = this.editEntityHelp(basicCourseParamsList, sysUser).get(0);
        this.saveOrUpdate(editBasicCourse);
        return editBasicCourse.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeBasicCourseBatch(List<Long> idList, Boolean enable) {
        Long schoolId = SystemConstant.convertIdToLong(ServletUtil.getRequestHeaderSchoolId().toString());
        if (idList.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("请选择要目标");
        }
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        if (!enable) {
            // 批量禁用判断
            // 业务判断
            Set<String> courseCodeSet = idList.stream().map(e -> {
                BasicCourse basicCourse = this.getById(e);
                if (Objects.isNull(basicCourse)) {
                    throw ExceptionResultEnum.ERROR.exception("未找到课程");
                }
                return basicCourse.getCode();
            }).collect(Collectors.toSet());
            Set<Map<String, Object>> mapList = basicCourseMapper.findExamTaskByCourseCode(schoolId, courseCodeSet);
            if (mapList.size() > 0) {
                StringBuilder courseNames = new StringBuilder();
                for (Map<String, Object> map : mapList) {
                    courseNames.append(map.get("courseName")).append(",");
                }
                throw ExceptionResultEnum.ERROR.exception("课程 ： 【" + courseNames.substring(0, courseNames.length() - 1) + "】 已经生成了命题任务，不允许禁用");
            }
        }
        // 课程批量启用禁用
        basicUserCourseService.update(new UpdateWrapper<BasicUserCourse>().lambda()
                .in(BasicUserCourse::getCourseId, idList)
                .eq(BasicUserCourse::getSchoolId, sysUser.getSchoolId())
                .set(BasicUserCourse::getEnable, enable)
                .set(BasicUserCourse::getUpdateId, sysUser.getId()));

        UpdateWrapper<BasicCourse> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(BasicCourse::getEnable, enable)
                .in(BasicCourse::getId, idList)
                .set(BasicCourse::getUpdateId, sysUser.getId());

        return this.update(updateWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean removeBasicCourseBatchByQuery(Long belongOrgId, String courseName, Long startCreateTime, Long endCreateTime, Boolean enable, Boolean enableOperate) {
        QueryWrapper<BasicCourse> basicCourseQueryWrapper = new QueryWrapper<>();
        if (SystemConstant.longNotNull(belongOrgId)){
            basicCourseQueryWrapper.lambda().eq(BasicCourse::getTeachingRoomId,belongOrgId);
        }
        if (SystemConstant.strNotNull(courseName)){
            basicCourseQueryWrapper.lambda().like(BasicCourse::getName,SystemConstant.translateSpecificSign(courseName));
        }
        if (SystemConstant.longNotNull(startCreateTime)){
            basicCourseQueryWrapper.lambda().ge(BasicCourse::getCreateTime,startCreateTime);
        }
        if (SystemConstant.longNotNull(endCreateTime)){
            basicCourseQueryWrapper.lambda().le(BasicCourse::getCreateTime,endCreateTime);
        }
        if (Objects.nonNull(enable)){
            basicCourseQueryWrapper.lambda().eq(BasicCourse::getEnable,enable);
        }
        List<BasicCourse> basicCourseList = this.list(basicCourseQueryWrapper);
        List<Long> idList = basicCourseList.stream().map(BaseEntity::getId).distinct().collect(Collectors.toList());

        return idList.size() > 0 ? this.removeBasicCourseBatch(idList, enableOperate): true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> executeBasicCourseImportLogic(List<LinkedMultiValueMap<Integer, Object>> finalList, Map<String, Object> map) {
        SysUser sysUser = (SysUser) map.get(SystemConstant.SYS_USER);
        Long schoolId = sysUser.getSchoolId();
        List<BasicCourseParams> addBasicCourseParamsList = new ArrayList<>();
        for (int i = 0; i < finalList.size(); i++) {
            LinkedMultiValueMap<Integer, Object> excelMap = finalList.get(i);
            List<Object> basicCourseImportDtoList = excelMap.get(i);
            assert basicCourseImportDtoList != null;
            if (basicCourseImportDtoList.get(0) instanceof DescribeImportDto) {
                continue;
            }
            for (int y = 0; y < Objects.requireNonNull(basicCourseImportDtoList).size(); y++) {
                BasicCourseImportDto basicCourseImportDto = (BasicCourseImportDto) basicCourseImportDtoList.get(y);
                String courseName = basicCourseImportDto.getCourseName();
                String courseCode = basicCourseImportDto.getCourseCode();
                String teachingRoomName = basicCourseImportDto.getTeachingRoomName();
                String clazz = basicCourseImportDto.getClazz();

                SysOrg sysOrg = sysOrgService.getOne(new QueryWrapper<SysOrg>().lambda()
                        .eq(SysOrg::getSchoolId, schoolId)
                        .eq(SysOrg::getEnable, true)
                        .eq(SysOrg::getType, OrgTypeEnum.TEACHING_ROOM)
                        .eq(SysOrg::getName, teachingRoomName));
                if (Objects.isNull(sysOrg)) {
                    throw ExceptionResultEnum.ERROR.exception("输入的教研室【" + teachingRoomName + "】不存在");
                }
                Long teachingRoomId = sysOrg.getId();
                LinkedHashSet<Long> clazzIdSet = new LinkedHashSet<>();
                if (SystemConstant.strNotNull(clazz)){
                    String[] clazzList = clazz.split(SystemConstant.COMMA);
                    for (String clzName : clazzList) {
                        BasicClazz basicClazz = basicClazzService.getOne(new QueryWrapper<BasicClazz>().lambda()
                                .eq(BasicClazz::getEnable, true)
                                .eq(BasicClazz::getSchoolId, schoolId)
                                .eq(BasicClazz::getClazzName, clzName));
                        if (Objects.isNull(basicClazz)) {
                            throw ExceptionResultEnum.ERROR.exception("所选择【班级】" + clzName + "不存在");
                        }
                        clazzIdSet.add(basicClazz.getId());
                    }
                }

                BasicCourseParams basicCourseParams = new BasicCourseParams();
                basicCourseParams.setCourseCode(courseCode);
                basicCourseParams.setCourseName(courseName);
                basicCourseParams.setTeachingRoomId(teachingRoomId);
                basicCourseParams.setClazzIdSet(clazzIdSet);
                BasicCourse old = this.getOne(new QueryWrapper<BasicCourse>().lambda()
                        .eq(BasicCourse::getSchoolId, schoolId)
                        .eq(BasicCourse::getEnable, true)
                        .eq(BasicCourse::getCode, courseCode));
                if (Objects.nonNull(old)) {
                    basicCourseParams.setId(old.getId());
                }
                addBasicCourseParamsList.add(basicCourseParams);
            }
            List<BasicCourse> editBasicCourse = this.editEntityHelp(addBasicCourseParamsList, sysUser);
            this.saveOrUpdateBatch(editBasicCourse);
        }
        return map;
    }

    @Override
    public Long getOrgIdBySchoolIdAndCourseCode(Long schoolId, String courseCode) {
        if (Objects.isNull(schoolId)) {
            schoolId = Long.valueOf(ServletUtil.getRequestHeaderSchoolId().toString());
        }
        QueryWrapper<BasicCourse> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).eq(BasicCourse::getCode, courseCode);
        BasicCourse basicCourse = this.getOne(queryWrapper);
        if (Objects.isNull(basicCourse)) {
            throw ExceptionResultEnum.ERROR.exception("课程不存在");
        }

        return basicCourse.getTeachingRoomId();
    }

    @Override
    public List<BasicCourse> findBySchoolIdAndCourseCode(Long schoolId, List<String> courseCodes) {
        QueryWrapper<BasicCourse> basicCourseQueryWrapper = new QueryWrapper<>();
        basicCourseQueryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId).in(BasicCourse::getCode, courseCodes);
        return this.list(basicCourseQueryWrapper);
    }

    private List<BasicCourse> editEntityHelp(List<BasicCourseParams> basicCourseParamsList, SysUser sysUser) {
        Long schoolId = sysUser.getSchoolId();
        List<BasicCourse> basicCourseList = new ArrayList<>();
        for (BasicCourseParams basicCourseParams : basicCourseParamsList) {
            Long id = basicCourseParams.getId();
            String courseName = basicCourseParams.getCourseName();
            // 校验课程编号
            String courseCode = basicCourseParams.getCourseCode();
            BasicCourse checkCode = this.getOne(new QueryWrapper<BasicCourse>().lambda()
                    .eq(BasicCourse::getCode, courseCode)
                    .eq(BasicCourse::getSchoolId, schoolId)
                    .eq(BasicCourse::getEnable, true));
            if (Objects.nonNull(checkCode)) {
                if (!checkCode.getId().equals(id)) {
                    throw ExceptionResultEnum.ERROR.exception("课程编号【" + courseCode + "】重复");
                }
            }
            // 校验教研室id
            Long teachingRoomId = basicCourseParams.getTeachingRoomId();
            if (Objects.isNull(sysOrgService.getOne(new QueryWrapper<SysOrg>().lambda()
                    .eq(SysOrg::getId, teachingRoomId)
                    .eq(SysOrg::getEnable, true)
                    .eq(SysOrg::getType, OrgTypeEnum.TEACHING_ROOM)))) {
                throw ExceptionResultEnum.ERROR.exception("所选教研室不存在");
            }
            // 校验班级
            Set<Long> clazzIdSet = basicCourseParams.getClazzIdSet();

            //基础数据组装
            Long orgId;
            BasicCourse basicCourse = new BasicCourse();
            basicCourse.setName(courseName);
            basicCourse.setCode(courseCode);
            basicCourse.setTeachingRoomId(teachingRoomId);
            basicCourse.setSchoolId(schoolId);

            if (!SystemConstant.longNotNull(id)) {
                // 没有id -》新增
                id = SystemConstant.getDbUuid();
                basicCourse.setId(id);
                basicCourse.setCreateId(sysUser.getId());
                basicCourse.setEnable(true);
                orgId = sysUser.getOrgId();
            } else {
                // 有id -》 更新
                BasicCourse old = this.getById(id);
                if (Objects.isNull(old) || old.getEnable().equals(false)) {
                    throw ExceptionResultEnum.ERROR.exception("课程主键不存在或被禁用");
                }
                orgId = old.getOrgId();
                basicCourse.setId(id);
                basicCourse.setUpdateId(sysUser.getId());
            }
            basicCourse.setOrgId(orgId);

            // 根据课程id和授课班级集合更新'basic_user_course'表
            basicUserCourseService.updateByCourseIdAndClazzList(id, clazzIdSet, sysUser, orgId);

            basicCourseList.add(basicCourse);
        }
        return basicCourseList;
    }
}
