<?php

declare(strict_types=1);

namespace App\Module\Core\Infrastructure\ApiPlatform\Extension;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\Operation;
use App\Module\Core\Domain\Entity\User;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\SecurityBundle\Security;

use function array_key_exists;

/**
 * Hides archived (soft-deleted) users from the `/users` collection so they are
 * no longer offered as assignees/collaborators, while existing references to
 * them (already stored on tasks, time entries…) keep resolving normally.
 *
 * An admin can opt back in to see archived users — e.g. to restore one — by
 * passing the `archived` query filter explicitly (`?archived=true`), in which
 * case the BooleanFilter declared on User handles the predicate instead.
 */
final readonly class ExcludeArchivedUserExtension implements QueryCollectionExtensionInterface
{
    public function __construct(private Security $security) {}

    public function applyToCollection(
        QueryBuilder $queryBuilder,
        QueryNameGeneratorInterface $queryNameGenerator,
        string $resourceClass,
        ?Operation $operation = null,
        array $context = [],
    ): void {
        if (User::class !== $resourceClass) {
            return;
        }

        // Let an admin explicitly query archived users via ?archived=...
        $filters = $context['filters'] ?? [];
        if (array_key_exists('archived', $filters) && $this->security->isGranted('ROLE_ADMIN')) {
            return;
        }

        $alias = $queryBuilder->getRootAliases()[0];
        $queryBuilder->andWhere(sprintf('%s.archived = false', $alias));
    }
}
