package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
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.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.SysOaTaskItemBo;
import com.ruoyi.oa.domain.vo.SysOaTaskItemVo;
import com.ruoyi.oa.domain.SysOaTaskItem;
import com.ruoyi.oa.mapper.SysOaTaskItemMapper;
import com.ruoyi.oa.service.ISysOaTaskItemService;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 报工任务单元Service业务层处理
 *
 * @author hdka
 * @date 2025-03-27
 */
@RequiredArgsConstructor
@Service
public class SysOaTaskItemServiceImpl implements ISysOaTaskItemService {

    private final SysOaTaskItemMapper baseMapper;



    private final ISysOssService ossService;

    /**
     * 查询报工任务单元
     */
    @Override
    public SysOaTaskItemVo queryById(Long itemId){
        System.out.println( baseMapper.selectVoById(itemId));
        return  baseMapper.selectVoById(itemId);
    }

    /**
     * 查询报工任务单元列表
     */
    @Override
    public TableDataInfo<SysOaTaskItemVo> queryPageList(SysOaTaskItemBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysOaTaskItem> lqw = buildQueryWrapper(bo);
        Page<SysOaTaskItemVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询报工任务单元列表
     */
    @Override
    public List<SysOaTaskItemVo> queryList(SysOaTaskItemBo bo) {
        LambdaQueryWrapper<SysOaTaskItem> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SysOaTaskItem> buildQueryWrapper(SysOaTaskItemBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysOaTaskItem> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getTaskId() != null, SysOaTaskItem::getTaskId, bo.getTaskId());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), SysOaTaskItem::getContent, bo.getContent());
        lqw.eq(StringUtils.isNotBlank(bo.getFiles()), SysOaTaskItem::getFiles, bo.getFiles());
        lqw.eq(bo.getSignTime() != null, SysOaTaskItem::getSignTime, bo.getSignTime());
        lqw.eq(bo.getStatus() != null, SysOaTaskItem::getStatus, bo.getStatus());
        lqw.eq(bo.getBeginTime() != null, SysOaTaskItem::getBeginTime, bo.getBeginTime());
        lqw.eq(bo.getEndTime() != null, SysOaTaskItem::getEndTime, bo.getEndTime());
        lqw.eq(bo.getOriginEndTime() != null, SysOaTaskItem::getOriginEndTime, bo.getOriginEndTime());
        lqw.eq(bo.getTempTime() != null, SysOaTaskItem::getTempTime, bo.getTempTime());
        return lqw;
    }

    /**
     * 新增报工任务单元
     */
    @Override
    public Boolean insertByBo(SysOaTaskItemBo bo) {
        SysOaTaskItem add = BeanUtil.toBean(bo, SysOaTaskItem.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setItemId(add.getItemId());
        }
        return flag;
    }

    /**
     * 修改报工任务单元
     */
    @Override
    public Boolean updateByBo(SysOaTaskItemBo bo) {
        SysOaTaskItem update = BeanUtil.toBean(bo, SysOaTaskItem.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

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

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

    /**
     * 提交表单后新建新周期表单
     * @param bo
     * @return
     */
    @Override
    public Boolean reportSubmit(SysOaTaskItemBo bo) {
        bo.setSignTime(new Date());
        bo.setCompletedTime(new Date());
        if (Objects.nonNull(bo.getFiles())) {
            List<String> fileUrls = Arrays.stream(bo.getFiles().split(","))
                    .map(String::valueOf)
                    .collect(Collectors.toList());
            String fileIds = ossService.insertFiles(fileUrls);
            bo.setFiles(fileIds);
        }
        SysOaTaskItem update = BeanUtil.toBean(bo, SysOaTaskItem.class);
        validEntityBeforeSave(update);
        update.setStatus(1L);
        Boolean flag =  baseMapper.updateById(update) > 0;
        SysOaTaskItemBo sysOaTaskItemBo = new SysOaTaskItemBo();
        sysOaTaskItemBo.setTaskId(bo.getTaskId());
        sysOaTaskItemBo.setBeginTime(bo.getEndTime());
        sysOaTaskItemBo.setEndTime(addDays(bo.getEndTime(),bo.getTimeGap()));
        sysOaTaskItemBo.setOriginEndTime(addDays(bo.getEndTime(),bo.getTimeGap()));
        insertByBo(sysOaTaskItemBo);
        return flag;
    }

    /**
     * 推迟申请
     * @param bo
     * @return
     */
    @Override
    public Boolean postpone(SysOaTaskItemBo bo) {
        bo.setEndTime(bo.getTempTime());
        Boolean flag = updateByBo(bo);
        return flag;
    }


    /**
     * 使用 Java 8 的 LocalDateTime 在 beginTime 上加上 timeGap 天并返回新的 Date。
     *
     * @param beginTime 开始时间（Date类型）
     * @param timeGap   需要增加的天数（Long类型）
     * @return 加上 timeGap 天后的日期（Date类型）
     */
    public static Date addDays(Date beginTime, Long timeGap) {
        if (beginTime == null || timeGap == null) {
            return null; // 或根据业务需求进行异常处理
        }

        // 将 Date 转为 LocalDateTime
        LocalDateTime localDateTime = beginTime.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();

        // 加上 timeGap 天
        localDateTime = localDateTime.plusDays(timeGap);

        // 再转换回 Date
        return Date.from(localDateTime
                .atZone(ZoneId.systemDefault())
                .toInstant());
    }
}
