package com.ruoyi.system.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IKaoqinRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.service.IRecordLeaveService;

import static com.ruoyi.common.constant.Constants.*;

/**
 * 请假记录信息Service业务层处理
 *
 * @author ruoyi
 * @date 2023-02-13
 */
@Service
public class RecordLeaveServiceImpl implements IRecordLeaveService {
    @Autowired
    private RecordLeaveMapper recordLeaveMapper;

    @Autowired
    private ProcessConfigurationMapper processConfigurationMapper;

    @Autowired
    private RecordLeaveFjMapper recordLeaveFjMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private KaoqinConfigMapper kaoqinConfigMapper;

    @Autowired
    private IKaoqinRecordService kaoqinRecordService;

    @Autowired
    private KaoqinRecordMapper kaoqinRecordMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    /**
     * 查询请假记录信息
     *
     * @param id 请假记录信息主键
     * @return 请假记录信息
     */
    @Override
    public RecordLeave selectRecordLeaveById(Long id) {
        return recordLeaveMapper.selectRecordLeaveById(id);
    }

    /**
     * 查询请假记录信息列表
     *
     * @param recordLeave 请假记录信息
     * @return 请假记录信息
     */
    @Override
    public List<RecordLeave> selectRecordLeaveList(RecordLeave recordLeave) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!"admin".equals(user.getUserName())) {
            recordLeave.setAbsenteeId(String.valueOf(user.getUserId()));
        }
        return recordLeaveMapper.selectRecordLeaveList(recordLeave);
    }

    /**
     * 新增请假记录信息
     *
     * @param recordLeave 请假记录信息
     * @return 结果
     */
    @Override
    public int insertRecordLeave(RecordLeave recordLeave) {
        //获取当前人员信息
        SysUser user = SecurityUtils.getLoginUser().getUser();
        recordLeave.setAbsenteeId(String.valueOf(user.getUserId()));
        recordLeave.setAbsenteeName(user.getNickName());
        recordLeave.setDeptId(user.getDeptId());
        recordLeave.setDeptName(user.getDept().getDeptName());
        recordLeave.setSubmitTime(DateUtils.getNowDate());

        return recordLeaveMapper.insertRecordLeave(recordLeave);
    }

    /**
     * 修改请假记录信息
     *
     * @param recordLeave 请假记录信息
     * @return 结果
     */
    @Override
    public int updateRecordLeave(RecordLeave recordLeave) {
        RecordLeave recordLeave1 = recordLeaveMapper.selectRecordLeaveById(recordLeave.getId());
        if (!"0".equals(recordLeave1.getIsPass())) {
            throw new ServiceException("当前补卡已处理，无法修改");
        }
        recordLeave.setSubmitTime(DateUtils.getNowDate());
        return recordLeaveMapper.updateRecordLeave(recordLeave);
    }

    /**
     * 批量删除请假记录信息
     *
     * @param ids 需要删除的请假记录信息主键
     * @return 结果
     */
    @Override
    public int deleteRecordLeaveByIds(Long[] ids) {
        return recordLeaveMapper.deleteRecordLeaveByIds(ids);
    }

    /**
     * 删除请假记录信息信息
     *
     * @param id 请假记录信息主键
     * @return 结果
     */
    @Override
    public int deleteRecordLeaveById(Long id) {
        return recordLeaveMapper.deleteRecordLeaveById(id);
    }

    @Override
    public int audit(RecordLeave recordLeave) {
        //获取当前人员信息
        SysUser user = SecurityUtils.getLoginUser().getUser();

        if (TWO.equals(recordLeave.getIsPass())) {
            RecordLeave recordLeave1 = recordLeaveMapper.selectRecordLeaveById(recordLeave.getId());
            //查询人员信息
            SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(recordLeave1.getAbsenteeId()));
            //考勤规则
            KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
            //查询打卡信息
            KaoqinRecord kaoqinRecord = new KaoqinRecord();
            kaoqinRecord.setUserId(sysUser.getUserId());
            kaoqinRecord.setStartTime(DateUtils.dateTime(recordLeave1.getStartTime()));
            kaoqinRecord.setEndTime(DateUtils.dateTime(recordLeave1.getEndTime()));
            List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
            Map<String, List<KaoqinRecord>> kaoqinRecordCollect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));


            // 3. 解析请假时间范围
            LocalDateTime start = DateUtils.convertToLocalDateTime(recordLeave1.getStartTime());
            LocalDateTime end = DateUtils.convertToLocalDateTime(recordLeave1.getEndTime());
            // 获取日期列表
            //List<String> dates = DateUtils.getDateStringsBetween(recordLeave1.getStartTime(), recordLeave1.getEndTime());
            List<LocalDate> leaveDates = DateUtils.getDateRange(start.toLocalDate(), end.toLocalDate());
            // 5. 处理每个请假日期
            for (LocalDate date : leaveDates) {
                KaoqinRecord record = null;
                if (kaoqinRecordCollect.containsKey(DateUtils.convertToString(date, "yyyy-MM-dd"))) {
                    record = new KaoqinRecord();
                    record = kaoqinRecordCollect.get(DateUtils.convertToString(date, "yyyy-MM-dd")).get(0);
                }
                updateDailyAttendance(recordLeave1, date, start, end, kaoqinConfig, record, sysUser);
            }

        }

        recordLeave.setExaminersId(user.getUserId());
        recordLeave.setExaminersName(user.getNickName());
        return recordLeaveMapper.updateRecordLeave(recordLeave);
    }

    // 更新单日考勤记录
    private void updateDailyAttendance(RecordLeave leave, LocalDate date,
                                       LocalDateTime leaveStart, LocalDateTime leaveEnd,
                                       KaoqinConfig config, KaoqinRecord record, SysUser sysUser) {


        // 3. 不存在记录则创建新记录
        if (record == null) {
            record = createNewRecord(leave, date, config, sysUser);
        }

        // 4. 更新打卡时段状态
        updateTimeSlotStatus(record, date, leaveStart, leaveEnd, config);

        // 5. 检查整体考勤状态
        updateOverallStatus(record);

        // 6. 保存更新
        if (record.getRecordId() == null || record.getRecordId() == 0) {
            kaoqinRecordMapper.insertKaoqinRecord(record);
        } else {
            kaoqinRecordMapper.updateKaoqinRecord(record);
        }

    }

    // 创建新的考勤记录
    private KaoqinRecord createNewRecord(RecordLeave leave, LocalDate date, KaoqinConfig config, SysUser sysUser) {
        KaoqinRecord record = new KaoqinRecord();
        record.setUserId(Long.parseLong(leave.getAbsenteeId()));
        record.setUserName(leave.getAbsenteeName());
        record.setDeptId(leave.getDeptId());
        record.setDeptName(leave.getDeptName());
        record.setAncestors(sysUser.getDept().getAncestors());
        record.setKaNum(config.getKaNum()); // 使用配置的打卡次数

        // 设置日期相关字段
        record.setKaYear(String.valueOf(date.getYear()));
        record.setKaMonth(String.format("%02d", date.getMonthValue()));
        record.setKaDay(String.format("%02d", date.getDayOfMonth()));
        record.setKaWeek(DateUtils.getWeekday(date));
        record.setKaTime(date.format(DateTimeFormatter.ISO_LOCAL_DATE));

        // 设置默认状态
        record.setKaTypeAmIn("5");
        record.setKaTypeAmOut("5");
        record.setKaTypePmIn("5");
        record.setKaTypePmOut("5");
        record.setKaStatus("1");

        // 设置考勤地址
        record.setKaAddressAmIn(config.getKaAddress());
        record.setKaAddressAmOut(config.getKaAddress());
        record.setKaAddressPmIn(config.getKaAddress());
        record.setKaAddressPmOut(config.getKaAddress());

        return record;
    }

    // 更新打卡时段状态
    private void updateTimeSlotStatus(KaoqinRecord record, LocalDate date,
                                      LocalDateTime leaveStart, LocalDateTime leaveEnd,
                                      KaoqinConfig config) {
        // 从配置获取打卡时间
        LocalDateTime amInEnd = DateUtils.combineDateTime(date, config.getKaTimeAmIn()); // 上午上班截止时间
        LocalDateTime amOutStart = DateUtils.combineDateTime(date, config.getKaTimeAmOut());// 上午下班开始时间
        LocalDateTime pmInEnd = DateUtils.combineDateTime(date, config.getKaTimePmIn());// 下午上班截止时间
        LocalDateTime pmOutStart = DateUtils.combineDateTime(date, config.getKaTimePmOut());// 下午下班开始时间

        // 检查请假是否覆盖各时段
        if (isLeaveCovered(leaveStart, leaveEnd, amInEnd)) {
            record.setKaTypeAmIn(SEVEN); // 上午上班请假
        }
        if (FOUR.equals(config.getKaNum())) {
            if (isLeaveCovered(leaveStart, leaveEnd, amOutStart)) {
                record.setKaTypeAmOut(SEVEN); // 上午下班请假
            }

            if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd)) {
                record.setKaTypePmIn(SEVEN); // 下午上班请假
            }
        }
/*
        if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd, pmOutStart)) {
            record.setKaTypePmOut("7"); // 下午下班请假
        }*/
        if (isLeaveCovered(leaveStart, leaveEnd, pmOutStart)) {
            record.setKaTypePmOut(SEVEN); // 下午下班请假
        }
    }

    // 检查请假是否覆盖时间段
    private boolean isLeaveCovered(LocalDateTime leaveStart, LocalDateTime leaveEnd,
                                   LocalDateTime active) {
        return (leaveStart.isBefore(active) &&
                leaveEnd.isAfter(active));
    }

    // 更新整体考勤状态
    private void updateOverallStatus(KaoqinRecord record) {
        // 检查是否有异常状态（非正常和非请假）
        boolean hasAbnormal = Stream.of(
                        record.getKaTypeAmIn(),
                        record.getKaTypeAmOut(),
                        record.getKaTypePmIn(),
                        record.getKaTypePmOut()
                )
                .filter(status -> !"1".equals(status) && !"7".equals(status))
                .findAny()
                .isPresent();

        record.setKaStatus(hasAbnormal ? "2" : "1");
    }


    @Override
    public List<RecordLeave> presentList(RecordLeave recordLeave) {
        //获取当前人员信息
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!"admin".equals(user.getUserName())) {
            //获取当前人员补卡配置所在的部门id
            ProcessConfiguration processConfiguration = new ProcessConfiguration();
            processConfiguration.setUserId(user.getUserId());
            processConfiguration.setType("2");
            List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
            if (list == null || list.isEmpty()) {
                List<RecordLeave> recordLeaveList = new ArrayList<>();
                return recordLeaveList;
            }
            List<Long> deptIdList = new ArrayList<>();
            List<Long> deptIds = list.stream().map(ProcessConfiguration::getDeptId).collect(Collectors.toList());
            deptIdList.addAll(deptIds);
            for (Long deptId : deptIds) {
                //查询所有子部门
                List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
                if(children!=null && !children.isEmpty()){
                    List<Long> childrenIds = children.stream().map(SysDept::getDeptId).collect(Collectors.toList());
                    deptIdList.addAll(childrenIds);
                }
            }
            recordLeave.setDeptIds(deptIdList);
        }
        return recordLeaveMapper.selectRecordLeaveList(recordLeave);
    }
}
