package cn.iocoder.yudao.module.exam.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.base.constant.SchoolBaseConstants;
import cn.iocoder.yudao.module.base.service.DlDriveSchoolStudentService;
import cn.iocoder.yudao.module.base.service.SchoolNotifyMessageSendService;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.mapper.ProcessMapper;
import cn.iocoder.yudao.module.course.service.ProcessService;
import cn.iocoder.yudao.module.exam.entity.ExamBatch;
import cn.iocoder.yudao.module.exam.entity.ExamBatchItem;
import cn.iocoder.yudao.module.exam.mapper.ExamBatchItemMapper;
import cn.iocoder.yudao.module.exam.service.ExamBatchItemService;
import cn.iocoder.yudao.module.exam.service.ExamBatchService;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemNewVO;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemVO;
import cn.iocoder.yudao.module.exam.vo.ExamBatchVO;
import cn.iocoder.yudao.module.exam.vo.ExamVO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 考试批次明细表 Service 实现类
 *
 * @author 若依
 */
@Service
public class ExamBatchItemServiceImpl extends ServiceImpl<ExamBatchItemMapper, ExamBatchItem> implements ExamBatchItemService {
    @Autowired
    private ExamBatchItemMapper examBatchItemMapper;
    @Autowired
    private ProcessMapper processMapper;
    @Autowired
    private ProcessService processService;
    @Lazy
    @Autowired
    private ExamBatchService examBatchService;
    @Autowired
    private SchoolNotifyMessageSendService schoolNotifyMessageSendService;
    @Resource
    private AdminUserApi userApi;

    @Resource
    private DlDriveSchoolStudentService dlDriveSchoolStudentService;

    /**
     * 分页查询
     *
     * @param pageReqVO TODO
     * @param page      TODO
     * @author vinjor-M
     * @date 15:05 2025/1/14
     **/
    @Override
    public IPage<ExamBatchItemVO> queryListPage(ExamBatchVO pageReqVO, Page<ExamBatchItemVO> page) {
        //教练ID
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        pageReqVO.setCoachId(userId);
        IPage<ExamBatchItemVO> rtnList = examBatchItemMapper.queryListPage(pageReqVO, page);
        return rtnList;
    }

    /**
     * 根据批次ID查所有子表记录
     *
     * @param batchId 批次ID
     * @return java.util.List<cn.iocoder.yudao.module.exam.vo.ExamBatchItemVO>
     * @author vinjor-M
     * @date 13:40 2025/1/21
     **/
    @Override
    public List<ExamBatchItemVO> selectListByBatchId(String batchId) {
        return examBatchItemMapper.selectByBatchId(batchId);
    }

    /**
     * 录入学生考试成绩
     *
     * @param examBatchVO
     * @author vinjor-M
     * @date 13:48 2025/1/21
     */
    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateObj(ExamBatchItemVO examBatchVO) {
        //教练ID
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        ExamBatchItem updateItem = this.getById(examBatchVO.getId());
        updateItem.setFraction(examBatchVO.getFraction());
        updateItem.setImages(examBatchVO.getImages());
        updateItem.setIfPass(examBatchVO.getIfPass());
        //更新子表考试结果
        this.updateById(updateItem);
        ExamBatch examBatch = examBatchService.getById(updateItem.getBatchId());
        Process process = processService.getByStudentAndCourse(updateItem.getUserId(), examBatch.getCourseId(), examBatch.getSubject(), examBatch.getCoachId(), "9");
        if (null == process) {
            throw new Exception("未找到该学生学习进度信息，请联系管理员");
        }
        //考试分数
        process.setExamScore(examBatchVO.getFraction());
        process.setImages(examBatchVO.getImages());
        process.setExamTime(examBatch.getStartTime());
        //已完成
        process.setStatus("2");
        process.setExamStatus(examBatchVO.getIfPass() ? "1" : "0");
        processService.updateById(process);
        //更新考试批次的通过率
        this.updateBatchPassRate(examBatch.getId());
        if (examBatchVO.getIfPass()) {
            //考试通过
            if (process.getSubject() < 3) {
                //科目一、二插入一条，需要查出下一个的学习进度（如果不存在，手动插入一个）
                Integer nextSubject = process.getSubject() + 1;
                LambdaQueryWrapper<Process> queryWrapper = new LambdaQueryWrapper<Process>()
                        .eq(Process::getCourseId, process.getCourseId())
                        .eq(Process::getUserId, process.getUserId())
                        .eq(Process::getSubject, nextSubject)
                        .eq(Process::getStatus, "0");
                List<Process> list = processService.list(queryWrapper);
                if (list.isEmpty()) {
                    //插入
                    Process nextProcess = new Process();
                    nextProcess.setCourseId(process.getCourseId());
                    nextProcess.setCourseName(process.getCourseName());
                    nextProcess.setUserId(process.getUserId());
                    nextProcess.setUserName(process.getUserName());
                    nextProcess.setUserMobile(process.getUserMobile());
                    nextProcess.setCoachName(process.getCoachName());
                    nextProcess.setSubject(process.getSubject() + 1);
                    nextProcess.setExamNum(process.getExamNum() + 1);
                    nextProcess.setStatus("1");
                    nextProcess.setTrainTime((double) 0);
                    processService.save(nextProcess);
                } else {
                    //更新状态为进行中
                    Process nextProcess = list.get(0);
                    nextProcess.setStatus("1");
                    processService.updateById(nextProcess);
                }
            }
        } else {
            //考试不通过,重新插入一条本科目的学习记录-并改为进行中
            Process thisProcess = new Process();
            thisProcess.setCourseId(process.getCourseId());
            thisProcess.setCourseName(process.getCourseName());
            thisProcess.setUserId(process.getUserId());
            thisProcess.setUserName(process.getUserName());
            thisProcess.setUserMobile(process.getUserMobile());
            thisProcess.setCoachId(process.getCoachId());
            thisProcess.setCoachName(process.getCoachName());
            thisProcess.setSubject(process.getSubject());
            thisProcess.setExamNum(process.getExamNum() + 1);
            thisProcess.setStatus("1");
            thisProcess.setTrainTime(process.getTrainTime());
            processService.save(thisProcess);
        }

    }

    /**
     * 更新考试批次通过率
     *
     * @param id 批次ID
     * @author vinjor-M
     * @date 17:39 2025/2/7
     **/
    public void updateBatchPassRate(String id) {
        ExamBatch examBatch = examBatchService.getById(id);
        LambdaQueryWrapper<ExamBatchItem> queryWrapper = new LambdaQueryWrapper<ExamBatchItem>()
                .eq(ExamBatchItem::getBatchId, id);
        List<ExamBatchItem> allList = this.list(queryWrapper);
        if (!allList.isEmpty()) {
            List<ExamBatchItem> passList = allList.stream().filter(item -> null != item.getIfPass() && item.getIfPass()).collect(Collectors.toList());
            if (!passList.isEmpty()) {
                BigDecimal result = new BigDecimal(passList.size()).divide(new BigDecimal(allList.size()), 2, RoundingMode.HALF_UP);
                examBatch.setPassRate(result.doubleValue());
                examBatchService.updateById(examBatch);
            }
        }
    }

    /**
     * 更新考试批次通过率
     * 手动录入/修改成绩使用
     *
     * @param id 批次ID
     * @author vinjor-M
     * @date 17:39 2025/2/7
     **/
    @Transactional(rollbackFor = Exception.class)  // 添加事务，确保数据一致性
    public void updateBatchPassRateNew(String id) {
        // 查询考试批次信息
        ExamBatch examBatch = examBatchService.getById(id);
        if (examBatch == null) {
            throw new RuntimeException("考试批次不存在");
        }

        // 查询该批次下的所有考试项
        LambdaQueryWrapper<ExamBatchItem> queryWrapper = new LambdaQueryWrapper<ExamBatchItem>()
                .eq(ExamBatchItem::getBatchId, id);
        List<ExamBatchItem> allList = this.list(queryWrapper);

        // 如果没有考试项，直接返回（或设为0，取决于业务需求）
        if (allList.isEmpty()) {
            examBatchService.updateById(examBatch);
            return;
        }

        // 筛选通过的考试项
        List<ExamBatchItem> passList = allList.stream()
                .filter(item -> item.getIfPass() != null && item.getIfPass())
                .collect(Collectors.toList());

        // 计算通过率（兼容无人通过的情况）
        double passRate = passList.isEmpty() ? 0.0 :
                new BigDecimal(passList.size())
                        .divide(new BigDecimal(allList.size()), 2, RoundingMode.HALF_UP)
                        .doubleValue();

        // 更新考试批次通过率
        examBatch.setPassRate(passRate);
        examBatchService.updateById(examBatch);
    }

    /**
     * 根据学生id和教练ID查询考试记录
     *
     * @param userId  学生ID
     * @param coachId 教练ID，可能为空
     * @return java.util.List<cn.iocoder.yudao.module.exam.vo.ExamBatchItemVO>
     * @author vinjor-M
     * @date 16:38 2025/2/10
     **/
    @Override
    public List<ExamBatchItemVO> selectByUserIdAndCoachId(Long userId, Long coachId) {
        return examBatchItemMapper.selectByUserIdAndCoachId(userId, coachId);
    }

    /**
     * 根据学生id和教练ID查询考试记录
     *
     * @param userId  学生ID
     * @param coachId 教练ID，可能为空
     * @return java.util.List<cn.iocoder.yudao.module.exam.vo.ExamBatchItemVO>
     * @author vinjor-M
     * @date 16:38 2025/2/10
     **/
    @Override
    public List<ExamVO> selectExamByUserIdAndCoachId(Long userId, Long coachId) {
        return examBatchItemMapper.selectExamByUserIdAndCoachId(userId, coachId);
    }

    /**
     * 录入学生考试成绩
     *
     * @param examBatchVO
     * @author vinjor-M
     * @date 13:48 2025/1/21
     */
    @SneakyThrows
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateObjNew(ExamBatchItemNewVO examBatchVO) {
        String subject = "";
        if (examBatchVO.getSubject() == 2) {
            subject = "科目二";
        } else if (examBatchVO.getSubject() == 3) {
            subject = "科目三";
        }
        //教练ID
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        AdminUserRespDTO user = userApi.getUser(userId);
        String userName = user.getNickname();
        ExamBatchItem updateItem = this.getById(examBatchVO.getId());
        updateItem.setFraction(examBatchVO.getFraction());
        updateItem.setImages(examBatchVO.getImages());
        updateItem.setIfPass(examBatchVO.getIfPass());
        //更新子表考试结果
        this.updateById(updateItem);
        ExamBatch examBatch = examBatchService.getById(updateItem.getBatchId());
        Process process = processService.getByStudentAndCourse(updateItem.getUserId(), examBatch.getCourseId(), examBatch.getSubject(), examBatch.getCoachId(), "9");
        if (null == process) {
            throw new Exception("未找到该学生学习进度信息，请联系管理员");
        }
        //考试分数
        process.setExamScore(examBatchVO.getFraction());
        process.setImages(examBatchVO.getImages());
        process.setExamTime(examBatch.getStartTime());
        process.setRemark(examBatchVO.getRemark());
        //已完成
        process.setExamNum(process.getExamNum() + 1);
        process.setExamStatus(examBatchVO.getIfPass() ? "1" : "0");

        processService.updateById(process);

        //更新考试批次的通过率
        this.updateBatchPassRate(examBatch.getId());
        if (examBatchVO.getIfPass()) {
            process.setStatus("2");
            processService.updateById(process);
            String message = String.format(SchoolBaseConstants.SCHOOL_NOTIFY_MESSAGE_TEMPLATE_MEMBER_EXAM_SCORE, userName, subject, examBatchVO.getFraction(), "已通过");
            schoolNotifyMessageSendService.sendMessage(examBatchVO.getCoachId(), message, SchoolBaseConstants.SCHOOL_NOTIFY_MESSAGE_TYPE_ADMIN, examBatchVO.getTenantId());

            //考试通过
            if (process.getSubject() == 3 || process.getSubject() == 2) {
                Integer nextSubject = process.getSubject() + 1;
                LambdaQueryWrapper<Process> queryWrapper = new LambdaQueryWrapper<Process>()
                        .eq(Process::getCourseId, process.getCourseId())
                        .eq(Process::getUserId, process.getUserId())
                        .eq(Process::getSubject, nextSubject)
                        .eq(Process::getTenantId, process.getTenantId());
                List<Process> list = processService.list(queryWrapper);
                if (!list.isEmpty()) {
                    Process nextProcess = list.get(0);
                    if (!"2".equals(nextProcess.getStatus())) {
                        nextProcess.setStatus("1");
                        processService.updateById(nextProcess);
                    }
                }
                // 科目三通过之后更新学员毕业时间
                if(process.getSubject() == 3){
                    dlDriveSchoolStudentService.updateStudentGradTime(process.getUserId(), process.getCourseId(), process.getTenantId());
                }
            }
        } else {
            //考试不通过
            process.setStatus("1");
            process.setExamStatus("0");
            process.setExamNum(process.getExamNum() + 1);
            processService.updateById(process);
            // 发送消息给教练
            String message = String.format(SchoolBaseConstants.SCHOOL_NOTIFY_MESSAGE_TEMPLATE_MEMBER_EXAM_SCORE, userName, subject, examBatchVO.getFraction(), "未通过");
            schoolNotifyMessageSendService.sendMessage(examBatchVO.getCoachId(), message, SchoolBaseConstants.SCHOOL_NOTIFY_MESSAGE_TYPE_ADMIN, examBatchVO.getTenantId());

        }

    }

    /**
     * 通过批次详情id集合查询
     *
     * @param examIds
     * @return
     */
    @Override
    public List<ExamBatchItemVO> listJoinBatchByIds(List<String> examIds) {
        if (CollUtil.isEmpty(examIds)) return null;
        return baseMapper.listJoinBatchByIds(examIds);
    }

    /**
     * 所有教练所有考试信息
     *
     * @param
     * @return
     */
    @Override
    public IPage<ExamBatchVO> batchItemListByCoach(ExamBatchVO examBatchVO, Page<ExamBatchVO> page) {
        if (examBatchVO == null) {
            return null;
        }
        String startTimeStr = "";
        String endTimeStr = "";
        String startTime = examBatchVO.getStartTimeSearch();
        String endTime = examBatchVO.getEndTimeSearch();
        String timeType = examBatchVO.getTimeType();
        if("more".equals(timeType)){
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(startTime)){
                startTimeStr = startTime+" 00:00:01";
            }
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(endTime)) {
                endTimeStr = endTime + " 23:59:59";
            }
        }else if("month".equals(timeType)){
            //当月
            startTimeStr = DateUtil.format(DateUtil.beginOfMonth(DateUtil.date()),"yyyy-MM-dd")+" 00:00:01";
            endTimeStr = DateUtil.format(DateUtil.endOfMonth(DateUtil.date()),"yyyy-MM-dd")+" 23:59:59";
        }else if("day".equals(timeType)){
            //当天
            startTimeStr = DateUtil.formatDate(DateUtil.date())+" 00:00:01";
            endTimeStr = DateUtil.formatDate(DateUtil.date())+" 23:59:59";
        }
        examBatchVO.setStartTimeSearch(startTimeStr);
        examBatchVO.setEndTimeSearch(endTimeStr);
        return baseMapper.batchItemListByCoach(examBatchVO, page);
    }
}
