package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
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 com.ruoyi.system.mapper.SysUserMapper;
import com.xxl.job.core.util.DateUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
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;
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 查询事件提醒
     */
    @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) {
        // 过滤：仅当天创建、到期在未来0~3天、未处理的任务/项目提醒
        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);
        // 到期在未来0~3天（含当天、含第3天）
        lqw.apply("DATEDIFF(end_time, {0}) BETWEEN 0 AND 3", today);

        if (bo != null && bo.getTargetUserId() != null) {
            lqw.eq(SysOaRemind::getTargetUserId, bo.getTargetUserId());
        }
        // 为了后续按 (type, detailId) 去重保留最新，先按创建时间倒序
        lqw.orderByDesc(SysOaRemind::getCreateTime);

        List<SysOaRemind> remindList = baseMapper.selectList(lqw);

        // 按 (remind_type, detail_id) 去重：由于已按 create_time 倒序，只保留第一次出现（最新）
        Map<String, SysOaRemindVo> latestMap = new LinkedHashMap<>();
        Date now = new Date(); // 添加当前时间变量
        for (SysOaRemind remind : remindList) {
            String key = (remind.getRemindType() == null ? "" : remind.getRemindType()) + "_" + (remind.getDetailId() == null ? "" : remind.getDetailId());
            if (latestMap.containsKey(key)) {
                continue;
            }
            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());
            vo.setType(remind.getRemindType()); // 兼容旧字段

            // 计算剩余时间或逾期时间
            if (remind.getEndTime() != null) {
                long diffMillis = remind.getEndTime().getTime() - now.getTime();
                long diffSeconds = diffMillis / 1000;
                vo.setRemainTime(diffSeconds);

                // 格式化时间字符串
                long absDays = Math.abs(diffSeconds) / (60 * 60 * 24);
                long absHours = (Math.abs(diffSeconds) / (60 * 60)) % 24;
                long absMinutes = (Math.abs(diffSeconds) / 60) % 60;

                StringBuilder sb = new StringBuilder();
                if (diffSeconds < 0) {
                    // 已逾期
                    sb.append("逾期 ");
                    if (absDays > 0) sb.append(absDays).append("天");
                    if (absHours > 0) sb.append(absHours).append("小时");
                    if (absMinutes > 0) sb.append(absMinutes).append("分钟");
                } else {
                    // 未到期
                    sb.append("剩余 ");
                    if (absDays > 0) sb.append(absDays).append("天");
                    if (absHours > 0) sb.append(absHours).append("小时");
                    if (absMinutes > 0) sb.append(absMinutes).append("分钟");
                }
                vo.setRemainTimeStr(sb.toString());
            }
            latestMap.put(key, vo);
        }
        return new ArrayList<>(latestMap.values());
    }

    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(null);
                    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 负责人id需要模糊查询sys_user表
                    LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    sysUserLambdaQueryWrapper.like(SysUser::getNickName, project.getFunctionary());
                    SysUser sysUser = sysUserMapper.selectOne(sysUserLambdaQueryWrapper);
                    if (sysUser != null ) {
                        // 如果找到用户，设置第一个用户的ID（或者根据实际需求选择合适的用户）
                        remind.setTargetUserId(sysUser.getUserId());
                    } else {
                        // 如果没找到匹配的用户，可以设置为null或者其他默认值
                        remind.setTargetUserId(null);
                    }
                    baseMapper.insert(remind);
                }
            }
        }
//        把三天前的提醒任务状态改为已处理
        LambdaUpdateWrapper<SysOaRemind> sysOaRemindLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        sysOaRemindLambdaUpdateWrapper.lt(SysOaRemind::getCreateTime, DateUtil.addDays(new Date(), -3));
        sysOaRemindLambdaUpdateWrapper.set(SysOaRemind::getTaskStatus, "1");
        baseMapper.update(null, sysOaRemindLambdaUpdateWrapper);
    }
}
