package com.ruoyi.zhushi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.zhushi.entity.*;
import com.ruoyi.zhushi.mapper.NjBalanceManageMapper;
import com.ruoyi.zhushi.mapper.NjRuleConfigAndUserMapper;
import com.ruoyi.zhushi.mapper.NjRuleConfigMapper;
import com.ruoyi.zhushi.service.NjBalanceManageService;
import com.ruoyi.zhushi.util.Constans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

@Service
public class NjBalanceManageServiceImpl implements NjBalanceManageService {

    @Autowired
    private NjBalanceManageMapper njBalanceManageMapper;

    @Autowired
    private NjRuleConfigMapper njRuleConfigMapper;

    @Autowired
    private NjRuleConfigAndUserMapper njRuleConfigAndUserMapper;

    @Autowired
    private ISysUserService userService;

    @Override
    public TableDataInfo<NjBalanceManageDTO> queryPageList(NjBalanceManageDTO njBalanceManageDTO, PageQuery pageQuery) {
        // 获取当前登录用户的ID
        LoginUser loginUser = LoginHelper.getLoginUser();
        String username = loginUser.getUsername();
        LambdaQueryWrapper<NjBalanceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(njBalanceManageDTO.getUserName()!= null, NjBalanceManage::getUserName, njBalanceManageDTO.getUserName());
        queryWrapper.eq(njBalanceManageDTO.getNickName()!= null, NjBalanceManage::getNickName, njBalanceManageDTO.getNickName());
        IPage<NjBalanceManageDTO> njBalanceManageDTOS = njBalanceManageMapper.selectVoPage(pageQuery.build(), queryWrapper, NjBalanceManageDTO.class);
        return TableDataInfo.build(njBalanceManageDTOS);
    }

    @Override
    public void insertBatch(List<NjBalanceManage> njBalanceManages) {
        njBalanceManageMapper.insertBatch(njBalanceManages);
    }

    @Override
    public BigDecimal getUnUsedDayByUserId(long userId) {
        // 根据用户id获取年假余额
        LambdaQueryWrapper<NjBalanceManage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BeanUtil.isNotEmpty(userId), NjBalanceManage::getUserId, userId);
        NjBalanceManageDTO njBalanceManageDTO = njBalanceManageMapper.selectVoOne(queryWrapper);
        return njBalanceManageDTO.getUnusedDay();
    }

    @Override
    public int update(NjBalanceManageDTO njBalanceManageDTO) {
        NjBalanceManage njBalanceManage = new NjBalanceManage();
        BeanUtil.copyProperties(njBalanceManageDTO, njBalanceManage);
        int i = njBalanceManageMapper.updateById(njBalanceManage);
        return i;
    }

    @Override
    public void generateYearBalance(String flag, NjRuleConfigDTO dto) {
        // 查询年假配置管理
//        List<NjRuleConfigDTO> njRuleConfigDTOS = njRuleConfigService.queryAll();
        LambdaQueryWrapper<NjRuleConfig> queryWrapper = Wrappers.lambdaQuery();
        List<NjRuleConfigDTO> njRuleConfigDTOS = new ArrayList<>();
        if(flag.equals("dingshi")){
            njRuleConfigDTOS = njRuleConfigMapper.selectVoList(queryWrapper, NjRuleConfigDTO.class);
        }
        if(flag.equals("shoudong")){
            njRuleConfigDTOS.add(dto);
        }
        // 遍历所有年假配置，判断是否适用全部人员，判断年假的生成方式
        for (NjRuleConfigDTO njRuleConfigDTO : njRuleConfigDTOS) {
            // 获取人员适用范围true  全员， fale  指定人员
            Boolean applicableRange = njRuleConfigDTO.getApplicableRange();
            // 定义存储人员
            List<NjBalanceManage> njBalanceManages = new ArrayList<>();
            if(applicableRange){
                // 全员
                // 查询所有人员
                SysUser user = new SysUser();
                List<SysUser> list = userService.selectUserList(user);
                // 遍历人员生成年假记录
                for (SysUser sysUser : list) {
                    NjBalanceManage njBalanceManage = new NjBalanceManage();
                    // 根据 人员id 查询年假信息 如果存在就跟新年假信息
                    njBalanceManage.setUserId(sysUser.getUserId());
                    LambdaQueryWrapper<NjBalanceManage> queryWrapper1 = new LambdaQueryWrapper<>();
                    queryWrapper1.eq(NjBalanceManage::getUserId, sysUser.getUserId());
                    int year = LocalDate.now().getYear();
                    queryWrapper1.apply("YEAR(create_time) = {}", year);
                    NjBalanceManage njBalanceManage1 = njBalanceManageMapper.selectOne(queryWrapper1);
                    if (BeanUtil.isNotEmpty(njBalanceManage1)) {
                        njBalanceManage = njBalanceManage1;
                    }

                    // 获取人员id
                    Long userId = sysUser.getUserId();
                    njBalanceManage.setUserId(userId);
                    // 获取人员名称
                    String userName = sysUser.getUserName();
                    njBalanceManage.setUserName(userName);
                    // 获取人员昵称
                    String nickName = sysUser.getNickName();
                    njBalanceManage.setNickName(nickName);

                    // 获取人员部门名称
                    String deptName = sysUser.getDept().getDeptName();
                    njBalanceManage.setDeptName(deptName);

                    // 判断年假发放规则
                    Integer annualLeaveTiers = njRuleConfigDTO.getAnnualLeaveTiers();
                    // 获取入职时间
                    LocalDate joinedDate = sysUser.getJoinedDate();
                    // 根据入职时间计算 （年假天数 = 入职当年剩余日历天数 / 365 × 5）
                    if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_0){
                        // 获取入职当年的最后一天
                        LocalDate lastDayOfYear = joinedDate.withDayOfMonth(31).withMonth(12);
                        LocalDate now = LocalDate.now();
                        // 计算从入职日期（不含）到年底（含）的天数差
                        long remainingDay = ChronoUnit.DAYS.between(joinedDate, now) + 1;
                        BigDecimal annualLeave = BigDecimal.valueOf(remainingDay).divide(BigDecimal.valueOf(365), 1, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(5));
                        njBalanceManage.setAnnualLeave(annualLeave);
                        // 剩余天数
                        njBalanceManage.setUnusedDay(annualLeave);
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_5){
                        // 获取当前年的一月一日
                        LocalDate now1 = LocalDate.now();
                        LocalDate localDate = now1.withDayOfYear(1);
                        // 判断是否满一年
                        boolean oneYearCompleted = isOneYearCompleted(joinedDate, now1);
                        if(oneYearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_10){
                        // 获取当前年的一月一日
                        LocalDate now2 = LocalDate.now();
                        LocalDate localDate = now2.withDayOfYear(1);
                        // 判断是否满一年
                        boolean yearCompleted = isYearsCompleted(joinedDate, annualLeaveTiers);
                        if(yearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else{
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_15) {
                        // 获取当前年的一月一日
                        LocalDate now3 = LocalDate.now();
                        LocalDate localDate = now3.withDayOfYear(1);
                        // 判断是否满一年
                        boolean yearCompleted = isYearsCompleted(joinedDate, 20);
                        if(yearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else{
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }
                    // 已使用天数
                    njBalanceManage.setUsedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                    //上年结转
                    njBalanceManage.setLastYearUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                    // 转态
                    njBalanceManage.setIsEnable(true);
                    njBalanceManages.add(njBalanceManage);
                }

                // 指定人员
            }else {
                // 查询指定人员根据配置id
                LambdaQueryWrapper<NjRuleConfigAndUser> queryWrapper1 = Wrappers.lambdaQuery();
                queryWrapper1.eq(NjRuleConfigAndUser::getNjRuleConfigId, njRuleConfigDTO.getId());
                List<NjRuleConfigAndUserDTO> njRuleConfigAndUserDTOS = njRuleConfigAndUserMapper.selectVoList(queryWrapper1);
                for (NjRuleConfigAndUserDTO njRuleConfigAndUserDTO : njRuleConfigAndUserDTOS) {
                    NjBalanceManage njBalanceManage = new NjBalanceManage();

                    // 根据 人员id 查询年假信息 如果存在就跟新年假信息
                    LambdaQueryWrapper<NjBalanceManage> queryWrapper2 = new LambdaQueryWrapper<>();
                    queryWrapper2.eq(NjBalanceManage::getUserId, njRuleConfigAndUserDTO.getUserId());
                    int year = LocalDate.now().getYear();
                    queryWrapper2.apply("YEAR(create_time) = {0}", year);
                    NjBalanceManage njBalanceManage1 = njBalanceManageMapper.selectOne(queryWrapper2);
                    if (BeanUtil.isNotEmpty(njBalanceManage1)) {
                        njBalanceManage = njBalanceManage1;
                    }

                    // 获取人员id
                    Long userId = njRuleConfigAndUserDTO.getUserId();
                    njBalanceManage.setUserId(userId);
                    // 获取人员名称
                    String userName = njRuleConfigAndUserDTO.getUserName();
                    njBalanceManage.setUserName(userName);
                    // 获取人员昵称
                    String nickName = njRuleConfigAndUserDTO.getNickName();
                    njBalanceManage.setNickName(nickName);

                    // 获取人员部门名称
                    String deptName = njRuleConfigAndUserDTO.getDeptName();
                    njBalanceManage.setDeptName(deptName);

                    // 判断年假发放规则
                    Integer annualLeaveTiers = njRuleConfigDTO.getAnnualLeaveTiers();
                    // 获取入职时间
                    LocalDate joinedDate = njRuleConfigAndUserDTO.getJoinedDate() == null ? LocalDate.now() : njRuleConfigAndUserDTO.getJoinedDate();

                    // 根据入职时间计算 （年假天数 = 入职当年剩余日历天数 / 365 × 5）
                    if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_0){
                        // 获取入职当年的最后一天
                        LocalDate lastDayOfYear = joinedDate.withDayOfMonth(31).withMonth(12);
                        LocalDate now = LocalDate.now();

                        // 计算从入职日期（不含）到年底（含）的天数差
                        long remainingDay = ChronoUnit.DAYS.between(joinedDate, now) + 1;
                        BigDecimal annualLeave = BigDecimal.valueOf(remainingDay).divide(BigDecimal.valueOf(365), 1, RoundingMode.HALF_DOWN).multiply(BigDecimal.valueOf(5));
                        njBalanceManage.setAnnualLeave(annualLeave);
                        // 剩余天数
                        njBalanceManage.setUnusedDay(annualLeave);
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_5){
                        // 获取当前年的一月一日
                        LocalDate now1 = LocalDate.now();
                        LocalDate localDate = now1.withDayOfYear(1);
                        // 判断是否满一年
                        boolean oneYearCompleted = isOneYearCompleted(joinedDate, localDate);
                        if(oneYearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_10){
                        // 获取当前年的一月一日
                        LocalDate now2 = LocalDate.now();
                        LocalDate localDate = now2.withDayOfYear(1);
                        // 判断是否满一年
                        boolean yearCompleted = isYearsCompleted(joinedDate, annualLeaveTiers);
                        if(yearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else{
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }else if(annualLeaveTiers == Constans.ANNUALLEAVETIERS_15) {
                        // 获取当前年的一月一日
                        LocalDate now3 = LocalDate.now();
                        LocalDate localDate = now3.withDayOfYear(1);
                        // 判断是否满一年
                        boolean yearCompleted = isYearsCompleted(joinedDate, 20);
                        if(yearCompleted)
                        {
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(annualLeaveTiers));
                            // 剩余天数
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(annualLeaveTiers));
                        }else{
                            njBalanceManage.setAnnualLeave(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                            njBalanceManage.setUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                        }
                    }
                    // 已使用天数
                    njBalanceManage.setUsedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                    //上年结转
                    njBalanceManage.setLastYearUnusedDay(BigDecimal.valueOf(Constans.ANNUALLEAVETIERS_0));
                    // 转态
                    njBalanceManage.setIsEnable(true);
                    njBalanceManages.add(njBalanceManage);
                }
            }

            // 批量插入
            njBalanceManageMapper.insertOrUpdateBatch(njBalanceManages);
        }
    }


    /**
     * 判断入职是否已满一年（到指定日期）
     * @param hireDate 入职日期
     * @param targetDate 目标日期
     * @return true表示已满一年，false表示未满
     */
    public static boolean isOneYearCompleted(LocalDate hireDate, LocalDate targetDate) {
        // 计算两个日期之间的年、月、日差
        Period period = Period.between(hireDate, targetDate);

        // 判断是否满一年：年份差大于1，或年份差等于1且月份和日期都满足
        return period.getYears() > 1 ||
            (period.getYears() == 1 &&
                period.getMonths() == 0 &&
                period.getDays() >= 0);
    }


    /**
     * 判断入职是否已满指定年限（到当前日期）
     * @param hireDate 入职日期（java.time.LocalDate）
     * @param targetYears 目标年限（如10、20）
     * @return true：已满指定年限；false：未满
     */
    public static boolean isYearsCompleted(LocalDate hireDate, int targetYears) {
        LocalDate now = LocalDate.now(); // 当前日期
        return isYearsCompleted(hireDate, now, targetYears);
    }

    /**
     * 判断入职是否已满指定年限（到自定义目标日期）
     * @param hireDate 入职日期
     * @param targetDate 目标日期（如某个特定时间点）
     * @param targetYears 目标年限
     * @return true：已满指定年限；false：未满
     */
    public static boolean isYearsCompleted(LocalDate hireDate, LocalDate targetDate, int targetYears) {
        // 计算入职日期到目标日期的时间差（年、月、日）
        Period period = Period.between(hireDate, targetDate);
        int yearsDiff = period.getYears(); // 年份差

        // 核心判断逻辑：
        // 1. 年份差 > 目标年限 → 已满
        // 2. 年份差 == 目标年限 → 需精确到月和日（如入职日为2013-05-10，满10年需到2023-05-10及之后）
        if (yearsDiff > targetYears) {
            return true;
        } else if (yearsDiff == targetYears) {
            // 月份差 >= 0，且月份相等时日期差 >= 0 → 已满
            return period.getMonths() > 0
                || (period.getMonths() == 0 && period.getDays() >= 0);
        } else {
            return false;
        }
    }
}
