package yangtz.cs.liu.campus.service.impl.schoolDuty;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.core.utils.HolidayDateUtil;
import com.ruoyi.common.core.domain.entity.SchoolTeacher;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.mapper.SysPostMapper;
import com.ruoyi.system.mapper.SysUserMapper;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yangtz.cs.liu.campus.domain.schoolDuty.SchoolDuty;
import yangtz.cs.liu.campus.domain.schoolDuty.SchoolDutyDetails;
import yangtz.cs.liu.campus.domain.schoolexam.SchoolExamDetail;
import yangtz.cs.liu.campus.mapper.schoolDuty.SchoolDutyDetailsMapper;
import yangtz.cs.liu.campus.mapper.schoolDuty.SchoolDutyMapper;
import yangtz.cs.liu.campus.mapper.teacher.SchoolTeacherMapper;
import yangtz.cs.liu.campus.service.schoolDuty.ISchoolDutyDetailsService;
import yangtz.cs.liu.campus.vo.schoolDuty.DutyHoildayVo;
import yangtz.cs.liu.campus.vo.schoolDuty.DutyVacationVo;
import yangtz.cs.liu.campus.vo.schoolDuty.HoildayDetailsVo;
import yangtz.cs.liu.campus.vo.schoolDuty.VacationDetailsVo;

import static com.ruoyi.common.utils.DateUtils.dateToWeek;
import static com.ruoyi.common.utils.DateUtils.getDutyList;
import static com.ruoyi.common.utils.StringUtils.isNull;
import static yangtz.cs.liu.campus.constant.DutyType.*;
import static yangtz.cs.liu.campus.constant.DutyType.DORMITORY;

/**
 * 值班管理明细Service业务层处理
 */
@Service
public class SchoolDutyDetailsServiceImpl extends ServiceImpl<SchoolDutyDetailsMapper, SchoolDutyDetails> implements ISchoolDutyDetailsService {
    @Autowired
    private SchoolDutyDetailsMapper schoolDutyDetailsMapper;

    @Autowired
    private SchoolDutyMapper schoolDutyMapper;

    @Autowired
    private SysPostMapper postMapper;

    @Autowired
    private SchoolTeacherMapper teacherMapper;


    /**
     * 查询值班管理明细列表
     *
     * @param schoolDutyDetails 值班管理明细
     * @return 值班管理明细
     */
    @Override
    public List<SchoolDutyDetails> selectSchoolDutyDetailsList(SchoolDutyDetails schoolDutyDetails) {
        return schoolDutyDetailsMapper.selectSchoolDutyDetailsList(schoolDutyDetails);
    }

    /**
     * 检查导入时的数据
     */
    @Override
    public void checkData(List<SchoolDutyDetails> list, Long dutyId) {
        //是否为空
        if (isNull(list) || list.size() == 0) {
            throw new ServiceException("导入数据不能为空");
        }
        //记录日志数据
        int failureNum = 0;
        StringBuilder failureMsg = new StringBuilder();

        SchoolDuty schoolDuty = schoolDutyMapper.selectById(dutyId);
        Date startDate = schoolDuty.getStartDate();
        Date endDate = schoolDuty.getEndDate();

        for (SchoolDutyDetails schoolDutyDetails : list) {
            schoolDutyDetails.setDutyId(dutyId);
            if (StringUtils.isNotEmpty(schoolDutyDetails.getDutyDeType())) {
                //宿舍值班和门卫值班不需要日期
                if (LEADERNUM.equals(schoolDutyDetails.getDutyDeType()) || PERSONNUM.equals(schoolDutyDetails.getDutyDeType())
                        || XZNUM.equals(schoolDutyDetails.getDutyDeType()) || CNUM.equals(schoolDutyDetails.getDutyDeType())) {
                    if (schoolDutyDetails.getDutyDeDate() == null || isNull(schoolDutyDetails.getDutyDeDate())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、值班日期不能为空，请您重新输入！");
                    } else if (StringUtils.isEmpty(schoolDutyDetails.getDutyDeUsername())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、值班人姓名不能为空，请您重新输入！");
                    } else if (StringUtils.isEmpty(schoolDutyDetails.getDutyDePhone())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、值班人手机不能为空，请您重新输入！");
                    } else if (StringUtils.isEmpty(schoolDutyDetails.getDutyDeType())) {
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、类型不能为空，请您重新输入！");
                    } else {
                        //1.日期格式是否合法
                        try {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                            sdf.format(schoolDutyDetails.getDutyDeDate());
                        } catch (Exception e) {
                            throw new ServiceException("格式不对，请检查日期格式");
                        }
                        //2.日期是否在正确范围内
                        if (schoolDutyDetails.getDutyDeDate().before(startDate) || schoolDutyDetails.getDutyDeDate().after(endDate)) {
                            failureNum++;
                            failureMsg.append("<br/>" + failureNum + "、日期不在本次值班范围内，请您重新检查后输入！");
                        }

                        //3.除门卫值班和宿舍值班外，其余值班人员和值班人手机号，是否存在系统中
                        SchoolTeacher teacher = teacherMapper.getTeacherByPhone(schoolDutyDetails.getDutyDePhone());
                        if (StringUtils.isNotNull(teacher)) {
                            //教师名和值班人员姓名是否一致
                            if (schoolDutyDetails.getDutyDeUsername().equals(teacher.getTeacherName())) {
                                schoolDutyDetails.setDutyDeUser(teacher.getId());
                            } else {
                                failureNum++;
                                failureMsg.append("<br/>" + failureNum + "、值班人员姓名为" + schoolDutyDetails.getDutyDeUsername() + ",值班人员手机为" + schoolDutyDetails.getDutyDePhone() + "的教职工不存在，请检查");
                            }
                        } else {
                            failureNum++;
                            failureMsg.append("<br/>" + failureNum + "、值班人员姓名为" + schoolDutyDetails.getDutyDeUsername() + ",值班人员手机为" + schoolDutyDetails.getDutyDePhone() + "的教职工不存在，请检查");
                        }

                    }
                } /*else if (GUARDNUM.equals(schoolDutyDetails.getDutyDeType()) || DORMITORYNUM.equals(schoolDutyDetails.getDutyDeType())) {
                    //如果是宿舍值班，只填写电话即可。
                }*/

            } else {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、类型不能为空，请您重新输入！");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共" + failureNum + "条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
    }


    /**
     * 数据导入
     */
    @Override
    @Transactional
    public String importDutyDetails(List<SchoolDutyDetails> list, Long dutyId) {
        //记录日志数据
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        //删除主表对应子表记录
        LambdaQueryWrapper<SchoolDutyDetails> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolDutyDetails::getDutyId, dutyId);
        schoolDutyDetailsMapper.delete(lqw);
        for (SchoolDutyDetails schoolDutyDetails : list) {
            try {
                schoolDutyDetails.setDutyId(dutyId);
                schoolDutyDetailsMapper.insert(schoolDutyDetails);
                successNum++;
            } catch (Exception e) {
                failureNum++;
                String msg = "<br>值班人" + schoolDutyDetails.getDutyDeUser() + "导入失败";
                failureMsg.append(msg + e.getMessage());
                throw new ServiceException("导入失败");
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共" + failureNum + "条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + "条");
        }
        return successMsg.toString();
    }


    /**
     * 制作下载模板的一个集合
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    @Override
    public List<SchoolDutyDetails> getDuty(Date startDate, Date endDate) throws ParseException {
        List<String> days = getDutyList(startDate, endDate);
        List<SchoolDutyDetails> list = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (String day : days) {
            SchoolDutyDetails schoolDutyDetails = new SchoolDutyDetails();
            String week = dateToWeek(day);
            schoolDutyDetails.setDutyDeWeek(week);
            schoolDutyDetails.setDutyDeDate(sdf.parse(day));
            schoolDutyDetails.setDutyDeType(XZNUM);
            list.add(schoolDutyDetails);
        }
        for (String day : days) {
            SchoolDutyDetails schoolDutyDetails = new SchoolDutyDetails();
            String week = dateToWeek(day);
            schoolDutyDetails.setDutyDeWeek(week);
            schoolDutyDetails.setDutyDeDate(sdf.parse(day));
            schoolDutyDetails.setDutyDeType(CNUM);
            list.add(schoolDutyDetails);
        }
        SchoolDutyDetails guard = new SchoolDutyDetails();
        guard.setDutyDeType(GUARDNUM);
        list.add(guard);

        SchoolDutyDetails dormitory = new SchoolDutyDetails();
        dormitory.setDutyDeType(DORMITORYNUM);
        list.add(dormitory);
        return list;
    }

    @Override
    public List<SchoolDutyDetails> getHoildayDuty(Date startDate, Date endDate) throws ParseException {
        List<String> days = getDutyList(startDate, endDate);
        List<SchoolDutyDetails> list = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (String day : days) {
            SchoolDutyDetails schoolDutyDetails = new SchoolDutyDetails();
            String week = dateToWeek(day);
            schoolDutyDetails.setDutyDeWeek(week);
            schoolDutyDetails.setDutyDeDate(sdf.parse(day));
            schoolDutyDetails.setDutyDeType(LEADERNUM);
            list.add(schoolDutyDetails);
        }
        for (String day : days) {
            SchoolDutyDetails schoolDutyDetails = new SchoolDutyDetails();
            String week = dateToWeek(day);
            schoolDutyDetails.setDutyDeWeek(week);
            schoolDutyDetails.setDutyDeDate(sdf.parse(day));
            schoolDutyDetails.setDutyDeType(PERSONNUM);
            list.add(schoolDutyDetails);
        }
        return list;

    }

    //节日值班表查看
    @Override
    public DutyHoildayVo selectHoliday(Long id) {
        //返回的v结果
        DutyHoildayVo vo = new DutyHoildayVo();
        SchoolDuty sd = schoolDutyMapper.selectById(id);
        BeanUtils.copyProperties(sd, vo);
        vo.setUnit(SCHOOL);

        LambdaQueryWrapper<SchoolDutyDetails> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolDutyDetails::getDutyId, id);
        List<SchoolDutyDetails> dutyDetails = schoolDutyDetailsMapper.selectList(lqw);
        if (isNull(dutyDetails) || dutyDetails.size() == 0) {
            vo.setList(null);
        } else {
            //子表不为空时
            List<HoildayDetailsVo> list = makeHoliday(dutyDetails);
            for (HoildayDetailsVo detailsVo : list) {
                detailsVo.setHolidayName(vo.getHolidayName());
            }
            vo.setList(list);
        }
        return vo;
    }

    @Override
    public DutyVacationVo selectVacation(Long id) {
        //返回的v结果
        DutyVacationVo vo = new DutyVacationVo();
        SchoolDuty sd = schoolDutyMapper.selectById(id);
        BeanUtils.copyProperties(sd, vo);

        LambdaQueryWrapper<SchoolDutyDetails> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SchoolDutyDetails::getDutyId, id).orderByAsc(SchoolDutyDetails::getDutyDeDate);
        List<SchoolDutyDetails> dutyDetails = schoolDutyDetailsMapper.selectList(lqw);
        if (isNull(dutyDetails) || dutyDetails.size() == 0) {
            vo.setList(null);
        } else {
            //子表不为空时
            List<VacationDetailsVo> list = makeVacation(dutyDetails);
            vo.setList(list);
        }
        return vo;
    }

    //处理节日值班表表格内容
    public List<HoildayDetailsVo> makeHoliday(List<SchoolDutyDetails> dutyDetails) {
        //返回结果
        List<HoildayDetailsVo> list = new ArrayList<>();

        //过滤出每天的值班领导
        List<SchoolDutyDetails> leaders = new ArrayList<>();
        for (SchoolDutyDetails d : dutyDetails) {
            if (d.getDutyDeType().equals(LEADERNUM)) {
                leaders.add(d);
            }
        }
        //处理最终对象结果显示
        for (SchoolDutyDetails leader : leaders) {
            HoildayDetailsVo vo = new HoildayDetailsVo();
            //设置值班日期leader.getDutyDeDate()
            String dateAndWeek = HolidayDateUtil.format1.format(leader.getDutyDeDate()) + "(" + leader.getDutyDeWeek() + ")";
            vo.setDateAndWeek(dateAndWeek);
            //设置值班领导姓名
            vo.setLeader(leader.getDutyDeUsername());
            //获取值班领导岗位
            List<SysPost> postList = postMapper.selectPostsByUserName(leader.getDutyDeUsername());
            String postName = "";
            if (postList.size() > 0) {
                postName = postList.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
            }
            //设置值班领导职务
            vo.setPostName(postName);
            //手机
            vo.setDutyDePhone(leader.getDutyDePhone());
            //电话
            vo.setDutyDeTel(leader.getDutyDeTel());

            String personAndPhone = "";

            //获取本天的值班人员
            for (SchoolDutyDetails dd : dutyDetails) {
                if (leader.getDutyDeDate().equals(dd.getDutyDeDate()) && dd.getDutyDeType().equals(PERSONNUM)) {
                    personAndPhone += dd.getDutyDeUsername() + ":" + dd.getDutyDePhone() + " ";
                }
            }
            //设置值班人员、手机
            vo.setPersonAndPhone(personAndPhone);
            list.add(vo);
        }
        return list;
    }

    //处理寒暑假值班表数据
    public List<VacationDetailsVo> makeVacation(List<SchoolDutyDetails> dutyDetails) {
        //返回结果
        List<VacationDetailsVo> list = new ArrayList<>();

        List<Date> dates = dutyDetails.stream().map(SchoolDutyDetails::getDutyDeDate).collect(Collectors.toList());
        //去重
        HashSet h = new HashSet(dates);
        dates.clear();
        dates.addAll(h);
        //去空
        List<Date> dateList = dates.stream().filter(Objects::nonNull).collect(Collectors.toList());

        dateList.sort((t1, t2) -> t1.compareTo(t2));

        //处理最终对象结果显示
        for (Date d : dateList) {
            VacationDetailsVo vo = new VacationDetailsVo();
            //设置值班日期,格式化为xxxx年xx月xx日
            String dutyDeDate = DateUtils.formatDate(d);
            dutyDeDate = dutyDeDate.substring(5, dutyDeDate.length());
            vo.setDutyDeDate(dutyDeDate);
            //设置星期
            //将当前日期处理成参数所需字符串yyyy-mm-dd
            String dd = HolidayDateUtil.format1.format(d);
            vo.setDutyDeWeek(DateUtils.dateToWeek(dd));
            //获取当天的行政值班，办公室值班，当前假期门卫宿舍值班
            for (SchoolDutyDetails sdd : dutyDetails) {
                //设置行政值班人员
                if (sdd.getDutyDeType().equals(XZNUM) && (sdd.getDutyDeDate().compareTo(d) == 0)) {
                    vo.setAdminPerson(sdd.getDutyDeUsername());
                    vo.setAdminTel(sdd.getDutyDeTel());
                    vo.setAdminPhone(sdd.getDutyDePhone());
                }
                //设置办公室值班
                if (sdd.getDutyDeType().equals(CNUM) && (sdd.getDutyDeDate().compareTo(d) == 0)) {
                    vo.setOfficerPerson(sdd.getDutyDeUsername());
                    vo.setOfficerTel(sdd.getDutyDeTel());
                    vo.setOfficerPhone(sdd.getDutyDePhone());
                }
                //设置门卫
                if (sdd.getDutyDeType().equals(GUARDNUM)) {
                    vo.setGuardPerson(sdd.getDutyDeUsername());
                    vo.setGuardTel(sdd.getDutyDeTel());
                    vo.setGuardPhone(sdd.getDutyDePhone());
                }
                if (sdd.getDutyDeType().equals(DORMITORYNUM)) {
                    vo.setDormPerson(sdd.getDutyDeUsername());
                    vo.setDormPhone(sdd.getDutyDePhone());
                }
            }
            list.add(vo);
        }
        return list;
    }
}
