package com.njcn.rdms.module.project.service.team;

import com.njcn.rdms.framework.common.pojo.CommonResult;
import com.njcn.rdms.framework.security.core.service.SecurityFrameworkService;
import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils;
import com.njcn.rdms.module.project.enums.ErrorCodeConstants;
import com.njcn.rdms.module.system.api.user.AdminUserApi;
import com.njcn.rdms.module.system.api.user.UserManagementRelationApi;
import com.njcn.rdms.module.system.api.user.dto.AdminUserRespDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

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

@Service
public class TeamDashboardAccessServiceImpl implements TeamDashboardAccessService {

    @Resource
    private UserManagementRelationApi userManagementRelationApi;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private SecurityFrameworkService securityFrameworkService;

    @Override
    public void validateTeamDashboardPermission(String permission) {
        if (!securityFrameworkService.hasPermission(permission)) {
            throw exception(ErrorCodeConstants.TEAM_DASHBOARD_PERMISSION_REQUIRED);
        }
    }

    @Override
    public List<Long> getAllSubordinateUserIds() {
        return new ArrayList<>(getSubordinateUserIdSet());
    }

    @Override
    public List<Long> resolveRequestedSubordinateUserIds(Collection<Long> candidateUserIds, String permission) {
        validateTeamDashboardPermission(permission);
        Set<Long> allSubordinates = getSubordinateUserIdSet();
        if (allSubordinates.isEmpty()) {
            return Collections.emptyList();
        }
        if (candidateUserIds == null || candidateUserIds.isEmpty()) {
            return new ArrayList<>(allSubordinates);
        }
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        LinkedHashSet<Long> resolved = new LinkedHashSet<>();
        for (Long candidateUserId : candidateUserIds) {
            if (candidateUserId == null || Objects.equals(candidateUserId, loginUserId)) {
                continue;
            }
            if (!allSubordinates.contains(candidateUserId)) {
                throw exception(ErrorCodeConstants.TEAM_DASHBOARD_SUBORDINATE_SCOPE_INVALID);
            }
            resolved.add(candidateUserId);
        }
        return new ArrayList<>(resolved);
    }

    @Override
    public boolean canReadSubordinateUser(Long userId, String permission) {
        if (userId == null) {
            return false;
        }
        if (!securityFrameworkService.hasPermission(permission)) {
            return false;
        }
        return getSubordinateUserIdSet().contains(userId);
    }

    @Override
    public Set<Long> getSubordinateUserIdSet() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        if (loginUserId == null) {
            return Collections.emptySet();
        }
        CommonResult<Set<Long>> result = userManagementRelationApi.getAllSubordinateUserIds(loginUserId);
        Set<Long> rawIds = result == null || result.getCheckedData() == null
                ? Collections.emptySet()
                : result.getCheckedData();
        if (rawIds.isEmpty()) {
            return Collections.emptySet();
        }
        LinkedHashSet<Long> uniqueIds = new LinkedHashSet<>(rawIds);
        uniqueIds.remove(loginUserId);
        if (uniqueIds.isEmpty()) {
            return Collections.emptySet();
        }
        CommonResult<List<AdminUserRespDTO>> userResult = adminUserApi.getUserList(uniqueIds);
        List<AdminUserRespDTO> users = userResult == null || userResult.getCheckedData() == null
                ? Collections.emptyList()
                : userResult.getCheckedData();
        LinkedHashSet<Long> availableIds = new LinkedHashSet<>();
        for (AdminUserRespDTO user : users) {
            if (user == null || user.getId() == null || !Objects.equals(user.getStatus(), 0)) {
                continue;
            }
            availableIds.add(user.getId());
        }
        return availableIds;
    }
}
