package com.qmth.exam.reserve.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.boot.core.collection.PageResult;
import com.qmth.boot.core.exception.StatusException;
import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
import com.qmth.exam.reserve.bean.login.LoginUser;
import com.qmth.exam.reserve.bean.stdapply.CategoryVO;
import com.qmth.exam.reserve.bean.task.ApplyTaskPageReq;
import com.qmth.exam.reserve.bean.task.ApplyTaskReq;
import com.qmth.exam.reserve.bean.task.ApplyTaskRuleVO;
import com.qmth.exam.reserve.bean.task.ApplyTaskVO;
import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
import com.qmth.exam.reserve.dao.ApplyTaskDao;
import com.qmth.exam.reserve.entity.ApplyTaskEntity;
import com.qmth.exam.reserve.entity.StudentApplyEntity;
import com.qmth.exam.reserve.enums.EventType;
import com.qmth.exam.reserve.service.ApplyTaskService;
import com.qmth.exam.reserve.service.OperateLogService;
import com.qmth.exam.reserve.service.StudentApplyService;
import com.qmth.exam.reserve.service.TimePeriodService;
import com.qmth.exam.reserve.util.PageUtil;

@Service
public class ApplyTaskServiceImpl extends ServiceImpl<ApplyTaskDao, ApplyTaskEntity> implements ApplyTaskService {

    @Autowired
    private OperateLogService logService;

    @Autowired
    private ApplyTaskCacheService cacheService;

    @Autowired
    private StudentApplyService studentApplyService;

    @Autowired
    private TimePeriodService timePeriodService;

    @Override
    public PageResult<ApplyTaskVO> page(ApplyTaskPageReq req) {
        IPage<ApplyTaskVO> iPage = this.baseMapper.page(new Page<ApplyTaskVO>(req.getPageNumber(), req.getPageSize()),
                req);
        return PageUtil.of(iPage);
    }

    @Override
    public ApplyTaskRuleVO find(Long id) {
        ApplyTaskRuleVO task = this.baseMapper.find(id);
        if (StringUtils.isEmpty(task)) {
            throw new StatusException("预约任务不存在！");
        }
        task.setTimeList(this.baseMapper.getTimePeriodList(id));
        return task;
    }

    @Override
    public void saveRule(ApplyTaskReq req, LoginUser user) {
        checkRule(req);
        ApplyTaskEntity task = new ApplyTaskEntity();
        BeanUtils.copyProperties(req, task);
        task.setAllowApplyDays(task.getAllowApplyCancelDays());
        if (req.getId() == null) {
            task.setEnable(Boolean.FALSE);
        }
        task.setOrgId(user.getOrgId());
        this.saveOrUpdate(task);
        cacheService.clearCurrentApplyTaskCache(task.getOrgId());
    }

    private void checkRule(ApplyTaskReq req) {
        if (StringUtils.isEmpty(req.getName()))
            throw new StatusException("请填写任务名称");
        if (StringUtils.isEmpty(req.getAllowApplyCancelDays()))
            throw new StatusException("请填写学生自主操作限制的天数");
        if (StringUtils.isEmpty(req.getSelfApplyStartTime()))
            throw new StatusException("请填写自主预约起始时间");
        if (StringUtils.isEmpty(req.getSelfApplyEndTime()))
            throw new StatusException("请填写自主预约截止时间");
        if (StringUtils.isEmpty(req.getOpenApplyStartTime()))
            throw new StatusException("请填写开放式预约起始时间");
        if (StringUtils.isEmpty(req.getOpenApplyEndTime()))
            throw new StatusException("请填写开放式预约截止时间");
        if (req.getSelfApplyStartTime() >= req.getSelfApplyEndTime())
            throw new StatusException("第一阶段起始时间必须小于截止时间");
        if (req.getOpenApplyStartTime() >= req.getOpenApplyEndTime())
            throw new StatusException("第三阶段起始时间必须小于截止时间");
        if (req.getSelfApplyEndTime() >= req.getOpenApplyStartTime())
            throw new StatusException("第三阶段的时间必须在第一阶段结束之后");
    }

    @Override
    public List<CategoryVO> listTask() {
        List<CategoryVO> categoryList = new ArrayList<CategoryVO>();
        QueryWrapper<ApplyTaskEntity> wrapper = new QueryWrapper<>();
        LambdaQueryWrapper<ApplyTaskEntity> lw = wrapper.lambda();
        lw.eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
        List<ApplyTaskEntity> taskList = this.getBaseMapper().selectList(wrapper);
        for (ApplyTaskEntity task : taskList) {
            CategoryVO category = new CategoryVO();
            category.setId(task.getId());
            category.setName(task.getName());
            categoryList.add(category);
        }
        return categoryList;
    }

    /**
     * 获取当前启用的预约任务
     */
    @Override
    public CurrentApplyTaskVO currentApplyTask(Long orgId) {
        // 默认取一个最新的启用的预约任务
        return baseMapper.currentApplyTask(orgId);
    }

    @Override
    public ApplyTaskEntity getLessInfoApplyTaskById(Long applyTaskId) {
        // 只查询id、name、enable等少量字段
        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ApplyTaskEntity::getId, ApplyTaskEntity::getName, ApplyTaskEntity::getEnable);
        wrapper.eq(ApplyTaskEntity::getId, applyTaskId);
        return this.getOne(wrapper);
    }

    @Override
    public ApplyTaskEntity findApplyTask() {
        LambdaQueryWrapper<ApplyTaskEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
        return baseMapper.selectOne(wrapper);
    }

    @Override
    public void saveNotice(Long userId, Long id, String notice) {
        ApplyTaskEntity task = checkTask(id);
        task.setNotice(notice);
        this.updateById(task);
        logService.insertOperateLog(userId, EventType.SAVE_NOTICE, null);
    }

    @Override
    public void enable(Long userId, Long id, Boolean enable) {
        ApplyTaskEntity task = checkTask(id);
        if (enable) {
            LambdaQueryWrapper<ApplyTaskEntity> query = new LambdaQueryWrapper<>();
            query.eq(ApplyTaskEntity::getEnable, Boolean.TRUE);
            ApplyTaskEntity existTask = this.getOne(query);
            if (existTask != null)
                throw new StatusException("只能有一个任务是开启状态");
        } else {
            // 清空redis中的缓存
            cacheService.clearCurrentApplyTaskCache(task.getOrgId());
        }

        task.setEnable(enable);
        updateById(task);
        logService.insertOperateLog(userId, EventType.ENABLE_APPLY_TASK, null);
    }

    private ApplyTaskEntity checkTask(Long id) {
        ApplyTaskEntity task = getById(id);
        if (task == null)
            throw new StatusException("预约任务不存在");
        return task;
    }

    @Override
    public void deleteRule(Long timeId) {
        if (timeId == null)
            return;
        LambdaQueryWrapper<StudentApplyEntity> lm = new LambdaQueryWrapper<>();
        lm.eq(StudentApplyEntity::getTimePeriodId, timeId);
        List<StudentApplyEntity> applyList = studentApplyService.list(lm);
        if (applyList != null && applyList.size() > 0) {
            throw new StatusException("考生已经预约，不能删除预约时段");
        }
        timePeriodService.removeById(timeId);
    }

}
