package com.ruoyi.hezhi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.hezhi.domain.*;
import com.ruoyi.hezhi.domain.vo.CareerExamListVO;
import com.ruoyi.hezhi.domain.vo.CourseListVO;
import com.ruoyi.hezhi.domain.vo.StudyCenterTeacherVO;
import com.ruoyi.hezhi.domain.vo.StudyCenterVO;
import com.ruoyi.hezhi.mapper.*;
import com.ruoyi.hezhi.service.ITbExamService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 考试Service业务层处理
 *
 * @author ruoyi
 * @date 2024-11-12
 */
@Service
public class TbExamServiceImpl implements ITbExamService
{
    @Autowired
    private TbExamMapper tbExamMapper;
    @Autowired
    private TbExamCourseMapper tbExamCourseMapper;
    @Resource
    private TbCourseMapper tbCourseMapper;
    @Resource
    private TbStudyCenterMapper tbStudyCenterMapper;
    @Resource
    private TbStudyCenterTeacherMapper tbStudyCenterTeacherMapper;
    @Resource
    private TbExamBatchMapper tbExamBatchMapper;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 查询考试
     *
     * @param examId 考试主键
     * @return 考试
     */
    @Override
    public TbExam selectTbExamByExamId(Long examId)
    {
        TbExam tbExam = tbExamMapper.selectTbExamByExamId(examId);
        if (ObjectUtils.isNotEmpty(tbExam)){
            List<TbExamCourse> examCourseList = tbExamCourseMapper.getExamCourseList(null, tbExam.getExamId(), null, null);
            tbExam.setExamCourseList(examCourseList);

            List<TbExamBatch> tbExamBatchList = tbExamBatchMapper.getByExamId(tbExam.getExamId());
            tbExam.setExamBatchList(tbExamBatchList);
        }
        return tbExam;
    }

    /**
     * 查询考试列表
     *
     * @param tbExam 考试
     * @return 考试
     */
    @Override
    public List<TbExam> selectTbExamList(TbExam tbExam)
    {
        return tbExamMapper.selectTbExamList(tbExam);
    }

    /**
     * 新增考试
     *
     * @param tbExam 考试
     * @return 结果
     */
    @Transactional
    @Override
    public int insertTbExam(TbExam tbExam)
    {
        //校验报名费是不是符合BigDecimal
        if (ObjectUtils.isNotEmpty(tbExam.getPrice())){
            String price = tbExam.getPrice().toString();
            if (!price.matches("^[0-9]+(\\.[0-9]+)?$")){
                throw new ServiceException("报名费格式错误");
            }
        }
        // 校验必须 > 0
        if (tbExam.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("报名费必须大于0");
        }
        if (StringUtils.isEmpty(tbExam.getName())){
            throw new ServiceException("考试名称不能为空");
        }
        //先判断考试名称是否重复
        List<TbExam> tbExamList = tbExamMapper.selectTbExamListByName(tbExam);
        if(!CollUtil.isEmpty(tbExamList)){
            throw new ServiceException("考试名称不能重复");
        }

        //先插入考试表获取主键
        tbExam.setExamNo(IdUtils.getOrderNum());
        tbExam.setCreateTime(DateUtils.getNowDate());
        int result = tbExamMapper.insertTbExam(tbExam);

        // 新增考试课程
        List<TbExamCourse> examCourseList = tbExam.getExamCourseList();
        if (!examCourseList.isEmpty()){
            for (TbExamCourse tbExamCourse : examCourseList) {
                tbExamCourse.setExamId(tbExam.getExamId());
                tbExamCourseMapper.insertTbExamCourse(tbExamCourse);
            }
        }

        // 考试批次
        List<TbExamBatch> tbExamBatchList = tbExam.getExamBatchList();
        if (!tbExamBatchList.isEmpty()){
            Date[] examStartTimeArr = new Date[tbExamBatchList.size()];
            Date[] examEndTimeArr = new Date[tbExamBatchList.size()];
            for (int i = 0; i < tbExamBatchList.size(); i++) {
                TbExamBatch tbExamBatch = tbExamBatchList.get(i);
                tbExamBatch.setExamId(tbExam.getExamId());
                tbExamBatch.setBatchIndex(i+1L);

                examStartTimeArr[i] = tbExamBatch.getExamStartTime();
                examEndTimeArr[i] = tbExamBatch.getExamEndTime();
            }

            for (int i = 0; i < tbExamBatchList.size(); i++) {
                Date examStartTime = examStartTimeArr[i];
                Date examEndTime = examEndTimeArr[i];

                for (int f = 0; f < tbExamBatchList.size(); f++) {
                    if (i!=f){
                        Date signStartTimeF = examStartTimeArr[f];
                        Date examEndTimeTimeF = examEndTimeArr[f];
                        // 检查第一个时间段是否完全在第二个时间段之前
                        if (examEndTime.before(signStartTimeF)) {
                            continue;
                        }
                        // 检查第二个时间段是否完全在第一个时间段之前
                        if (examEndTimeTimeF.before(examStartTime)) {
                            continue;
                        }
                        // 如果有上述情况都不成立，则时间段有交集
                        throw new ServiceException(tbExamBatchList.get(f).getExamBatch()+"时间设置和"+tbExamBatchList.get(f-1).getExamBatch()+"存在重合");
                    }
                }
            }
            tbExamBatchMapper.insertTbExamBatchBatch(tbExamBatchList);
        }
        return result;
    }

    /**
     * 修改考试
     *
     * @param tbExam 考试
     * @return 结果
     */
    @Override
    public int updateTbExam(TbExam tbExam)
    {
        //校验报名费是不是符合BigDecimal
        if (ObjectUtils.isNotEmpty(tbExam.getPrice())){
            String price = tbExam.getPrice().toString();
            if (!price.matches("^[0-9]+(\\.[0-9]+)?$")){
                throw new ServiceException("报名费格式错误");
            }
        }
        // 校验必须 > 0
        if (tbExam.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("报名费必须大于0");
        }
        // 新增考试课程
        List<TbExamCourse> examCourseList = tbExam.getExamCourseList();
        if (!examCourseList.isEmpty()){
            tbExamCourseMapper.deleteTbExamCourse(null, tbExam.getExamId(), null, null);
            for (TbExamCourse tbExamCourse : examCourseList) {
                tbExamCourse.setExamId(tbExam.getExamId());
                tbExamCourseMapper.insertTbExamCourse(tbExamCourse);
            }
        }
        //todo 删除逻辑
//
//        List<TbExamBatch> existingBatches = tbExamBatchMapper.getByExamId(tbExam.getExamId());
//        //存在的批次
//        Map<Long, TbExamBatch> existingBatchMap = existingBatches.stream()
//                .collect(Collectors.toMap(TbExamBatch::getBatchIndex, Function.identity()));
//
//        // 2. 获取当前提交的批次（必须包含原来的 batchIndex）
//        List<TbExamBatch> newBatches = tbExam.getExamBatchList();
//        Set<Long> newBatchIndexes = newBatches.stream()
//                .map(TbExamBatch::getBatchIndex)
//                .collect(Collectors.toSet());
//
//        // 3. 获取被移除的批次的主键 ID，转换为 Long[]
//        Long[] toDeleteIds = existingBatches.stream()
//                .filter(old -> !newBatchIndexes.contains(old.getBatchIndex()))
//                .map(TbExamBatch::getExamBatchId)
//                .toArray(Long[]::new);
//
//        // 4. 删除操作
//        if (toDeleteIds.length > 0) {
//            tbExamBatchMapper.deleteTbExamBatchByExamBatchIds(toDeleteIds);
//        }
//
//        List<TbExamBatch> toInsert = new ArrayList<>();
//        List<TbExamBatch> toUpdate = new ArrayList<>();
//
//        for (TbExamBatch newBatch : newBatches) {
//            newBatch.setExamId(tbExam.getExamId()); // 保证 examId 正确
//            if (existingBatchMap.containsKey(newBatch.getBatchIndex())) {
//                // 是更新：保留已有的主键 ID
//                TbExamBatch existing = existingBatchMap.get(newBatch.getBatchIndex());
//                newBatch.setExamBatchId(existing.getExamBatchId());
//                toUpdate.add(newBatch);
//            } else {
//                // 是新增
//                toInsert.add(newBatch);
//            }
//        }
//        if (!toInsert.isEmpty()) {
//            tbExamBatchMapper.insertTbExamBatchBatch(toInsert);
//        }
//
//        if (!toUpdate.isEmpty()) {
//            tbExamBatchMapper.updateTbExamBatchBatch(toUpdate); // 你需要写批量 update 逻辑
//        }

        // 考试批次
        List<TbExamBatch> tbExamBatchList = tbExam.getExamBatchList();
        if (!tbExamBatchList.isEmpty()){
            tbExamBatchMapper.deleteByExamId(tbExam.getExamId());
            Date[] examStartTimeArr = new Date[tbExamBatchList.size()];
            Date[] examEndTimeArr = new Date[tbExamBatchList.size()];
            for (int i = 0; i < tbExamBatchList.size(); i++) {
                TbExamBatch tbExamBatch = tbExamBatchList.get(i);
                tbExamBatch.setExamId(tbExam.getExamId());
                tbExamBatch.setBatchIndex(i+1L);

                examStartTimeArr[i] = tbExamBatch.getExamStartTime();
                examEndTimeArr[i] = tbExamBatch.getExamEndTime();
            }

            for (int i = 0; i < tbExamBatchList.size(); i++) {
                Date examStartTime = examStartTimeArr[i];
                Date examEndTime = examEndTimeArr[i];

                for (int f = 0; f < tbExamBatchList.size(); f++) {
                    if (i!=f){
                        Date signStartTimeF = examStartTimeArr[f];
                        Date examEndTimeTimeF = examEndTimeArr[f];

                        // 检查第一个时间段是否完全在第二个时间段之前
                        if (examEndTime.before(signStartTimeF)) {
                            continue;
                        }
                        // 检查第二个时间段是否完全在第一个时间段之前
                        if (examEndTimeTimeF.before(examStartTime)) {
                            continue;
                        }
                        // 如果有上述情况都不成立，则时间段有交集
                        throw new ServiceException(tbExamBatchList.get(f).getExamBatch()+"时间设置和"+tbExamBatchList.get(f-1).getExamBatch()+"存在重合");
                    }
                }
            }
            tbExamBatchMapper.insertTbExamBatchBatch(tbExamBatchList);
        }

        tbExam.setUpdateTime(DateUtils.getNowDate());
        return tbExamMapper.updateTbExam(tbExam);
    }

    /**
     * 批量删除考试
     *
     * @param examIds 需要删除的考试主键
     * @return 结果
     */
    @Override
    public int deleteTbExamByExamIds(Long[] examIds)
    {
        return tbExamMapper.deleteTbExamByExamIds(examIds);
    }

    /**
     * 删除考试信息
     *
     * @param examId 考试主键
     * @return 结果
     */
    @Override
    public int deleteTbExamByExamId(Long examId)
    {
        return tbExamMapper.deleteTbExamByExamId(examId);
    }

    /**
     * 职业考试列表
     *
     * @param params 参数
     * @return 职业考试列表
     */
    @Override
    public List<CareerExamListVO> getCareerExamList(Map<String, Object> params) {
        return tbExamMapper.getCareerExamList(params);
    }

    /**
     * 职业考试详情
     *
     * @param params 参数
     * @return 职业考试详情
     */
    @Override
    public Map<String, Object> getCareerExamInfo(Map<String, Object> params) {
        return tbExamMapper.getCareerExamInfo(params);
    }

    @Override
    public List<CourseListVO> getCourseListByEvaluateAgency(Long evaluateAgencyId) {
        List<CourseListVO> courseListByEvaluateAgency = tbCourseMapper.getCourseListByEvaluateAgency(evaluateAgencyId);
        if (!courseListByEvaluateAgency.isEmpty()){
            try {
                CountDownLatch countDownLatch = new CountDownLatch(courseListByEvaluateAgency.size());
                for (CourseListVO courseListVO : courseListByEvaluateAgency) {
                    threadPoolTaskExecutor.execute(()->{
                        Long courseId = courseListVO.getCourseId();
                        TbExamCourse tbExamCourse = tbExamCourseMapper.getExamIdByCourseId(courseId);
                        if (ObjectUtils.isNotEmpty(tbExamCourse)){
                            Long examId = tbExamCourse.getExamId();
                            TbExam tbExam = tbExamMapper.selectTbExamByExamId(examId);
                            List<TbExamBatch> enableByExamId = tbExamBatchMapper.getEnableByExamId(examId, tbExam.getExamBatchEarly());
                            if (!enableByExamId.isEmpty()){
                                TbExamBatch tbExamBatch = enableByExamId.get(0);
                                courseListVO.setExamBatch(tbExamBatch.getExamBatch());
                                courseListVO.setExamId(tbExam.getExamId());
                                courseListVO.setLevel(getLevel(tbExam.getLevel()));//等级也查出来
                            }
                        }
                        countDownLatch.countDown();
                    });
                }
                countDownLatch.await();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return courseListByEvaluateAgency;
    }

    //等级转换方法
    public String getLevel(Integer level) {
        if (level == null) {
            return null;
        }
        switch (level) {
            case 1:
                return "初级";
            case 2:
                return "中级";
            case 3:
                return "高级";
            default:
                return null;
        }
    }

    @Override
    public List<StudyCenterVO> getStudyListByCourse(Long courseId) {
        List<StudyCenterVO> studyCenterList = tbStudyCenterMapper.getStudyListByCourse(courseId);
        if (!studyCenterList.isEmpty()){
            for (StudyCenterVO studyCenterVO : studyCenterList) {
                Long studyCenterId = studyCenterVO.getStudyCenterId();
                List<TbStudyCenterTeacher> tbStudyCenterTeacherList = tbStudyCenterTeacherMapper.getByStudyCenterId(studyCenterId);

                List<TbStudyCenterTeacher> subList=new ArrayList<>();
                // 截取前三个元素
                if (tbStudyCenterTeacherList.size()>3){
                    subList = tbStudyCenterTeacherList.subList(0, 3);
                }else {
                    subList = tbStudyCenterTeacherList;
                }
                studyCenterVO.setStudyCenterTeacherList(BeanUtil.copyToList(subList, StudyCenterTeacherVO.class));
            }
        }
        return studyCenterList;
    }
}
