package jnpf.util.attendance;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import jnpf.attendance.service.RuleScopeService;
import jnpf.base.ActionResult;
import jnpf.entity.attendance.AttendanceRuleScope;
import jnpf.enums.attendance.ScopeBizType;
import jnpf.exception.HandleException;
import jnpf.model.attendance.dto.UpdateChangeDto;
import jnpf.model.attendance.dto.UserOrgDto;
import jnpf.model.personnels.dto.turnover.FtbDepUserDTO;
import jnpf.permission.V2UserApi;
import jnpf.permission.eum.v2.UserWorkStatusEnums;
import jnpf.permission.vo.v2.user.UserBoundInfoVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.service.FtbPersonnelsTurnoverManagementService;
import jnpf.util.ConstantUtil;
import jnpf.util.FtbUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * 规则适配范围工具类
 *
 * @author yanwenfu
 * @create 2025-09-18
 */
@Component
public class RuleScopeUtil {

    @Resource
    private RuleScopeService ruleScopeService;
    @Autowired
    private V2UserApi v2UserApi;
    @Resource
    private FtbPersonnelsTurnoverManagementService ftbPersonnelsTurnoverManagementService;


    public AttendanceRuleScope getRuleScope(String ruleId, String value, Integer ruleScope, ScopeBizType scopeBizType) {
        return getRuleScope(ruleId, value, ruleScope, scopeBizType, null);
    }
    /**
     * 生成适配范围
     *
     * @param value        值
     * @param ruleScope    适配范围
     * @param scopeBizType 业务类型
     * @return jnpf.entity.attendance.AttendanceRuleScope
     */
    public AttendanceRuleScope getRuleScope(String ruleId, String value, Integer ruleScope, ScopeBizType scopeBizType, String leaveTypeId) {

        AttendanceRuleScope attendanceRuleScope = new AttendanceRuleScope();
        attendanceRuleScope.setId(FtbUtil.getId());
        attendanceRuleScope.setBizType(scopeBizType.getValue());
        attendanceRuleScope.setRuleId(ruleId);
        attendanceRuleScope.setExpand(leaveTypeId);
        attendanceRuleScope.setScopeType(ruleScope);
        attendanceRuleScope.setScopeValue(value);
        attendanceRuleScope.setPriority(ruleScope);
        attendanceRuleScope.setCreatorUserId(UserProvider.getLoginUserId());
        attendanceRuleScope.setLastModifyUserId(UserProvider.getLoginUserId());
        attendanceRuleScope.setDeleteMark(ConstantUtil.NUM_FALSE);
        return attendanceRuleScope;
    }

    public void coverRuleScope(String ruleId, Integer ruleScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType) {
        coverRuleScope(ruleId, ruleScope, dataList, bizType, null);
    }

    /**
     * 覆盖适配范围(适用于加班&公休&假期)
     *
     * @param ruleId    规则id
     * @param ruleScope 适配范围(0: 全部, 1: 指定组织/成员)
     * @param dataList  组织列表&用户列表
     * @param bizType   适配范围业务类型
     */
    public void coverRuleScope(String ruleId, Integer ruleScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType, String leaveTypeId) {
        if (ConstantUtil.SCOPE_ALL.equals(ruleScope)) {
            // 删除其他相同业务类型的适配范围
            ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                    .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                    .eq(StringUtil.isNotEmpty(leaveTypeId), AttendanceRuleScope::getExpand, leaveTypeId)
                    .ne(AttendanceRuleScope::getRuleId, ruleId));
        } else {
            if (CollectionUtils.isNotEmpty(dataList.getLeft())) {
                // 查询组织下的所有人
                ActionResult<List<UserBoundVO>> actionResult = v2UserApi.listTargetOrganizesOrHaveChild(dataList.getLeft(), false, List.of(UserWorkStatusEnums.RESIGNED), UserProvider.getUser().getTenantId());
                if (null != actionResult && actionResult.getCode() == 200 && !actionResult.getData().isEmpty()) {
                    List<String> userIds = actionResult.getData().stream().map(UserBoundVO::getId).collect(Collectors.toList());
                    ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                            .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                            .eq(AttendanceRuleScope::getScopeType, ConstantUtil.RULE_SCOPE_USER)
                            .eq(StringUtil.isNotEmpty(leaveTypeId), AttendanceRuleScope::getExpand, leaveTypeId)
                            .in(AttendanceRuleScope::getScopeValue, userIds)
                            .ne(AttendanceRuleScope::getRuleId, ruleId));
                }
                ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                        .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                        .eq(AttendanceRuleScope::getScopeType, ConstantUtil.RULE_SCOPE_ORG)
                        .eq(StringUtil.isNotEmpty(leaveTypeId), AttendanceRuleScope::getExpand, leaveTypeId)
                        .in(AttendanceRuleScope::getScopeValue, dataList.getLeft())
                        .ne(AttendanceRuleScope::getRuleId, ruleId));
            }
            if (CollectionUtils.isNotEmpty(dataList.getRight())) {
                ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                        .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                        .eq(AttendanceRuleScope::getScopeType, ConstantUtil.RULE_SCOPE_USER)
                        .eq(StringUtil.isNotEmpty(leaveTypeId), AttendanceRuleScope::getExpand, leaveTypeId)
                        .in(AttendanceRuleScope::getScopeValue, dataList.getRight())
                        .ne(AttendanceRuleScope::getRuleId, ruleId));
            }
        }
    }

    /**
     * 生成适配范围列表
     *
     * @param ruleId    规则id
     * @param ruleScope 适配范围(0: 全部, 1: 指定组织/成员)
     * @param dataList  组织列表&用户列表
     * @param bizType   适配范围业务类型
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> getRuleScopeList(String ruleId, Integer ruleScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType) throws HandleException {
        return getRuleScopeList(ruleId, ruleScope, dataList, bizType, null);
    }

    /**
     * 生成适配范围列表
     *
     * @param ruleId      规则id
     * @param ruleScope   适配范围(0: 全部, 1: 指定组织/成员)
     * @param dataList    组织列表&用户列表
     * @param bizType     适配范围业务类型
     * @param leaveTypeId 2.0假期类型Id列表
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> getRuleScopeList(String ruleId, Integer ruleScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType, String leaveTypeId) throws HandleException {

        List<String> organizeList = dataList.getLeft();
        List<String> userIdList = dataList.getRight();
        List<AttendanceRuleScope> ruleScopeList = new ArrayList<>();
        if (ruleScope.equals(ConstantUtil.SCOPE_ALL)) {
            ruleScopeList.add(getRuleScope(ruleId, null, ConstantUtil.RULE_SCOPE_ALL, bizType, leaveTypeId));
        } else {
            if (null == organizeList) organizeList = List.of();
            if (null == userIdList) userIdList = List.of();
            if (organizeList.isEmpty() && userIdList.isEmpty()) {
                throw new HandleException("至少选择一个组织或成员");
            }
            if (!organizeList.isEmpty()) {
                organizeList.forEach(orgId -> ruleScopeList.add(getRuleScope(ruleId, orgId, ConstantUtil.RULE_SCOPE_ORG, bizType, leaveTypeId)));
            }
            if (!userIdList.isEmpty()) {
                userIdList.forEach(userId -> ruleScopeList.add(getRuleScope(ruleId, userId, ConstantUtil.RULE_SCOPE_USER, bizType, leaveTypeId)));
            }
        }
        if (bizType.equals(ScopeBizType.OVERTIME_RULE) || bizType.equals(ScopeBizType.PUBLIC_HOLIDAY_RULE )|| bizType.equals(ScopeBizType.LEAVE_RULES)) {
            coverRuleScope(ruleId, ruleScope, dataList, bizType, leaveTypeId);
        }
        return ruleScopeList;
    }

    public void saveBatch(List<AttendanceRuleScope> list) {

        ruleScopeService.saveBatch(list);
    }

    /**
     * 根据适配范围的变更, 更新数据库适配范围
     *
     * @param ruleId   加班规则id
     * @param oldScope 数据库适配范围(0: 全部, 1: 指定组织/成员)
     * @param newScope 更新适配范围(0: 全部, 1: 指定组织/成员)
     * @param dataList 更新组织/成员数据
     * @param bizType  适配范围业务类型
     * @return jnpf.model.attendance.dto.UpdateChangeDto 返回变更的组织和用户[新增, 删除]
     */
    public UpdateChangeDto updateRuleScopeList(String ruleId, Integer oldScope, Integer newScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType) throws HandleException {
        return updateRuleScopeList(ruleId, oldScope, newScope, dataList, bizType, null);
    }

    /**
     * 根据适配范围的变更, 更新数据库适配范围
     *
     * @param ruleId   加班规则id
     * @param oldScope 数据库适配范围(0: 全部, 1: 指定组织/成员)
     * @param newScope 更新适配范围(0: 全部, 1: 指定组织/成员)
     * @param dataList 更新组织/成员数据
     * @param bizType  适配范围业务类型
     * @return jnpf.model.attendance.dto.UpdateChangeDto 返回变更的组织和用户[新增, 删除]
     */
    public UpdateChangeDto updateRuleScopeList(String ruleId, Integer oldScope, Integer newScope, MutablePair<List<String>, List<String>> dataList, ScopeBizType bizType, String leaveTypeId) throws HandleException {

        // 查询已有的适配范围数据
        List<AttendanceRuleScope> oldDetails = ruleScopeService.list(
                new LambdaQueryWrapper<AttendanceRuleScope>().eq(AttendanceRuleScope::getRuleId, ruleId)
        );
        if (oldScope.equals(newScope)) {
            // 0 -> 0 无需更新 1 -> 1 判定是否需要更新
            if (newScope.equals(ConstantUtil.SCOPE_ORG_USER)) {
                Set<String> newOrgSet = new HashSet<>(dataList.getLeft());
                Set<String> newUserSet = new HashSet<>(dataList.getRight());
                // 数据库组织范围
                Set<String> oldOrgSet = oldDetails.stream()
                        .filter(d -> Objects.equals(d.getScopeType(), ConstantUtil.RULE_SCOPE_ORG))
                        .map(AttendanceRuleScope::getScopeValue)
                        .collect(Collectors.toSet());
                // 数据库成员范围
                Set<String> oldUserSet = oldDetails.stream()
                        .filter(d -> Objects.equals(d.getScopeType(), ConstantUtil.RULE_SCOPE_USER))
                        .map(AttendanceRuleScope::getScopeValue)
                        .collect(Collectors.toSet());
                // 找出要删除的
                Set<String> delOrgSet = new HashSet<>(oldOrgSet);
                delOrgSet.removeAll(newOrgSet);
                Set<String> delUserSet = new HashSet<>(oldUserSet);
                delUserSet.removeAll(newUserSet);
                // 找出要新增的
                Set<String> addOrgSet = new HashSet<>(newOrgSet);
                addOrgSet.removeAll(oldOrgSet);
                Set<String> addUserSet = new HashSet<>(newUserSet);
                addUserSet.removeAll(oldUserSet);
                // 删除
                if (!delOrgSet.isEmpty()) {
                    ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                            .eq(AttendanceRuleScope::getRuleId, ruleId)
                            .eq(AttendanceRuleScope::getScopeType, ConstantUtil.RULE_SCOPE_ORG)
                            .in(AttendanceRuleScope::getScopeValue, delOrgSet));
                }
                if (!delUserSet.isEmpty()) {
                    ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                            .eq(AttendanceRuleScope::getRuleId, ruleId)
                            .eq(AttendanceRuleScope::getScopeType, ConstantUtil.RULE_SCOPE_USER)
                            .in(AttendanceRuleScope::getScopeValue, delUserSet));
                }
                // 新增
                List<String> addOrgList = new ArrayList<>(addOrgSet);
                List<String> addUserList = new ArrayList<>(addUserSet);
                if (!addOrgList.isEmpty() || !addUserList.isEmpty()) {
                    List<AttendanceRuleScope> insertList = getRuleScopeList(ruleId, newScope, MutablePair.of(addOrgList, addUserList), bizType, leaveTypeId);
                    if (!insertList.isEmpty()) {
                        ruleScopeService.saveBatch(insertList);
                    }
                }
                UpdateChangeDto updateChange = new UpdateChangeDto();
                updateChange.getAddOrgList().addAll(addOrgList);
                updateChange.getAddUserList().addAll(addUserList);
                updateChange.getDelOrgList().addAll(delOrgSet);
                updateChange.getDelUserList().addAll(delUserSet);
                return updateChange;
            }
        } else {
            // 范围变更
            ruleScopeService.remove(new LambdaQueryWrapper<AttendanceRuleScope>()
                    .eq(AttendanceRuleScope::getRuleId, ruleId));
            if (Objects.equals(newScope, ConstantUtil.SCOPE_ALL)) {
                // 1 -> 0 删除原有记录, 生成一条全部范围的记录
                AttendanceRuleScope allScope = getRuleScope(ruleId, null, ConstantUtil.RULE_SCOPE_ALL, bizType, leaveTypeId);
                ruleScopeService.save(allScope);
            } else if (Objects.equals(newScope, ConstantUtil.SCOPE_ORG_USER)) {
                // 0 -> 1 删除原有记录, 按选择的组织和成员生成新记录
                List<AttendanceRuleScope> insertList = getRuleScopeList(ruleId, newScope, dataList, bizType, leaveTypeId);
                if (!insertList.isEmpty()) {
                    ruleScopeService.saveBatch(insertList);
                }
                UpdateChangeDto updateChange = new UpdateChangeDto();
                updateChange.getAddOrgList().addAll(dataList.getLeft());
                updateChange.getAddUserList().addAll(dataList.getRight());
                return updateChange;
            }
        }
        if (bizType.equals(ScopeBizType.OVERTIME_RULE) || bizType.equals(ScopeBizType.PUBLIC_HOLIDAY_RULE)) {
            coverRuleScope(ruleId, newScope, dataList, bizType);
        }
        return new UpdateChangeDto();
    }

    /**
     * 根据规则id查询适配范围[组织, 用户]
     * 适配范围是全部返回null
     *
     * @param ruleId  规则id
     * @param bizType 规则类型
     * @return org.apache.commons.lang3.tuple.MutablePair<java.util.List < java.lang.String>,java.util.List<java.lang.String>>
     */
    public MutablePair<List<String>, List<String>> selectScopeList(String ruleId, ScopeBizType bizType) {

        List<AttendanceRuleScope> list = ruleScopeService.list(new LambdaQueryWrapper<AttendanceRuleScope>()
                .eq(AttendanceRuleScope::getRuleId, ruleId)
                .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                .orderByDesc(AttendanceRuleScope::getLastModifyTime));
        return getList(list);
    }

    /**
     * 根据规则id集合查询适配范围
     * Map<规则id, [组织, 用户]>
     *
     * @param ruleIds 规则id集合
     * @param bizType 规则类型
     * @return java.util.Map<java.lang.String, org.apache.commons.lang3.tuple.MutablePair < java.util.List < java.lang.String>,java.util.List<java.lang.String>>>
     */
    public Map<String, MutablePair<List<String>, List<String>>> selectScopeListBatch(List<String> ruleIds, ScopeBizType bizType) {

        Map<String, MutablePair<List<String>, List<String>>> returnMap = new HashMap<>();
        List<AttendanceRuleScope> list = ruleScopeService.list(new LambdaQueryWrapper<AttendanceRuleScope>()
                .in(AttendanceRuleScope::getRuleId, ruleIds)
                .eq(AttendanceRuleScope::getBizType, bizType.getValue())
                .orderByDesc(AttendanceRuleScope::getLastModifyTime));
        ConcurrentMap<String, List<AttendanceRuleScope>> map = list.stream().collect(Collectors.groupingByConcurrent(AttendanceRuleScope::getRuleId));
        map.forEach((k, v) -> returnMap.put(k, getList(v)));
        return returnMap;
    }

    private MutablePair<List<String>, List<String>> getList(List<AttendanceRuleScope> list) {

        AttendanceRuleScope scope = list.stream().filter(v -> v.getScopeType().equals(ConstantUtil.RULE_SCOPE_ALL)).findFirst().orElse(null);
        if (null != scope) {
            return null;
        }
        List<String> orgList = new ArrayList<>();
        List<String> userList = new ArrayList<>();
        list.forEach(v -> {
            if (v.getScopeType().equals(ConstantUtil.RULE_SCOPE_ORG)) {
                orgList.add(v.getScopeValue());
            }
            if (v.getScopeType().equals(ConstantUtil.RULE_SCOPE_USER)) {
                userList.add(v.getScopeValue());
            }
        });
        return MutablePair.of(orgList, userList);
    }

    /**
     * 查询用户生效中的规则
     *
     * @param userId  用户id
     * @param bizType 业务类型
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> selectUserEffectList(String userId, ScopeBizType bizType, String tenantId) {

        UserBoundInfoVO data = null;
        ActionResult<UserBoundInfoVO> usersBoundResult = v2UserApi.getUsersBound(userId, tenantId);
        if (null == usersBoundResult || null == usersBoundResult.getData()) {
            FtbDepUserDTO dto = new FtbDepUserDTO();
            dto.setUserIds(List.of(userId));
            dto.setTenantId(tenantId);
            List<UserBoundVO> person = ftbPersonnelsTurnoverManagementService.getInformationAboutTheDepartingPerson(dto);
            if (null != person && !person.isEmpty()) {
                data = new UserBoundInfoVO();
                data.setUserId(person.get(0).getId());
                data.setOrganizeId(person.get(0).getOrganizeId());
            }
        } else {
            data = usersBoundResult.getData();
        }
        if (null == data) {
            return List.of();
        }
        return ruleScopeService.selectUserEffectList(data.getUserId(), data.getOrganizeId(), bizType);
    }
    public List<AttendanceRuleScope> selectUserEffectList(String userId, String orgId, ScopeBizType bizType) {
        return ruleScopeService.selectUserEffectList(userId, orgId, bizType);
    }
    /**
     * 查询用户生效中的规则[批量]
     *
     * @param userIds  用户id集合
     * @param bizType  业务类型
     * @param priority 使用优先级(1: 是, 0: 否)
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> selectUserEffectListBatch(List<String> userIds, ScopeBizType bizType, Integer priority) {
        return selectUserEffectListBatch(userIds, bizType, priority, null, null);
    }
    /**
     * 查询用户生效中的规则[批量]
     *
     * @param userIds  用户id集合
     * @param bizType  业务类型
     * @param priority 使用优先级(1: 是, 0: 否)
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> selectUserEffectListBatch2(List<String> userIds, ScopeBizType bizType, Integer priority,String tenantId) {
        return selectUserEffectListBatch(userIds, bizType, priority, null,tenantId);
    }
    public List<AttendanceRuleScope> selectUserEffectListBatch(List<String> userIds, ScopeBizType bizType, Integer priority, List<String> leaveTypeIds) {
        return selectUserEffectListBatch(userIds, bizType, priority, leaveTypeIds, null);
    }
    /**
     * 查询用户生效中的规则[批量]
     *
     * @param userIds  用户id集合
     * @param bizType  业务类型
     * @param priority 使用优先级(1: 是, 0: 否)
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> selectUserEffectListBatch(List<String> userIds, ScopeBizType bizType, Integer priority, List<String> leaveTypeIds,String tenantId) {

        ActionResult<List<UserBoundVO>> batchResult = v2UserApi.getAllUserInfoBatch(userIds, Objects.requireNonNullElse(tenantId, UserProvider.getUser().getTenantId()));
        if (null == batchResult || null == batchResult.getData()) {
            return List.of();
        }
        List<UserBoundVO> data = batchResult.getData();
        List<UserOrgDto> userOrgList = new ArrayList<>();
        data.forEach(v -> userOrgList.add(new UserOrgDto(v.getId(), v.getOrganizeId())));
        // 分批查询
        List<List<UserOrgDto>> partition = Lists.partition(userOrgList, 200);
        List<AttendanceRuleScope> scopeList = new ArrayList<>();
        for (List<UserOrgDto> subList : partition) {
            List<AttendanceRuleScope> partResult = ruleScopeService.selectUserEffectListBatch(
                    subList, bizType, priority, leaveTypeIds
            );
            if (partResult != null && !partResult.isEmpty()) {
                scopeList.addAll(partResult);
            }
        }
        return scopeList;
    }

    /**
     * 查询组织生效中假期的规则[批量]
     *
     * @param oldOrganizeId 上级组织id
     * @return java.util.List<jnpf.entity.attendance.AttendanceRuleScope>
     */
    public List<AttendanceRuleScope> selectOrgEffectListBatch(String oldOrganizeId) {
        return ruleScopeService.selectOrgEffectListBatch(oldOrganizeId);
    }
}
