package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.bo.OaProgressBo;
import com.ruoyi.oa.domain.bo.SysOaProjectBo;
import com.ruoyi.oa.domain.bo.SysOaTaskBo;
import com.ruoyi.oa.domain.vo.OaProgressVo;
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
import com.ruoyi.oa.domain.vo.SysOaTaskVo;
import com.ruoyi.oa.service.IOaProgressService;
import com.ruoyi.oa.service.ISysOaProjectService;
import com.ruoyi.oa.service.ISysOaTaskService;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.SysOaRemindBo;
import com.ruoyi.oa.domain.vo.SysOaRemindVo;
import com.ruoyi.oa.domain.SysOaRemind;
import com.ruoyi.oa.mapper.SysOaRemindMapper;
import com.ruoyi.oa.service.ISysOaRemindService;
import org.yaml.snakeyaml.constructor.Construct;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 事件提醒Service业务层处理
 *
 * @author huangxing
 * @date 2024-04-02
 */
@RequiredArgsConstructor
@Service
public class SysOaRemindServiceImpl implements ISysOaRemindService {

    private final SysOaRemindMapper baseMapper;

    private final ISysOaTaskService sysOaTaskService;

    private final ISysOaProjectService projectService;

    private final IOaProgressService progressService;

    /**
     * 查询事件提醒
     */
    @Override
    public SysOaRemindVo queryById(Long remindId){
        return baseMapper.selectVoById(remindId);
    }

    /**
     * 查询代办事件列表
     *
     * @param bo
     * @param pageQuery
     * @return
     */
    @Override
    public R<List<SysOaRemindVo>> queryRemindList(SysOaRemindBo bo, PageQuery pageQuery){

        // 任务的逾期情况，项目的逾期情况 目前就这个两个需要提醒
        // 开始
        // 首先查询任务存在不存在逾期问题
        SysOaTaskBo sysOaTaskBo = new SysOaTaskBo();
        sysOaTaskBo.setState(0L);
        sysOaTaskBo.setWorkerId(LoginHelper.getUserId());
        List<SysOaTaskVo> tasks = sysOaTaskService.queryListByRemain(sysOaTaskBo,pageQuery);
        ArrayList<SysOaRemindVo> sysOaRemindVos = new ArrayList<>();
        for (SysOaTaskVo task : tasks) {
            SysOaRemindVo sysOaRemindVo = new SysOaRemindVo();
            sysOaRemindVo.setType("task");
            sysOaRemindVo.setAccessory(task.getAccessory());
            sysOaRemindVo.setContent(task.getContent());
            sysOaRemindVo.setTaskTime(task.getFinishTime());
            sysOaRemindVo.setRemainTime(task.getOverDays());
            sysOaRemindVos.add(sysOaRemindVo);
        }
        // 查询报工
        sysOaTaskBo.setItemStatus(0L);
        tasks = sysOaTaskService.queryListByRemain(sysOaTaskBo, pageQuery);
        for (SysOaTaskVo task : tasks) {
            SysOaRemindVo sysOaRemindVo = new SysOaRemindVo();
            sysOaRemindVo.setType("taskItem");
            sysOaRemindVo.setAccessory(task.getFiles());
            sysOaRemindVo.setContent(task.getContent());
            sysOaRemindVo.setRemainTime(task.getOverDays());
            sysOaRemindVo.setTaskTime(task.getFinishTime());
            sysOaRemindVos.add(sysOaRemindVo);
        }

        // 查询项目情况
        SysOaProjectBo sysOaProjectBo = new SysOaProjectBo();
        sysOaProjectBo.setProjectStatus("0");
        sysOaProjectBo.setCreateBy(LoginHelper.getNickName());
        List<SysOaProjectVo> rows = projectService.queryPageList(sysOaProjectBo, pageQuery).getRows();
        for (SysOaProjectVo row : rows) {
            SysOaRemindVo sysOaRemindVo = new SysOaRemindVo();
            sysOaRemindVo.setType("project");
            sysOaRemindVo.setAccessory(row.getAccessory());
            sysOaRemindVo.setContent(row.getProjectName());
            sysOaRemindVo.setRemainTime(row.getRemainTime());
            sysOaRemindVo.setTaskTime(row.getFinishTime());
            sysOaRemindVos.add(sysOaRemindVo);
        }

        // 查询邻近过期进度
//        OaProgressBo oaProgressBo = new OaProgressBo();
//        oaProgressBo.setType(1L);
//        List<OaProgressVo> rows1 = progressService.queryPageList(oaProgressBo, pageQuery).getRows();
//        for (OaProgressVo row : rows1) {
//            if (row.getRemainTime()!=null && row.getStatus() ==0L && row.getRemainTime()<3L){
//                SysOaRemindVo sysOaRemindVo = new SysOaRemindVo();
//                sysOaRemindVo.setType("progress-project");
//                sysOaRemindVo.setContent(row.getProgressName());
//                sysOaRemindVo.setRemainTime(row.getRemainTime());
//                sysOaRemindVo.setTaskTime(row.getEndTime());
//                sysOaRemindVos.add(sysOaRemindVo);
//            }
//
//        }

        return R.ok(sysOaRemindVos);
    }

    @Override
    public Long queryRemindCount(SysOaRemindBo bo){
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysOaRemind> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTaskStatus()), SysOaRemind::getTaskStatus, bo.getTaskStatus());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null, SysOaRemind::getTaskTime, params.get("beginTime"), params.get("endTime"));
        Long aLong = baseMapper.selectCount(lqw);
        return  aLong;
    }

    /**
     * 查询事件提醒列表
     */
    @Override
    public TableDataInfo<SysOaRemindVo> queryPageList(SysOaRemindBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysOaRemind> lqw = buildQueryWrapper(bo);
        Page<SysOaRemindVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询事件提醒列表
     */
    @Override
    public List<SysOaRemindVo> queryList(SysOaRemindBo bo) {
        LambdaQueryWrapper<SysOaRemind> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<SysOaRemindVo> queryRecentRemindList(SysOaRemindBo bo) {
        LambdaQueryWrapper<SysOaRemind> lqw = Wrappers.lambdaQuery();
        lqw.in(SysOaRemind::getRemindType, Arrays.asList("task", "project"));
        lqw.eq(SysOaRemind::getTaskStatus, "0");
        // 只查当天
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
        String today = sdf.format(new java.util.Date());
        lqw.apply("DATE_FORMAT(create_time, '%Y-%m-%d') = {0}", today);
        lqw.orderByAsc(SysOaRemind::getEndTime);
        if (bo != null && bo.getTargetUserId() != null) {
            lqw.eq(SysOaRemind::getTargetUserId, bo.getTargetUserId());
        }
        List<SysOaRemind> remindList = baseMapper.selectList(lqw);
        List<SysOaRemindVo> voList = new ArrayList<>();
        for (SysOaRemind remind : remindList) {
            SysOaRemindVo vo = new SysOaRemindVo();
            vo.setRemindId(remind.getRemindId());
            vo.setTaskTitle(remind.getTaskTitle());
            vo.setContent(remind.getContent());
            vo.setTaskTime(remind.getTaskTime());
            vo.setTaskStatus(remind.getTaskStatus());
            vo.setAccessory(remind.getAccessory());
            vo.setRemark(remind.getRemark());
            vo.setCreateBy(remind.getCreateBy());
            vo.setCreateTime(remind.getCreateTime());
            vo.setUpdateBy(remind.getUpdateBy());
            vo.setUpdateTime(remind.getUpdateTime());
            vo.setRemindType(remind.getRemindType());
            vo.setDetailId(remind.getDetailId());
            vo.setTargetUserId(remind.getTargetUserId());
            vo.setEndTime(remind.getEndTime());
            // 计算剩余秒数和格式化字符串
            if (remind.getEndTime() != null) {
                long diffMillis = remind.getEndTime().getTime() - System.currentTimeMillis();
                long remainSeconds = diffMillis / 1000;
                vo.setRemainTime(remainSeconds);
                // 格式化为天时分秒
                long days = remainSeconds / (60 * 60 * 24);
                long hours = (remainSeconds / (60 * 60)) % 24;
                long minutes = (remainSeconds / 60) % 60;
                long seconds = remainSeconds % 60;
                StringBuilder sb = new StringBuilder();
                if (days > 0) sb.append(days).append("天");
                if (hours > 0 || days > 0) sb.append(hours).append("小时");
                if (minutes > 0 || hours > 0 || days > 0) sb.append(minutes).append("分");
                sb.append(seconds).append("秒");
                vo.setRemark(sb.toString());
            }
            voList.add(vo);
        }
        return voList;
    }

    private LambdaQueryWrapper<SysOaRemind> buildQueryWrapper(SysOaRemindBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysOaRemind> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTaskTitle()), SysOaRemind::getTaskTitle, bo.getTaskTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getTaskStatus()), SysOaRemind::getTaskStatus, bo.getTaskStatus());
        lqw.between(params.get("beginTime") != null && params.get("endTime") != null, SysOaRemind::getTaskTime, params.get("beginTime"), params.get("endTime"));
        lqw.orderByDesc(SysOaRemind::getCreateTime);
        return lqw;
    }

    /**
     * 新增事件提醒
     */
    @Override
    public Boolean insertByBo(SysOaRemindBo bo) {
        bo.setCreateBy(LoginHelper.getUsername());
        bo.setCreateTime(new Date());
        SysOaRemind add = BeanUtil.toBean(bo, SysOaRemind.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRemindId(add.getRemindId());
        }
        return flag;
    }

    /**
     * 修改事件提醒
     */
    @Override
    public Boolean updateByBo(SysOaRemindBo bo) {
        bo.setUpdateBy(LoginHelper.getUsername());
        bo.setUpdateTime(new Date());
        SysOaRemind update = BeanUtil.toBean(bo, SysOaRemind.class);
        update.setTaskStatus("1");
        update.setTaskTime(new Date());
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SysOaRemind entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除事件提醒
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 定时任务：每天凌晨1点，查task表和project表，把3天内到期且未完成/未完结的任务和项目插入remind表。
     */
    //    @PostConstruct
    //一秒执行一次

//    @Scheduled(fixedRate = 1000)
//    @Scheduled(cron = "0 * * * * ?")
    @Scheduled(cron = "0 0 1 * * ?")
    public void generateRemindJob() {
        // 查询3天内到期的任务
        SysOaTaskBo taskBo = new SysOaTaskBo();
        // 只查未完成任务
        taskBo.setState(0L);
        List<SysOaTaskVo> taskList = sysOaTaskService.queryListPlus(taskBo);
        Date now = new Date();
        for (SysOaTaskVo task : taskList) {
            Date endTime = null;
            if (task.getStatus() != null && task.getStatus() == 1L) {
                // 报工模式，endTime=beginTime+timeGap天
                endTime = com.ruoyi.oa.service.impl.SysOaTaskServiceImpl.addDays(task.getBeginTime(), task.getTimeGap());
            } else {
                // 普通模式，endTime=finishTime
                endTime = task.getFinishTime();
            }
            if (endTime != null) {
                long diff = (endTime.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
                if (diff >= 0 && diff <= 3) {
                    SysOaRemind remind = new SysOaRemind();
                    remind.setRemindType("task");
                    remind.setDetailId(task.getTaskId());
                    remind.setTargetUserId(task.getWorkerId());
                    remind.setTaskTitle(task.getTaskTitle());
                    remind.setContent(task.getContent());
                    remind.setTaskTime(now);
                    remind.setTaskStatus("0");
                    remind.setEndTime(endTime);
                    remind.setCreateBy(task.getCreateBy());
                    remind.setCreateTime(now);
                    remind.setUpdateBy(""); // 无updateBy
                    remind.setAccessory(task.getAccessory());
                    remind.setRemark(task.getRemark());
                    baseMapper.insert(remind);
                }
            }
        }
        // 查询3天内到期的项目
        SysOaProjectBo projectBo = new SysOaProjectBo();
        projectBo.setProjectStatus("0"); // 只查未完结项目
        List<SysOaProjectVo> projectList = projectService.queryList(projectBo);
        for (SysOaProjectVo project : projectList) {
            if (project.getFinishTime() != null) {
                long diff = (project.getFinishTime().getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
                if (diff >= 0 && diff <= 3) {
                    SysOaRemind remind = new SysOaRemind();
                    remind.setRemindType("project");
                    remind.setDetailId(project.getProjectId());
                    remind.setTaskTitle(project.getProjectName());
                    remind.setContent(project.getIntroduction());
                    remind.setTaskTime(null);
                    remind.setTaskStatus("0");
                    remind.setEndTime(project.getFinishTime());
                    remind.setCreateBy(project.getCreateBy());
                    remind.setCreateTime(now);
                    remind.setUpdateBy(""); // 无updateBy
                    remind.setAccessory(project.getAccessory());
                    remind.setRemark(project.getRemark());
                    // 项目提醒targetUserId可为空或负责人id
                    remind.setTargetUserId(null);
                    baseMapper.insert(remind);
                }
            }
        }
    }
}
