package com.ruoyi.system.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
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.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.IBusinessTripService;

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

/**
 * 出差记录信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-06-23
 */
@Service
public class BusinessTripServiceImpl implements IBusinessTripService 
{
    @Autowired
    private BusinessTripMapper businessTripMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private BusinessUserMapper businessUserMapper;

    @Autowired
    private ProcessConfigurationMapper processConfigurationMapper;

    @Autowired
    private KaoqinConfigMapper kaoqinConfigMapper;

    @Autowired
    private IKaoqinRecordService kaoqinRecordService;

    @Autowired
    private KaoqinRecordMapper kaoqinRecordMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysDeptMapper deptMapper;


    /**
     * 查询出差记录信息
     * 
     * @param id 出差记录信息主键
     * @return 出差记录信息
     */
    @Override
    public BusinessTrip selectBusinessTripById(Long id)
    {
        BusinessTrip businessTrip = businessTripMapper.selectBusinessTripById(id);

        BusinessUser businessUser = new BusinessUser();
        businessUser.setBusinessId(id);
        List<BusinessUser> businessUsers = businessUserMapper.selectBusinessUserList(businessUser);
        businessTrip.setBusinessUserList(businessUsers);

        return businessTrip;
    }

    /**
     * 查询出差记录信息列表
     * 
     * @param businessTrip 出差记录信息
     * @return 出差记录信息
     */
    @Override
    public List<BusinessTrip> selectBusinessTripList(BusinessTrip businessTrip)
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!"admin".equals(user.getUserName())){
            businessTrip.setUserId(user.getUserId());
        }
        return businessTripMapper.selectBusinessTripListLb(businessTrip);
    }

    /**
     * 新增出差记录信息
     * 
     * @param businessTrip 出差记录信息
     * @return 结果
     */
    @Override
    public int insertBusinessTrip(BusinessTrip businessTrip)
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        businessTrip.setInitiatorId(user.getUserId());
        businessTrip.setInitiatorName(user.getNickName());
        businessTrip.setSubmitTime(DateUtils.getNowDate());
        int index = businessTripMapper.insertBusinessTrip(businessTrip);

        BusinessUser bu = new BusinessUser();
        bu.setBusinessId(businessTrip.getId());
        bu.setAbsenteeId(user.getUserId());
        bu.setAbsenteeName(user.getNickName());
        bu.setDeptId(user.getDeptId());
        bu.setDeptName(user.getDept().getDeptName());
        bu.setType("1");
        bu.setSubmitTime(DateUtils.getNowDate());
        businessUserMapper.insertBusinessUser(bu);

        if(businessTrip.getBusinessUserList()!=null && !businessTrip.getBusinessUserList().isEmpty()){
            //保存人员表
            StringBuilder sb = new StringBuilder();
            List<BusinessUser> businessUserList = businessTrip.getBusinessUserList();
            for (int i = 0; i < businessUserList.size(); i++) {
                BusinessUser businessUser = businessUserList.get(i);

                if(i==0){
                    sb.append(businessUser.getAbsenteeName());
                }else{
                    sb.append("、").append(businessUser.getAbsenteeName());
                }


                businessUser.setBusinessId(businessTrip.getId());
                //查询人员部门信息
                SysUser sysUser = userMapper.selectUserById(businessUser.getAbsenteeId());
                businessUser.setDeptId(sysUser.getDeptId());
                businessUser.setDeptName(sysUser.getDept().getDeptName());
                businessUser.setType("2");
                businessUser.setSubmitTime(DateUtils.getNowDate());
                businessUserMapper.insertBusinessUser(businessUser);
            }
            //将随行人员放入主表
            businessTrip.setAbsenteeName(sb.toString());
            businessTripMapper.updateBusinessTrip(businessTrip);
        }

        return index;
    }

    /**
     * 修改出差记录信息
     * 
     * @param businessTrip 出差记录信息
     * @return 结果
     */
    @Override
    public int updateBusinessTrip(BusinessTrip businessTrip)
    {
        if(!"0".equals(businessTrip.getIsPass())){
            throw new ServiceException("当前出差已处理，无法修改");
        }
        //删除随行人员信息
        businessUserMapper.deleteBusinessUserByBusinessId(businessTrip.getId());

        SysUser use = SecurityUtils.getLoginUser().getUser();
        BusinessUser bUse = new BusinessUser();
        bUse.setAbsenteeId(use.getUserId());
        bUse.setAbsenteeName(use.getNickName());
        bUse.setDeptId(use.getDeptId());
        bUse.setDeptName(use.getDept().getDeptName());
        bUse.setType("1");
        bUse.setSubmitTime(DateUtils.getNowDate());
        businessUserMapper.insertBusinessUser(bUse);

        if(businessTrip.getBusinessUserList()!=null && !businessTrip.getBusinessUserList().isEmpty()){
            //保存人员表
            StringBuilder sb = new StringBuilder();
            List<BusinessUser> businessUserList = businessTrip.getBusinessUserList();
            for (int i = 0; i < businessUserList.size(); i++) {
                BusinessUser businessUser = businessUserList.get(i);

                if(i==0){
                    sb.append(businessUser.getAbsenteeName());
                }else{
                    sb.append("、").append(businessUser.getAbsenteeName());
                }

                businessUser.setBusinessId(businessTrip.getId());
                //查询人员部门信息
                SysUser sysUser = userMapper.selectUserById(businessUser.getAbsenteeId());
                businessUser.setDeptId(sysUser.getDeptId());
                businessUser.setDeptName(sysUser.getDept().getDeptName());
                businessUser.setType("2");
                businessUser.setSubmitTime(DateUtils.getNowDate());
                businessUserMapper.insertBusinessUser(businessUser);
            }


            //将随行人员放入主表
            businessTrip.setAbsenteeName(sb.toString());
        }

        return businessTripMapper.updateBusinessTrip(businessTrip);
    }

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

    /**
     * 删除出差记录信息信息
     * 
     * @param id 出差记录信息主键
     * @return 结果
     */
    @Override
    public int deleteBusinessTripById(Long id)
    {
        return businessTripMapper.deleteBusinessTripById(id);
    }

    @Override
    public int audit(BusinessTrip businessTrip) {
        //获取当前人员信息
        SysUser user = SecurityUtils.getLoginUser().getUser();
        businessTrip.setExaminersId(user.getUserId());
        businessTrip.setExaminersName(user.getNickName());
        if (TWO.equals(businessTrip.getIsPass())) {
            //查询出差信息
            BusinessTrip trip = businessTripMapper.selectBusinessTripById(businessTrip.getId());
            //出差人员
            BusinessUser businessUser = new BusinessUser();
            businessUser.setBusinessId(businessTrip.getId());
            List<BusinessUser> businessUsers = businessUserMapper.selectBusinessUserList(businessUser);
            //考勤规则
            KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();

            // 3. 解析出差时间范围
            LocalDateTime start = DateUtils.convertToLocalDateTime(trip.getStartTime());
            LocalDateTime end = DateUtils.convertToLocalDateTime(trip.getEndTime());
            // 获取日期列表
            List<LocalDate> leaveDates = DateUtils.getDateRange(start.toLocalDate(), end.toLocalDate());
            for (BusinessUser businessUser1 : businessUsers) {
                //查询打卡信息
                KaoqinRecord kaoqinRecord = new KaoqinRecord();
                kaoqinRecord.setUserId(businessUser1.getAbsenteeId());
                kaoqinRecord.setStartTime(DateUtils.dateTime(trip.getStartTime()));
                kaoqinRecord.setEndTime(DateUtils.dateTime(trip.getEndTime()));
                List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
                Map<String, List<KaoqinRecord>> kaoqinRecordCollect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));

                //查询人员信息
                SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(businessUser1.getAbsenteeId()));

                // 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(date, start, end, kaoqinConfig, record,sysUser);
                }

            }

        }

        return businessTripMapper.updateBusinessTrip(businessTrip);
    }

    private void updateDailyAttendance(LocalDate date, LocalDateTime leaveStart, LocalDateTime leaveEnd, KaoqinConfig config, KaoqinRecord record, SysUser sysUser) {
        // 3. 不存在记录则创建新记录
        if (record == null) {
            record = createNewRecord(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 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(EIGHT); // 上午上班出差
        }
        if(FOUR.equals(config.getKaNum())){
            if (isLeaveCovered(leaveStart, leaveEnd,amOutStart)) {
                record.setKaTypeAmOut(EIGHT); // 上午下班出差
            }

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

    // 检查请假是否覆盖时间段
    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) && !"8".equals(status))
                .findAny()
                .isPresent();

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

    private KaoqinRecord createNewRecord(LocalDate date, KaoqinConfig config, SysUser sysUser) {
        KaoqinRecord record = new KaoqinRecord();
        record.setUserId(sysUser.getUserId());
        record.setUserName(sysUser.getNickName());
        record.setDeptId(sysUser.getDeptId());
        record.setDeptName(sysUser.getDept().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;
    }

    @Override
    public List<BusinessTrip> presentList(BusinessTrip businessTrip) {

        //获取当前人员信息
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!"admin".equals(user.getUserName())){
            //获取当前人员补卡配置所在的部门id
            ProcessConfiguration processConfiguration = new ProcessConfiguration();
            processConfiguration.setUserId(user.getUserId());
            processConfiguration.setType("3");
            List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
            if(list==null|| list.isEmpty()){
                List<BusinessTrip> businessTripList = new ArrayList<>();
                return businessTripList;
            }
            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);
                }
            }

            businessTrip.setDeptIds(deptIdList);
        }
        return businessTripMapper.selectBusinessTripList(businessTrip);
    }
}
