<?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\CommandInput;
use App\Dto\Output\CommandOutput;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

readonly class CommandProvider implements ProviderInterface
{
    public function __construct(
        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);
        }
    }

    private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
    {
        $paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);

        $items = new \ArrayObject();
        foreach ($paginator->getIterator() as $item){
            $items[] = new CommandOutput($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('Command not found');
        }

        return new CommandOutput($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 CommandInput($item) : null;
        }

        return new CommandInput();
    }
}
