<?php

namespace App\State\Provider;

use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Put;
use ApiPlatform\State\Pagination\TraversablePaginator;
use ApiPlatform\State\ProviderInterface;
use App\Dto\Input\ClientInput;
use App\Dto\Output\ClientOutput;
use App\Repository\ClientRepository;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

readonly class ClientProvider implements ProviderInterface
{
    public function __construct(
        private ClientRepository $clientRepository,
        private ProviderInterface $collectionProvider,
        private ProviderInterface $itemProvider
    )
    {
    }

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        switch ($operation){
            case $operation instanceof GetCollection:
                return $this->provideCollection($operation, $uriVariables, $context);
            case $operation instanceof Patch:
            case $operation instanceof Put:
                return $this->provideInput($operation, $uriVariables, $context);
            case $operation instanceof Get:
                return $this->provideItem($operation, $uriVariables, $context);
        }
    }

    public function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
    {
        $filters = $context['filters'] ?? [];

        if (isset($filters['organizationalUnit.id'])) {
            $organizationalUnitId = (int) $filters['organizationalUnit.id'];

            $totalClients = $this->clientRepository->countClientsByOrganizationalUnitAndDescendants($organizationalUnitId, $filters);
            $clients = $this->clientRepository->findClientsByOrganizationalUnitAndDescendants($organizationalUnitId, $filters);

            $items = new \ArrayObject();
            foreach ($clients as $client) {
                $items[] = new ClientOutput($client);
            }

            return new TraversablePaginator($items, $filters['page'] ?? 1, $filters['itemsPerPage'] ?? count($clients), $totalClients);
        } else {
            $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);

            $items = new \ArrayObject();
            foreach ($paginator->getIterator() as $item) {
                $items[] = new ClientOutput($item);
            }

            return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
        }
    }




    public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        $item = $this->itemProvider->provide($operation, $uriVariables, $context);

        if (!$item) {
            throw new NotFoundHttpException('Client not found');
        }

        return new ClientOutput($item);
    }

    public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        if (isset($uriVariables['uuid'])) {
            $item = $this->itemProvider->provide($operation, $uriVariables, $context);

            return $item !== null ? new ClientInput($item) : null;
        }

        return new ClientInput();
    }
}
