package com.zhongzheng.modules.exam.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zhongzheng.common.utils.DateUtils;
import com.zhongzheng.common.utils.ServletUtils;
import com.zhongzheng.modules.exam.bo.*;
import com.zhongzheng.modules.exam.domain.ExamBefore;
import com.zhongzheng.modules.exam.vo.*;
import com.zhongzheng.modules.user.vo.CalendarStudyVo;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.zhongzheng.modules.exam.domain.ExamApply;
import com.zhongzheng.modules.exam.mapper.ExamApplyMapper;
import com.zhongzheng.modules.exam.service.IExamApplyService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 考试安排Service业务层处理
 *
 * @author ruoyi
 * @date 2021-12-07
 */
@Service
public class ExamApplyServiceImpl extends ServiceImpl<ExamApplyMapper, ExamApply> implements IExamApplyService {

    @Override
    public ExamApplyVo queryById(Long applyId){
        ExamApplyVo examApplyVo = baseMapper.selectByApply(applyId);
        List<ExamNumberGoodsVo> examNumberGoodsVos = baseMapper.examNumberGoodsVos(applyId);
        List<ExamApplySiteVo> examApplySite = baseMapper.addressExam(applyId,1L);
        for (ExamApplySiteVo examApplySiteVo : examApplySite) {
            List<ExamApplySiteTimeVo> examApplySiteTime = baseMapper.addressTimeExam(examApplySiteVo.getId());
            examApplySiteVo.setExamApplySiteTime(examApplySiteTime);
        }
        List<ExamApplySiteVo> examApplySiteTrain = baseMapper.addressExam(applyId,2L);
        for (ExamApplySiteVo examApplySiteVo : examApplySiteTrain) {
            List<ExamApplySiteTimeVo> examApplySiteTime = baseMapper.addressTimeExam(examApplySiteVo.getId());
            examApplySiteVo.setExamApplySiteTime(examApplySiteTime);
        }
        examApplyVo.setExamNumberGoods(examNumberGoodsVos);
        examApplyVo.setExamApplySite(examApplySite);
        examApplyVo.setExamApplySiteTrain(examApplySiteTrain);
        return examApplyVo;
    }

    @Override
    public List<ExamApplyVo> queryList(ExamApplyQueryBo bo) {
        List<ExamApplyVo> examApplyVos = baseMapper.queryExam(bo);
        for (ExamApplyVo examApplyVo : examApplyVos) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
            calendar.setTimeInMillis(System.currentTimeMillis());
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
            if ((examApplyVo.getApplyEndTime()+86400) < calendar.getTimeInMillis()/1000){
                ExamApply update = new ExamApply();
                update.setApplyId(examApplyVo.getApplyId());
                update.setStatus(2);
                update.setUpdateTime(DateUtils.getNowTime());
                this.updateById(update);
            }
        }

        return baseMapper.queryExam(bo);
    }

    /**
    * 实体类转化成视图对象
    *
    * @param collection 实体类集合
    * @return
    */
    private List<ExamApplyVo> entity2Vo(Collection<ExamApply> collection) {
        List<ExamApplyVo> voList = collection.stream()
                .map(any -> BeanUtil.toBean(any, ExamApplyVo.class))
                .collect(Collectors.toList());
        if (collection instanceof Page) {
            Page<ExamApply> page = (Page<ExamApply>)collection;
            Page<ExamApplyVo> pageVo = new Page<>();
            BeanUtil.copyProperties(page,pageVo);
            pageVo.addAll(voList);
            voList = pageVo;
        }
        return voList;
    }

    @Override
    public Boolean insertByAddBo(ExamApplyAddBo bo) {
        ExamApply add = BeanUtil.toBean(bo, ExamApply.class);
        validEntityBeforeSave(add);
        add.setCode(ServletUtils.getEncoded("KSAP"));
        add.setCreateTime(DateUtils.getNowTime());
        add.setUpdateTime(DateUtils.getNowTime());
        return this.save(add);
    }

    @Override
    public Boolean updateByEditBo(ExamApplyEditBo bo) {
        ExamApply update = BeanUtil.toBean(bo, ExamApply.class);
        if (bo.getStatus() == 1){
            Long contGoodsId = baseMapper.countGoods(bo.getApplyId());
            if (contGoodsId < 1){
                throw new RuntimeException("请先设置适用商品");
            }
            List<ExamApplySiteVo> examApplySite = baseMapper.addressExam(bo.getApplyId(),1L);
            if (CollectionUtils.isEmpty(examApplySite)){
                throw new RuntimeException("请先设置考试地点和时间");
            }
            List<Long> contGoods = baseMapper.countGoodsHold(bo.getApplyId());
            if (CollectionUtils.isNotEmpty(contGoods)){
                String goodsName ="";
                for (Long goodsId : contGoods) {
                    ExamNumberGoodsQueryBo examNumberGoodsQueryBo = new ExamNumberGoodsQueryBo();
                    examNumberGoodsQueryBo.setGoodsId(goodsId);
                    List<ExamNumberGoodsVo> examNumberGoodsVos = this.listGoods(examNumberGoodsQueryBo);
                    if(CollectionUtils.isNotEmpty(examNumberGoodsVos)) {
                        goodsName.concat(examNumberGoodsVos.get(0).getGoodsName() + ",");
                    }
                }
                throw new RuntimeException(goodsName+"已被其他进行中的考试计划使用，请修改，再启用");
            }
        }
        validEntityBeforeSave(update);
        update.setUpdateTime(DateUtils.getNowTime());
        return this.updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(ExamApply entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return this.removeByIds(ids);
    }

    @Override
    public List<ExamNumberGoodsVo> listGoods(ExamNumberGoodsQueryBo bo) {
        return baseMapper.listGoods(bo);
    }

    @Override
    public List<ExamApplySiteVo> getSiteInfo(ExamApplyQueryBo bo) {
        List<ExamApplySiteVo> examApplySite = baseMapper.addressExam(bo.getApplyId(),bo.getAddressStatus());
        for (ExamApplySiteVo examApplySiteVo : examApplySite) {
            List<ExamApplySiteTimeVo> examApplySiteTime = baseMapper.addressTimeExam(examApplySiteVo.getId());
            examApplySiteVo.setExamApplySiteTime(examApplySiteTime);
        }
        return examApplySite;
    }

    @Override
    public ExamApplyVo getGoodsInfo(ExamApplyQueryBo bo) {
        ExamApply db = this.baseMapper.selectById(bo.getApplyId());
        ExamApplyVo examApplyVo = BeanUtil.toBean(db, ExamApplyVo.class);
        List<ExamNumberGoodsVo> examNumberGoodsVos = baseMapper.examNumberGoodsVos(bo.getApplyId());
        //初始化需要得到的数组
        Long[] array = new Long[examNumberGoodsVos.size()];
        //使用for循环得到数组
        for(int i = 0; i < examNumberGoodsVos.size();i++){
            array[i] = examNumberGoodsVos.get(i).getGoodsId();
        }
        examApplyVo.setExamNumberGoods(examNumberGoodsVos);
        examApplyVo.setGoodsId(array);
        return examApplyVo;
    }

    @Override
    public ExamUserApplyVo subscribe(ExamApplyQueryBo bo) {
        Integer countGradePeriod = baseMapper.countGradePeriod(bo);
        if (countGradePeriod < 1){
            throw new IllegalArgumentException("学时审核未通过，不可以报名参加考试");
        }
        Integer countSubscribe = baseMapper.countSubscribe(bo);
        if (countSubscribe > 1){
            throw new IllegalArgumentException("考试已通过，不需要重考");
        }
        Integer countHaveSubscribe = baseMapper.countHaveSubscribe(bo);
        if (countSubscribe > 1){
            throw new IllegalArgumentException("您所报考的专业，已经预约成功，您可在“我的-我的考试预约”中查询详情");
        }
        ExamUserApplyVo examUserApplyVo = baseMapper.selectExamUserApplyVo(bo);
        if (examUserApplyVo == null){
            throw new IllegalArgumentException("商品无考试计划，无需预约考试");
        }
        return examUserApplyVo;
    }

    @Override
    public Long subscribeNext(ExamApplyQueryBo bo) {
        Integer countHaveSubscribeNext = baseMapper.countHaveSubscribeNext(bo);
        if (bo.getApplyStatus() == 1 && countHaveSubscribeNext > 0){
            throw new IllegalArgumentException("系统检索到您不符合【非补考学员】的报名条件，请重新选择！");
        }
        //查询剩余考试次数
        Integer residueSubscribeNext = baseMapper.residueSubscribeNext(bo);
        if (residueSubscribeNext == null || residueSubscribeNext < 1){
            return 3L;
        }
        Integer beforeSubscribeNext = baseMapper.beforeSubscribeNext(bo);
        if (beforeSubscribeNext > 0){
            return 1L;
        }
        return 2L;
    }

    @Override
    public List<ExamUserApplySiteVo> subscribeApplySite(ExamApplyQueryBo bo) {
        List<ExamUserApplySiteVo> examUserApplySiteVos= baseMapper.subscribeApplySite(bo);
        //获得详细地址查看是否满员
        for (ExamUserApplySiteVo examUserApplySiteVo : examUserApplySiteVos) {
            List<ExamUserApplySiteTimeVo> examApplySiteTime = baseMapper.subscribeApplySiteTime(examUserApplySiteVo.getId());
            for (ExamUserApplySiteTimeVo examUserApplySiteTimeVo : examApplySiteTime) {
                List<ExamApplySiteTimeTwoVo> examApplySiteTimeTwoVos = JSONObject.parseArray(examUserApplySiteTimeVo.getSiteTime(), ExamApplySiteTimeTwoVo.class);
                for (ExamApplySiteTimeTwoVo examApplySiteTimeTwoVo : examApplySiteTimeTwoVos) {
                    examApplySiteTimeTwoVo.setRegistration(baseMapper.registration(examUserApplySiteVo.getApplyId(), examUserApplySiteTimeVo.getExamTime()
                            ,examUserApplySiteVo.getSiteAddress(),examApplySiteTimeTwoVo.getStartTime(),examApplySiteTimeTwoVo.getEndTime()));
                    examApplySiteTimeTwoVo.setStatus(baseMapper.userStatus(bo.getUserId(),examUserApplySiteTimeVo.getExamTime(),examApplySiteTimeTwoVo.getStartTime(),examApplySiteTimeTwoVo.getEndTime()));
                }
                examUserApplySiteTimeVo.setExamApplySiteTimeTwoVo(examApplySiteTimeTwoVos);
            }
            examUserApplySiteVo.setExamUserApplySiteTime(examApplySiteTime);
        }
        return examUserApplySiteVos;
    }

    @Override
    public List<ExamUserApplySiteVo> subscribeApplySiteTrain(ExamApplyQueryBo bo) {
        List<ExamUserApplySiteVo> examUserApplySiteVos= baseMapper.subscribeApplySiteTrain(bo);
        //获得详细地址查看是否满员
        for (ExamUserApplySiteVo examUserApplySiteVo : examUserApplySiteVos) {
            List<ExamUserApplySiteTimeVo> examApplySiteTime = baseMapper.subscribeApplySiteTime(examUserApplySiteVo.getId());
            for (ExamUserApplySiteTimeVo examUserApplySiteTimeVo : examApplySiteTime) {
                List<ExamApplySiteTimeTwoVo> examApplySiteTimeTwoVos = JSONObject.parseArray(examUserApplySiteTimeVo.getSiteTime(), ExamApplySiteTimeTwoVo.class);
                for (ExamApplySiteTimeTwoVo examApplySiteTimeTwoVo : examApplySiteTimeTwoVos) {
                    examApplySiteTimeTwoVo.setRegistration(baseMapper.registrationTrain(examUserApplySiteVo.getApplyId(), examUserApplySiteTimeVo.getExamTime()
                            ,examUserApplySiteVo.getSiteAddress(),examApplySiteTimeTwoVo.getStartTime(),examApplySiteTimeTwoVo.getEndTime()));
                    examApplySiteTimeTwoVo.setStatus(baseMapper.userStatusTrain(bo.getUserId(),examUserApplySiteTimeVo.getExamTime(),examApplySiteTimeTwoVo.getStartTime(),examApplySiteTimeTwoVo.getEndTime()));
                }
                examUserApplySiteTimeVo.setExamApplySiteTimeTwoVo(examApplySiteTimeTwoVos);
            }
            examUserApplySiteVo.setExamUserApplySiteTime(examApplySiteTime);
        }
        return examUserApplySiteVos;
    }
}
