package com.ruoyi.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.common.core.domain.R;
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.pay.domain.*;
import com.ruoyi.pay.domain.bo.PayAttendanceBo;
import com.ruoyi.pay.domain.bo.PayBaohuoWorktimeBo;
import com.ruoyi.pay.domain.bo.PayWorkTimeBo;
import com.ruoyi.pay.domain.vo.*;
import com.ruoyi.pay.mapper.PayAttendanceMapper;
import com.ruoyi.pay.mapper.PayDwHoursContrastMapper;
import com.ruoyi.pay.service.IPayAttendanceService;
import com.ruoyi.pay.service.IPayBaohuoWorktimeService;
import com.ruoyi.pay.service.IPayWorkTimeService;
import com.ruoyi.pay.util.DateCompareUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.pay.domain.bo.PayDayWorkHoursBo;
import com.ruoyi.pay.mapper.PayDayWorkHoursMapper;
import com.ruoyi.pay.service.IPayDayWorkHoursService;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 日工工时Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-12
 */
@RequiredArgsConstructor
@Service
public class PayDayWorkHoursServiceImpl implements IPayDayWorkHoursService {

    private final PayDayWorkHoursMapper baseMapper;
    private final IPayAttendanceService attendanceService;
    private final IPayWorkTimeService workTimeService;
    private final IPayBaohuoWorktimeService baohuoWorktimeService;
    private final PayDwHoursContrastMapper dwHoursContrastMapper;

    /**
     * 查询日工工时
     */
    @Override
    public PayDayWorkHoursVo queryById(Long id){
        return baseMapper.selectDetailById(id);
    }

    /**
     * 查询日工工时列表
     */
    @Override
    public TableDataInfo<PayDayWorkHoursVo> queryPageList(PayDayWorkHoursBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PayDayWorkHours> lqw = buildQueryWrapper(bo);
        Page<PayDayWorkHoursVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }
    /**
     * 查询日工工时列表
     */
    @Override
    public TableDataInfo<PayDayWorkHoursVo> queryPageList2(PayDayWorkHoursBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PayDayWorkHours> lqw = buildQueryWrapper(bo);
        Page<PayDayWorkHoursVo> result = baseMapper.selectVoPage2(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询日工工时列表
     */
    @Override
    public List<PayDayWorkHoursVo> queryList(PayDayWorkHoursBo bo) {
        LambdaQueryWrapper<PayDayWorkHours> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PayDayWorkHours> buildQueryWrapper(PayDayWorkHoursBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PayDayWorkHours> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getTenantId() != null, PayDayWorkHours::getTenantId, bo.getTenantId());
        lqw.eq(bo.getDeptId() != null, PayDayWorkHours::getDeptId, bo.getDeptId());
        lqw.like(StringUtils.isNotBlank(bo.getDeptName()), PayDayWorkHours::getDeptName, bo.getDeptName());
        lqw.eq(bo.getEmployeeId() != null, PayDayWorkHours::getEmployeeId, bo.getEmployeeId());
        lqw.like(StringUtils.isNotBlank(bo.getEmpName()), PayDayWorkHours::getEmpName, bo.getEmpName());
        lqw.eq(bo.getDate() != null, PayDayWorkHours::getDate, bo.getDate());
        lqw.eq(StringUtils.isNotBlank(bo.getDwYearMonth()), PayDayWorkHours::getDwYearMonth, bo.getDwYearMonth());
        lqw.eq(StringUtils.isNotBlank(bo.getNote()), PayDayWorkHours::getNote, bo.getNote());
        return lqw;
    }

    /**
     * 新增日工工时
     */
    @Override
    @Transactional
    public R<Void> insertByBo(PayDayWorkHoursQuery2 payDayWorkHoursQuery2) {
        //先拆分员工 然后每个员工信息存储到SgrDayWorkHoursQuery集合中
        List<PayDayWorkHoursQuery>  querys = new ArrayList<>();
        if(payDayWorkHoursQuery2.getEmpInfos()!=null&&payDayWorkHoursQuery2.getEmpInfos().size()>0){
            return R.fail("添加工时的员工为空！");
        }
        for(PayDayWorkEmps emp :payDayWorkHoursQuery2.getEmpInfos()){
            PayDayWorkHoursQuery payDayWorkHoursQuery = new PayDayWorkHoursQuery();
            payDayWorkHoursQuery.setEmpName(emp.getEmpName());
            payDayWorkHoursQuery.setEmployeeId(emp.getEmployeeId());
            payDayWorkHoursQuery.setDeptId(emp.getDeptId());
            payDayWorkHoursQuery.setDeptName(emp.getDeptName());
            payDayWorkHoursQuery.setDwHoursContrasts(payDayWorkHoursQuery2.getDwHoursContrasts());
            payDayWorkHoursQuery.setDwYearMonth(payDayWorkHoursQuery2.getDwYearMonth());
            payDayWorkHoursQuery.setDate(payDayWorkHoursQuery2.getDate());
            querys.add(payDayWorkHoursQuery);
        }
        //验证每个员工信息是否符合添加条件  不符合则提示退出
        for(PayDayWorkHoursQuery sgrDayWorkHoursQuery:querys){
            //1.已有该员工该日期的工时工单
            String rigongDate = new SimpleDateFormat("yyyy-MM-dd").format(sgrDayWorkHoursQuery.getDate());
            PayDayWorkHoursBo payDayWorkHours = new PayDayWorkHoursBo();
            payDayWorkHours.setDate(sgrDayWorkHoursQuery.getDate());
            payDayWorkHours.setEmployeeId(sgrDayWorkHoursQuery.getEmployeeId());
            List<PayDayWorkHoursVo> sgrDayWorkHourss = this.queryList(payDayWorkHours);
            if (sgrDayWorkHourss != null && sgrDayWorkHourss.size() > 0) {
                //return AjaxResult.error("已有员工该日期的工时信息");
                return R.fail(("新增失败，已有"+sgrDayWorkHoursQuery.getEmpName()+"员工"+rigongDate+"的工时信息"));
            }
            Integer cmresult = compareTimes(sgrDayWorkHoursQuery);
            switch (cmresult) {
                case 0:
                    break;
              /* case -1:
                   return AjaxResult.error("喷塑生产，"+sgrDayWorkHoursQuery.getEmpName()+"考勤需要有上午上班时间和下午下班时间");*/
                case -2:
                    return R.fail("新增失败，" + sgrDayWorkHoursQuery.getEmpName() + "考勤时间录入不全");
                case -3:
                    return R.fail("新增失败，请先录入" + sgrDayWorkHoursQuery.getEmpName() + "考勤信息");
                case -4:
                    return R.fail("新增失败，" + sgrDayWorkHoursQuery.getEmpName() + "工时时间段不在考勤范围内");
                case -5:
                    return R.fail("新增失败，" + sgrDayWorkHoursQuery.getEmpName() + "工时时间段与流程卡工单时间段重叠");
                case -6:
                    return R.fail("新增失败，" + sgrDayWorkHoursQuery.getEmpName() + "工时时间段与包活工单时间段重叠");
            }
        }
        //遍历存储员工信息
        for(PayDayWorkHoursQuery sgrDayWorkHoursQuery:querys){
            //保存员工工时信息
            sgrDayWorkHoursQuery.setDwYearMonth(getYearMonth(sgrDayWorkHoursQuery));
            PayDayWorkHours payDayWorkHour = BeanUtil.toBean(sgrDayWorkHoursQuery, PayDayWorkHours.class);
            int result = baseMapper.insert(payDayWorkHour);
            //存员工当日工作时间段
            if (result > 0) {
                List<PayDwHoursContrast> sgrDwHoursContrasts = sgrDayWorkHoursQuery.getDwHoursContrasts();
                sgrDwHoursContrasts.parallelStream().forEachOrdered(sgrDwHoursContrast -> {
                    sgrDwHoursContrast.setDwHoursId(payDayWorkHour.getId());
                    if (sgrDwHoursContrast.getIsHelper() == 0) {//当不是帮工时  直接存员工的部门
                        sgrDwHoursContrast.setDeptId(sgrDayWorkHoursQuery.getDeptId());
                        sgrDwHoursContrast.setDeptName(sgrDayWorkHoursQuery.getDeptName());
                    }
                    sgrDwHoursContrast.setHours(DateCompareUtil.getDatePoor(sgrDwHoursContrast.getStartTime(),sgrDwHoursContrast.getEndTime()));
                    dwHoursContrastMapper.insert(sgrDwHoursContrast);
                });
            }else{
                return R.ok("系统存储数据库过程中出现故障!");
            }
        }

        /*PayDayWorkHours add = BeanUtil.toBean(bo, PayDayWorkHours.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }*/
        return R.ok();
    }

    /**
     * 修改日工工时
     */
    @Override
    @Transactional
    public R<Void> updateByBo(PayDayWorkHoursQuery sgrDayWorkHoursQuery) {
        Integer cmresult = compareTimes(sgrDayWorkHoursQuery);
        switch (cmresult) {
            case 0:
                break;
           /* case -1://喷塑生产特殊情况，1天只打2次卡  在此时间段完成校验
                return AjaxResult.error("喷塑生产，"+sgrDayWorkHoursQuery.getEmpName()+"考勤需要有上午上班时间和下午下班时间");*/
            case -2:
                return R.fail("修改失败，"+sgrDayWorkHoursQuery.getEmpName()+"考勤时间录入不全");
            case -3:
                return R.fail("修改失败，请先录入"+sgrDayWorkHoursQuery.getEmpName()+"考勤信息");
            case -4:
                return R.fail("修改失败，"+sgrDayWorkHoursQuery.getEmpName()+"工时时间段不在考勤范围内");
            case -5:
                return R.fail("修改失败，"+sgrDayWorkHoursQuery.getEmpName()+"工时时间段与流程卡工单时间段重叠");
            case -6:
                return R.fail("修改失败，"+sgrDayWorkHoursQuery.getEmpName()+"工时时间段与包活工单时间段重叠");
        }

        //保存工时信息
        sgrDayWorkHoursQuery.setDwYearMonth(getYearMonth(sgrDayWorkHoursQuery));
        PayDayWorkHours payDayWorkHour = BeanUtil.toBean(sgrDayWorkHoursQuery, PayDayWorkHours.class);
        int result = baseMapper.insert(payDayWorkHour);
        //存员工当日工作时间段
        if (result > 0) {
            //采用先删除对应的时间段，然后重新添加的方式
            int delNum = dwHoursContrastMapper.deleteSgrDwHoursContrastByDwHoursId(sgrDayWorkHoursQuery.getId());
            if (delNum <= 0) {
                return R.fail("操作失败");  //删除失败直接返回
            }
            //重新插入时间段
            List<PayDwHoursContrast> sgrDwHoursContrasts = sgrDayWorkHoursQuery.getDwHoursContrasts();
            sgrDwHoursContrasts.parallelStream().forEachOrdered(sgrDwHoursContrast -> {
                sgrDwHoursContrast.setDwHoursId(payDayWorkHour.getId());
                if (sgrDwHoursContrast.getIsHelper() == 0) {//当不是帮工时  直接存员工的部门
                    sgrDwHoursContrast.setDeptId(sgrDayWorkHoursQuery.getDeptId());
                    sgrDwHoursContrast.setDeptName(sgrDayWorkHoursQuery.getDeptName());
                }
                sgrDwHoursContrast.setHours(DateCompareUtil.getDatePoor(sgrDwHoursContrast.getStartTime(),sgrDwHoursContrast.getEndTime()));
                dwHoursContrastMapper.insert(sgrDwHoursContrast);
            });
        }
        return R.ok();
    }

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

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

    /**
     * 工时时间与考勤   包活、流程卡等做比对
     * @param sgrDayWorkHoursQuery
     * @return
     */
    public int compareTimes(PayDayWorkHoursQuery sgrDayWorkHoursQuery) {
        //日工工时时间段与考勤时间比较，与包活时间比较  不能重复
        boolean ispentu = false; //标记是否为喷塑生产部门
        Date kqStartAm = null;
        Date kqEndAm = null;
        Date kqStartPm = null;
        Date kqEndPm = null;
        //获取员工当日的考勤记录
        PayAttendanceBo attendance = new PayAttendanceBo();
        attendance.setKaoqinDate(sgrDayWorkHoursQuery.getDate());
        attendance.setEmpName(sgrDayWorkHoursQuery.getEmpName());
        List<PayAttendanceVo> kaoqins = attendanceService.queryList(attendance);
        //根据员工
        if (kaoqins != null && kaoqins.size() > 0) {
            kqStartAm = kaoqins.get(0).getAmStartTime();
            kqEndAm = kaoqins.get(0).getAmEndTime();
            kqStartPm = kaoqins.get(0).getPmStartTime();
            kqEndPm = kaoqins.get(0).getPmEndTime();
            //喷塑生产部门一天只打两次卡校验     (第二次修改为喷塑生产不校验考勤)
            if(sgrDayWorkHoursQuery.getDeptName().equals("喷塑生产")){
                ispentu=true;
                /*if(kqStartAm == null||kqEndPm == null){
                    return -1;
                }*/
            }else if ((kqStartAm == null || kqEndAm == null) && (kqStartPm == null || kqEndPm == null)) {
                //return AjaxResult.error("考勤时间录入不全,无法比对");
                return -2;
            }
        } else {
            //return AjaxResult.error("不能做时间比对，请先录入考勤信息");
            return -3;
        }

        //获取包活及流程卡当日的时间段信息
        PayWorkTimeBo workTime = new PayWorkTimeBo();
        workTime.setEmpId(sgrDayWorkHoursQuery.getEmployeeId());
        workTime.setDate(sgrDayWorkHoursQuery.getDate());
        List<PayWorkTimeVo> sgrWorkTimes = workTimeService.queryList(workTime);
        PayBaohuoWorktimeBo bhworkTime = new PayBaohuoWorktimeBo();
        bhworkTime.setEmpId(sgrDayWorkHoursQuery.getEmployeeId());
        bhworkTime.setDate(sgrDayWorkHoursQuery.getDate());
        List<PayBaohuoWorktimeVo> bhworkTimes =baohuoWorktimeService.queryList(bhworkTime);

        //开始比对
        List<PayDwHoursContrast> dwHoursContrasts = sgrDayWorkHoursQuery.getDwHoursContrasts();
        for (PayDwHoursContrast dwHours : dwHoursContrasts) {
            Date start2 = dwHours.getStartTime();
            Date end2 = dwHours.getEndTime();
            boolean contain = true;  //默认包含
            if(ispentu){
                //后来修改为喷涂生产不校验考勤时间
                /*if (!DateCompareUtil.isContain(kqStartAm, kqEndPm, start2, end2)) {
                    contain = false;
                }*/
            }else{
                //判断时间段是否为上午包含 还是 下午包含
                if (kqStartAm != null && kqEndAm != null) {
                    if (!DateCompareUtil.isContain(kqStartAm, kqEndAm, start2, end2)) {
                        contain = false;
                    }
                }
                //当上午考勤都为null时
                if(kqStartAm == null || kqEndAm == null){
                    contain = false;
                }
                if (!contain) {
                    if (kqStartPm != null && kqEndPm != null) {
                        if (DateCompareUtil.isContain(kqStartPm, kqEndPm, start2, end2)) {
                            contain = true;
                        }
                    }
                }
            }

            if (!contain) {
                //return AjaxResult.error("工时时间段不在考勤范围内");
                return -4;
            } else {
                //获取该员工当天的流程卡信息  做时间重叠比对
                if (sgrWorkTimes != null && sgrWorkTimes.size() > 0) {
                    for (PayWorkTimeVo wtime : sgrWorkTimes) {

                        if (DateCompareUtil.isOverlapping(start2, end2, wtime.getStime(), wtime.getEtime())) {
                            //return AjaxResult.error("工时时间段与流程卡工单时间段重叠");
                            return -5;
                        }
                    }
                }
                //获取该员工当天的包活信息  做时间重叠比对
                if (bhworkTimes != null && bhworkTimes.size() > 0) {
                    for (PayBaohuoWorktimeVo bhtime : bhworkTimes) {

                        if (DateCompareUtil.isOverlapping(start2, end2, bhtime.getStime(), bhtime.getEtime())) {
                            //return AjaxResult.error("工时时间段与包活工单时间段重叠");
                            return -6;
                        }
                    }
                }
            }
        }
        return 0;
    }
    public String getYearMonth(PayDayWorkHoursQuery payDayWorkHoursQuery){
        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM");
        Calendar cal = Calendar.getInstance();
        cal.setTime(payDayWorkHoursQuery.getDate());
        return ft.format(cal.getTime());
    }
}
