package com.njcn.rdms.module.project.dal.mysql.member;

import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
import com.njcn.rdms.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
import org.apache.ibatis.annotations.Mapper;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

@Mapper
public interface UserObjectRoleMapper extends BaseMapperX<UserObjectRoleDO> {

    default List<UserObjectRoleDO> selectListByObject(String objectType, Long objectId) {
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .orderByAsc(UserObjectRoleDO::getStatus)
                .orderByAsc(UserObjectRoleDO::getJoinedTime)
                .orderByAsc(UserObjectRoleDO::getId));
    }

    default UserObjectRoleDO selectByObjectAndUserId(String objectType, Long objectId, Long userId) {
        return selectOne(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .eq(UserObjectRoleDO::getUserId, userId));
    }

    default UserObjectRoleDO selectByIdAndObject(Long id, String objectType, Long objectId) {
        return selectOne(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getId, id)
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId));
    }

    default UserObjectRoleDO selectActiveByObjectAndUserId(String objectType, Long objectId, Long userId) {
        return selectOne(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .eq(UserObjectRoleDO::getUserId, userId)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    /**
     * multi-role：拿 user 在某对象内全部 ACTIVE 角色行（含 manager + creator + watcher 等所有显式角色）。
     * 用于对象域鉴权（ProductObjectPermissionService / ProjectObjectPermissionService 的 anyMatch 权限聚合）
     * 与 Context 主角色挑选（按 sort 升序排，主角色 + additionalRoleNames）。
     */
    default List<UserObjectRoleDO> selectActiveListByObjectAndUserId(String objectType, Long objectId, Long userId) {
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .eq(UserObjectRoleDO::getUserId, userId)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    default List<UserObjectRoleDO> selectListByIdsAndObject(List<Long> ids, String objectType, Long objectId) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .in(UserObjectRoleDO::getId, ids)
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId));
    }

    default List<UserObjectRoleDO> selectActiveListByObjectTypeAndUserId(String objectType, Long userId) {
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getUserId, userId)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    /**
     * multi-role 唯一索引精确命中：按 (object_type, object_id, user_id, role_id) 单查任一记录。
     * 不带 status —— ACTIVE / INACTIVE 都要返回，用于 insertOrReactivate / pre-check 撞索引场景。
     */
    default UserObjectRoleDO selectByObjectUserAndRole(String objectType, Long objectId, Long userId, Long roleId) {
        return selectOne(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .eq(UserObjectRoleDO::getUserId, userId)
                .eq(UserObjectRoleDO::getRoleId, roleId));
    }

    /**
     * 同 {@link #selectByObjectUserAndRole}，但仅返回 ACTIVE 行（status=0）。
     * 用于 manager 转岗：按 (user, object, manager_role_id) 三元组定位 manager ACTIVE 行后改 role_id 降级。
     */
    default UserObjectRoleDO selectActiveByObjectUserAndRole(String objectType, Long objectId, Long userId, Long roleId) {
        return selectOne(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getObjectId, objectId)
                .eq(UserObjectRoleDO::getUserId, userId)
                .eq(UserObjectRoleDO::getRoleId, roleId)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    /**
     * 通道 2 用：批量按 userIds 反查指定 objectType 下的活跃记录（status=0），用于"组织负责人 → 下属参与的对象"反推。
     */
    default List<UserObjectRoleDO> selectListByUserIdsAndObjectType(Collection<Long> userIds, String objectType) {
        if (userIds == null || userIds.isEmpty()) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .in(UserObjectRoleDO::getUserId, userIds)
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    /**
     * 工作台「我负责的项目」：批量查一批对象下的活跃成员角色行（status=0）。
     * 一次拿全，内存按 objectId 分组，避免逐项目 N+1。
     */
    default List<UserObjectRoleDO> selectActiveListByObjectTypeAndObjectIds(String objectType, Collection<Long> objectIds) {
        if (objectIds == null || objectIds.isEmpty()) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .in(UserObjectRoleDO::getObjectId, objectIds)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

    /**
     * 顶层列表「当前登录用户角色」用：查某用户在一批指定对象上的活跃角色行（status=0）。
     * 三条件精确命中，结果集只回当前页对象、与分页规模解耦，内存按 objectId 分组即可，无 N+1。
     */
    default List<UserObjectRoleDO> selectActiveListByObjectTypeAndUserIdAndObjectIds(
            String objectType, Long userId, Collection<Long> objectIds) {
        if (objectIds == null || objectIds.isEmpty()) {
            return Collections.emptyList();
        }
        return selectList(new LambdaQueryWrapperX<UserObjectRoleDO>()
                .eq(UserObjectRoleDO::getObjectType, objectType)
                .eq(UserObjectRoleDO::getUserId, userId)
                .in(UserObjectRoleDO::getObjectId, objectIds)
                .eq(UserObjectRoleDO::getStatus, 0));
    }

}
