package com.mosquito.project.permission;

import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 权限判断服务 - 核心权限验证逻辑
 */
@Service
public class PermissionCheckService {

    private final RoleRepository roleRepository;
    private final PermissionRepository permissionRepository;
    private final UserRoleRepository userRoleRepository;
    private final RolePermissionRepository rolePermissionRepository;

    public PermissionCheckService(RoleRepository roleRepository,
                                  PermissionRepository permissionRepository,
                                  UserRoleRepository userRoleRepository,
                                  RolePermissionRepository rolePermissionRepository) {
        this.roleRepository = roleRepository;
        this.permissionRepository = permissionRepository;
        this.userRoleRepository = userRoleRepository;
        this.rolePermissionRepository = rolePermissionRepository;
    }

    /**
     * 检查用户是否拥有指定权限
     */
    public boolean hasPermission(Long userId, String permissionCode) {
        // 获取用户所有角色
        Set<String> userRoles = getUserRoleCodes(userId);
        if (userRoles.isEmpty()) {
            return false;
        }

        // 检查角色是否拥有该权限
        return userRoles.stream()
                .anyMatch(roleCode -> roleHasPermission(roleCode, permissionCode));
    }

    /**
     * 检查用户是否拥有指定角色
     */
    public boolean hasRole(Long userId, String roleCode) {
        Set<String> userRoles = getUserRoleCodes(userId);
        return userRoles.contains(roleCode);
    }

    /**
     * 获取用户所有权限代码
     */
    public Set<String> getUserPermissions(Long userId) {
        Set<String> userRoles = getUserRoleCodes(userId);
        if (userRoles.isEmpty()) {
            return Set.of();
        }

        // 获取所有角色对应的权限
        return userRoles.stream()
                .flatMap(roleCode -> getRolePermissions(roleCode).stream())
                .collect(Collectors.toSet());
    }

    /**
     * 获取用户数据权限范围
     */
    public String getUserDataScope(Long userId) {
        Set<String> userRoles = getUserRoleCodes(userId);
        if (userRoles.isEmpty()) {
            return "OWN"; // 默认个人权限
        }

        // 返回最高级别的数据权限
        if (userRoles.contains("super_admin") || userRoles.contains("system_admin")) {
            return "ALL";
        }
        if (userRoles.contains("auditor")) {
            return "ALL";
        }
        return "DEPARTMENT";
    }

    /**
     * 获取用户角色代码列表
     */
    private Set<String> getUserRoleCodes(Long userId) {
        // 1. 获取用户所有角色ID
        List<Long> roleIds = userRoleRepository.findRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return Set.of();
        }

        // 2. 根据角色ID获取角色代码
        return roleIds.stream()
                .map(roleId -> roleRepository.findById(roleId))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .map(SysRole::getRoleCode)
                .collect(Collectors.toSet());
    }

    /**
     * 检查角色是否拥有指定权限
     */
    private boolean roleHasPermission(String roleCode, String permissionCode) {
        Set<String> permissions = getRolePermissions(roleCode);
        return permissions.contains(permissionCode);
    }

    /**
     * 获取角色的所有权限
     */
    private Set<String> getRolePermissions(String roleCode) {
        // 1. 根据角色代码获取角色ID
        List<Long> roleIds = rolePermissionRepository.findRoleIdsByRoleCode(roleCode);
        if (roleIds.isEmpty()) {
            return Set.of();
        }

        // 2. 获取角色所有权限ID
        Long roleId = roleIds.get(0);
        List<Long> permissionIds = rolePermissionRepository.findPermissionIdsByRoleId(roleId);
        if (permissionIds.isEmpty()) {
            return Set.of();
        }

        // 3. 根据权限ID获取权限代码
        return permissionIds.stream()
                .map(permId -> permissionRepository.findById(permId))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .map(SysPermission::getPermissionCode)
                .collect(Collectors.toSet());
    }
}
