<?php

declare(strict_types=1);

namespace NoahVet\Reef\Factory\RequestContext;

use NoahVet\Reef\Bridge\Reef\IAM\Client\ClientAdapter;
use NoahVet\Reef\Domain\Tool\ArrayTool;
use NoahVet\Reef\Security\IAM\Model\ResourceType;
use NoahVet\Reef\Security\ResourceType\ResourceCollectionPermissionFetcherInterface;
use Symfony\Component\HttpFoundation\Request;

class PermissionApplier extends AbstractApplier implements PermissionApplierInterface
{
    public function __construct(
        private readonly ClientAdapter $clientAdapter,
        private readonly ResourceCollectionPermissionFetcherInterface $resourceCollectionPermissionFetcher,
        private readonly string $reefAppName,
    ) {
    }

    public function apply(Request $request, array $whitelist): array
    {
        $permissions = [];

        if (!isset($whitelist['permissions'])) {
            return [];
        }

        foreach ($whitelist['permissions'] as $context) {
            // Fetch IAM Authorization List
            $iamPermissions = $this->resourceCollectionPermissionFetcher->fetch(
                ResourceType::fromString(
                    (!\str_contains($context['resourceName'], ':') ? $this->reefAppName.':' : '').$context['resourceName'],
                ),
                true,
                $this->clientAdapter->getToken()->getBearerToken(),
            );

            // Get global permission
            $iamAllPermissions = $iamPermissions->getAllPermissions();

            // Get specific permissions, by resource 'id'
            $iamResourcePermissions = $iamPermissions->getResourcePermissions();

            $permissionSlugs = \is_array($context['permissionSlug']) ? $context['permissionSlug'] : [$context['permissionSlug']];

            /** @var array<string, list<string>|null> $resourceLists */
            $resourceLists = [];

            foreach ($permissionSlugs as $permissionSlug) {
                // If you don't have all permissions on this resource type
                if (\in_array($permissionSlug, $iamAllPermissions)) {
                    // Allow all resources (null value)
                    $resourceLists[$permissionSlug] = null;
                } else {
                    // List specific resources with all permissions (can be no resources = empty array)
                    $resourceLists[$permissionSlug] = ArrayTool::removeDuplicateValues(
                        \array_keys(
                            \array_filter(
                                $iamResourcePermissions,
                                fn (array $permList): bool => \in_array($permissionSlug, $permList),
                            ),
                        ),
                    );
                }
            }

            /** @var list<list<string>> $resourceLists */
            $resourceLists = \array_filter(\array_values($resourceLists), fn ($resourceList) => null !== $resourceList);

            /* @var array<string, list<string>> $permissions Keep only resources with all permissions */
            $permissions[$context['mappedKey']] = empty($resourceLists) ? null : \array_intersect(...$resourceLists);
        }

        return $permissions;
    }
}
