package com.fjhx.oa.service.schedule.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.oa.entity.schedule.dto.ScheduleInfoDto;
import com.fjhx.oa.entity.schedule.dto.ScheduleInfoSelectDto;
import com.fjhx.oa.entity.schedule.po.ScheduleDetails;
import com.fjhx.oa.entity.schedule.po.ScheduleInfo;
import com.fjhx.oa.entity.schedule.vo.ScheduleDetailsVo;
import com.fjhx.oa.entity.schedule.vo.ScheduleInfoVo;
import com.fjhx.oa.mapper.schedule.ScheduleInfoMapper;
import com.fjhx.oa.service.schedule.ScheduleDetailsService;
import com.fjhx.oa.service.schedule.ScheduleInfoService;
import com.fjhx.oa.utils.Notice;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.wrapper.IWrapper;
import com.ruoyi.system.utils.UserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 日程信息表 服务实现类
 * </p>
 *
 * @author
 * @since 2023-04-03
 */
@DS(SourceConstant.OA)
@Service
public class ScheduleInfoServiceImpl extends ServiceImpl<ScheduleInfoMapper, ScheduleInfo> implements ScheduleInfoService {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Autowired
    ScheduleDetailsService scheduleDetailsService;

    @Override
    public Page<ScheduleInfoVo> getPage(ScheduleInfoSelectDto dto) {
        IWrapper<ScheduleInfo> wrapper = getWrapper();
        wrapper.orderByAsc("si", ScheduleInfo::getCreateTime);
        if (ObjectUtil.isNotEmpty(dto.getDate())) {
            wrapper.apply("date_format(si.start_date,'%Y-%m') = date_format('" + sdf.format(dto.getDate()) + "','%Y-%m')");
        }
        wrapper.eq("si", ScheduleInfoVo::getCreateUser, dto.getCreateUser());
        wrapper.eq("sd", ScheduleInfoVo::getParticipantId, dto.getParticipantId());
        if (ObjectUtil.isNotEmpty(dto.getStartDate())) {
//            wrapper.apply("date_format(si.start_date,'%Y-%m-%d') BETWEEN date_format('" + sdf.format(dto.getStartDate()) + "','%Y-%m-%d') AND date_format('" + sdf.format(dto.getEndDate()) + "','%Y-%m-%d')");
            wrapper.and(q -> q.apply("date_format( '" + sdf.format(dto.getStartDate()) + "', '%y-%m-%d' ) BETWEEN date_format( si.start_date, '%y-%m-%d' ) AND date_format( si.end_date, '%y-%m-%d' )").or()
                    .apply("date_format( '" + sdf.format(dto.getStartDate()) + "', '%y-%m-%d' ) BETWEEN date_format( si.start_date, '%y-%m-%d' ) AND date_format( si.end_date, '%y-%m-%d' )"));
        }
        wrapper.groupBy("si.id");
        Page<ScheduleInfoVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
        return page;
    }

    @Override
    public ScheduleInfoVo detail(Long id) {
        ScheduleInfo ScheduleInfo = this.getById(id);
        ScheduleInfoVo result = BeanUtil.toBean(ScheduleInfo, ScheduleInfoVo.class);
        List<ScheduleDetails> scheduleDetailsList = scheduleDetailsService.list(q -> q.eq(ScheduleDetails::getScheduleInfoId, result.getId()));
        List<ScheduleDetailsVo> scheduleDetailsVos = BeanUtil.copyToList(scheduleDetailsList, ScheduleDetailsVo.class);
        if (ObjectUtil.isNotEmpty(scheduleDetailsVos)) {
            //赋值用户信息
            UserUtil.assignmentNickName(scheduleDetailsVos, ScheduleDetails::getParticipantId, ScheduleDetailsVo::setParticipantName);
            result.setParticipantList(scheduleDetailsVos);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ScheduleInfoDto scheduleInfoDto) {
        this.save(scheduleInfoDto);
        //添加日程明细
        List<ScheduleDetails> participantList = scheduleInfoDto.getParticipantList();
        if (ObjectUtil.isNotEmpty(participantList)) {
            for (ScheduleDetails scheduleDetails : participantList) {
                scheduleDetails.setScheduleInfoId(scheduleInfoDto.getId());
            }
            scheduleDetailsService.saveBatch(participantList);
        }
        //判断是否是今天的日程是加入消息通知队列
        Notice.updateNoticeList(scheduleInfoDto);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ScheduleInfoDto scheduleInfoDto) {
        this.updateById(scheduleInfoDto);
        //更新明细信息
        List<ScheduleDetails> participantList = scheduleInfoDto.getParticipantList();
        //先处理删除掉的参与人
        List<Long> scheduleDetailsIds = participantList.stream().map(ScheduleDetails::getParticipantId).collect(Collectors.toList());
        scheduleDetailsService.remove(q -> q.eq(ScheduleDetails::getScheduleInfoId, scheduleInfoDto.getId())
                .notIn(ObjectUtil.isNotEmpty(scheduleDetailsIds), ScheduleDetails::getParticipantId, scheduleDetailsIds));
        if (ObjectUtil.isNotEmpty(participantList)) {
            for (ScheduleDetails scheduleDetails : participantList) {
                scheduleDetails.setScheduleInfoId(scheduleInfoDto.getId());
            }
            scheduleDetailsService.saveOrUpdateBatch(participantList);
        }
        //判断是否是今天的日程是加入消息通知队列
        Notice.updateNoticeList(scheduleInfoDto);
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
        //删除日程对应的通知计划
        Notice.deleteNoticeList(id);
    }

    @Override
    public List<ScheduleInfoVo> mySchedule(ScheduleInfoSelectDto dto) {
        IWrapper<ScheduleInfo> wrapper = getWrapper();
        wrapper.eq(ScheduleInfoVo::getParticipantId, SecurityUtils.getUserId());
        wrapper.eq("(date( si.start_date ) = curdate())", 1);
        if (ObjectUtil.isNotEmpty(dto.getKeyword())) {
            wrapper.and(wrapper1 ->
                    wrapper1.like(
                                    ScheduleInfo::getTitle, dto.getKeyword())
                            .or()
                            .like(ScheduleInfo::getPlace, dto.getKeyword())
                            .or()
                            .like(ScheduleInfo::getRemark, dto.getKeyword())
            );
        }
        return baseMapper.mySchedule(wrapper);
    }

}
