package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
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.ProjectAttendance;
import com.ruoyi.oa.domain.vo.ProjectAttendanceVo;
import com.ruoyi.oa.domain.vo.SysOaProjectVo;
import com.ruoyi.oa.mapper.SysOaAttendanceMapper;
import com.ruoyi.oa.mapper.SysOaProjectMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import liquibase.pro.packaged.A;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaAttendanceRecordBo;
import com.ruoyi.oa.domain.vo.OaAttendanceRecordVo;
import com.ruoyi.oa.domain.OaAttendanceRecord;
import com.ruoyi.oa.mapper.OaAttendanceRecordMapper;
import com.ruoyi.oa.service.IOaAttendanceRecordService;

import java.util.*;

/**
 * 计算记录Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-15
 */
@RequiredArgsConstructor
@Service
public class OaAttendanceRecordServiceImpl implements IOaAttendanceRecordService {

    private final OaAttendanceRecordMapper baseMapper;

    @Autowired
    private SysOaProjectMapper projectMapper;

    @Autowired
    private SysOaAttendanceMapper attendanceMapper;

    @Autowired
    private SysUserMapper userMapper;

    /**
     * 查询计算记录
     */
    @Override
    public OaAttendanceRecordVo queryById(Long recordId){
        return baseMapper.selectVoByIdPlus(recordId);
    }

    /**
     * 查询计算记录列表
     */
    @Override
    public TableDataInfo<OaAttendanceRecordVo> queryPageList(OaAttendanceRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OaAttendanceRecord> lqw = buildQueryWrapper(bo);
        Page<OaAttendanceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<OaAttendanceRecord> buildQueryWrapper(OaAttendanceRecordBo bo) {
        LambdaQueryWrapper<OaAttendanceRecord> lqw = Wrappers.lambdaQuery();
        if (bo.getRelationMonth() != null) {
            lqw.apply(

                    "YEAR(relation_month) = YEAR({0}) AND  MONTH(relation_month) = MONTH({1})",
                    bo.getRelationMonth(), bo.getRelationMonth());
            if (bo.getCalcTime() != null) {
                // 2a) 如果前端传了 genTime，就按那天精准过滤
                lqw.apply("DATE(calc_time) = {0}", bo.getCalcTime());
            } else {
                // 2b) 如果没传 genTime，就只拿该月最新一次的记录
                lqw.apply(
                        "calc_time = (" +
                                "SELECT MAX(calc_time) FROM oa_attendance_record " +
                                "WHERE YEAR(relation_month)=YEAR({0}) AND MONTH(relation_month)=MONTH({1})" +
                                ")",
                        bo.getRelationMonth(), bo.getRelationMonth()
                );
            }

        }
        return lqw;
    }

    /**
     * 查询计算记录列表
     */
    @Override
    public List<OaAttendanceRecordVo> queryList(OaAttendanceRecordBo bo) {
        LambdaQueryWrapper<OaAttendanceRecord> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }



    /**
     * 新增计算记录
     */
    @Override
    public Boolean insertByBo(OaAttendanceRecordBo bo) {
        OaAttendanceRecord add = BeanUtil.toBean(bo, OaAttendanceRecord.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRecordId(add.getRecordId());
        }
        return flag;
    }

    /**
     * 修改计算记录
     */
    @Override
    public Boolean updateByBo(OaAttendanceRecordBo bo) {
        OaAttendanceRecord update = BeanUtil.toBean(bo, OaAttendanceRecord.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

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

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

    @Override
    public List<String> listGenDate(String date) {

        return baseMapper.listGenDate(date);
    }

    /**
     *
     * @param userIds
     * @param calcTime “yyyy-MM-dd”
     * @param relationMonth “yyyy-MM-dd”
     * @return
     */
    @Override
    public List<ProjectAttendanceVo> getAttendance(List<Long> userIds, String calcTime,String relationMonth) {
        // 首先查询合并好的projectIds 然后在查到的这个Long类型的列表后加入 0 1, 分别代表0出差1请假
        List<String> projectIdsString = baseMapper.selectProjectIds(userIds,calcTime,relationMonth);
        List<Long> projectIds = parseProjectIds(projectIdsString);
        projectIds.add(0L);
        projectIds.add(1L);
        // 然后拿着每一个userId和projectId去签到表查询出勤 在传入的计算时间之前
        List<ProjectAttendanceVo> attendanceVoList = new ArrayList<>();
        for (Long userId : userIds) {

            List<ProjectAttendance> projects = new ArrayList<>();
            for (Long projectId : projectIds) {
                // 老规矩如果calcTime和relationMonth不在一个月则查询relationMonth全月的 如果在一个月则查询从一号到calcTime的出勤次数 及day_length>0或hour>0或project_id=0
                Long workDays = attendanceMapper.getWorkDaysByUserIdAndProjectId(userId,projectId,calcTime,relationMonth);

                ProjectAttendance projectAttendance = new ProjectAttendance();
                projectAttendance.setProjectId(projectId);
                projectAttendance.setWorkDays(workDays);
                if (projectId.equals(0L)) {
                    projectAttendance.setProjectName("出差");
                }else if (projectId.equals(1L)) {
                    projectAttendance.setProjectName("请假");
                }else{
                    SysOaProjectVo sysOaProjectVo = projectMapper.selectVoById(projectId);
                    projectAttendance.setProjectName(sysOaProjectVo.getProjectName());
                }

                projects.add(projectAttendance);
            }
            ProjectAttendanceVo projectAttendanceVo = new ProjectAttendanceVo();
            projectAttendanceVo.setProjects(projects);
            projectAttendanceVo.setRelationMonth(relationMonth);
            projectAttendanceVo.setNickName(userMapper.selectVoById(userId).getNickName());
            attendanceVoList.add(projectAttendanceVo);
        }
        //
        return attendanceVoList;
    }



    public static List<Long> parseProjectIds(List<String> projectIdsString) {
        // 使用 HashSet 来确保去重
        Set<Long> projectIdSet = new HashSet<>();
        // 遍历输入的每个字符串
        for (String ids : projectIdsString) {
            // 按照逗号分割每个字符串
            String[] idsArray = ids.split(",");

            // 将每个分割出来的 ID 转换为 Long 类型并添加到 Set 中
            for (String id : idsArray) {
                // 去除空格并检查是否为空字符串
                id = id.trim();  // 去除两端的空格
                if (!id.isEmpty()) {  // 如果不为空
                    projectIdSet.add(Long.parseLong(id)); // 转换并添加到 Set 中
                }
            }
        }

        // 返回 List，Set 会自动去重
        return new ArrayList<>(projectIdSet);
    }
}
