package com.njcn.rdms.module.project.framework.security.service;

import cn.hutool.core.util.StrUtil;
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.module.project.constant.ObjectRoleConstants;
import com.njcn.rdms.module.project.constant.ProjectObjectConstants;
import com.njcn.rdms.module.project.dal.dataobject.member.UserObjectRoleDO;
import com.njcn.rdms.module.project.dal.mysql.member.UserObjectRoleMapper;
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
import com.njcn.rdms.module.system.api.permission.ObjectPermissionApi;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;

/**
 * 项目对象权限服务。
 */
@Slf4j
@Service
public class ProjectObjectPermissionService implements ObjectPermissionService {

    @Resource
    private UserObjectRoleMapper userObjectRoleMapper;
    @Resource
    private ObjectPermissionApi objectPermissionApi;

    @Override
    public String getObjectType() {
        return ProjectObjectConstants.OBJECT_TYPE;
    }

    @Override
    public void checkPermission(Long objectId, String permission, boolean memberOnly) {
        if (objectId == null) {
            throw invalidParamException("对象编号不能为空");
        }
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        // 多角色支持：拿 user 在对象内全部 ACTIVE 角色行
        List<UserObjectRoleDO> userRoles = userObjectRoleMapper
                .selectActiveListByObjectAndUserId(ProjectObjectConstants.OBJECT_TYPE, objectId, loginUserId);
        if (userRoles.isEmpty()) {
            throw exception(ErrorCodeConstants.PROJECT_OBJECT_PERMISSION_DENIED,
                    buildDeniedPermission(permission, memberOnly));
        }
        if (memberOnly) {
            return;
        }
        String normalizedPermission = normalizePermission(permission);
        // 任一角色含该权限码即放行（等价于多角色 union；短路求值）
        boolean allowed = userRoles.stream()
                .map(UserObjectRoleDO::getRoleId)
                .distinct()
                .anyMatch(roleId -> getRolePermissions(roleId).contains(normalizedPermission));
        if (!allowed) {
            throw exception(ErrorCodeConstants.PROJECT_OBJECT_PERMISSION_DENIED, normalizedPermission);
        }
    }

    @Override
    public boolean hasPermission(Long objectId, String permission) {
        if (objectId == null || StrUtil.isBlank(permission)) {
            return false;
        }
        Long userId = SecurityFrameworkUtils.getLoginUserId();
        if (userId == null) {
            return false;
        }
        try {
            // 先确认是对象成员，非成员直接返回 false
            List<UserObjectRoleDO> userRoles = userObjectRoleMapper
                    .selectActiveListByObjectAndUserId(ProjectObjectConstants.OBJECT_TYPE, objectId, userId);
            if (userRoles.isEmpty()) {
                return false;
            }
            String normalizedPermission = permission.trim();
            return userRoles.stream()
                    .map(UserObjectRoleDO::getRoleId)
                    .distinct()
                    .anyMatch(roleId -> getRolePermissions(roleId).contains(normalizedPermission));
        } catch (Exception e) {
            log.warn("[hasPermission] objectId={}, permission={} 查询权限失败", objectId, permission, e);
            return false;
        }
    }

    private Set<String> getRolePermissions(Long roleId) {
        Set<String> permissions = objectPermissionApi
                .getObjectRolePermissions(roleId, ObjectRoleConstants.ROLE_SCOPE_OBJECT, ProjectObjectConstants.OBJECT_TYPE)
                .getCheckedData();
        if (permissions == null || permissions.isEmpty()) {
            return Collections.emptySet();
        }
        return permissions.stream()
                .filter(StringUtils::hasText)
                .map(String::trim)
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    private String normalizePermission(String permission) {
        if (!StringUtils.hasText(permission)) {
            throw invalidParamException("对象权限码不能为空");
        }
        return permission.trim();
    }

    private String buildDeniedPermission(String permission, boolean memberOnly) {
        return memberOnly ? "member" : normalizePermission(permission);
    }

}
