<?php declare(strict_types=1);

namespace Shop\Presentation\Controllers;

use League\Fractal\Manager;
use League\Fractal\Resource\Collection;
use Core\Application\Loader;
use Diamond\Application\Content\Exceptions\PageNotFoundException;
use League\Fractal\Resource\Item;
use Shop\Presentation\Transformers\CatalogTransformer;
use Shop\Presentation\Transformers\CategoryTransformer;
use Shop\Infrastructure\Repositories\Catalog\CatalogCriteria;
use Shop\Infrastructure\Repositories\Catalog\CatalogRepository;
use Shop\Infrastructure\Repositories\ProductCategory\ProductCategoryCriteria;
use Shop\Infrastructure\Repositories\ProductCategory\ProductCategoryRepository;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

class CatalogController extends RestController
{
    use ClientApiKeyTrait;

    public function __construct(protected CatalogRepository         $catalogRepository,
                                protected ProductCategoryRepository $productCategoryRepository,
                                protected Manager                   $manager)
    {
    }


    /**
     * @return JsonResponse
     * @throws \ReflectionException
     */
    public function list(): JsonResponse
    {
        $this->validateToken();

        $criteria = CatalogCriteria::create();

        $items = $this->catalogRepository->findByCriteria($criteria);

        $data = $this->manager->createData(
            (new Collection($items, new CatalogTransformer()))->setMetaValue('total', $this->catalogRepository->count($criteria))
        );

        return $this->buildJsonResponse($data->toArray());
    }

    /**
     * @param array $args
     * @return JsonResponse
     */
    public function show(array $args): JsonResponse
    {
        $this->validateToken();

        $id = $args['id'] ?? null;

        if (!$item = $this->catalogRepository->findById((int)$id)) {
            return $this->buildPageNotFound('catalog not found by id');
        }

        $data = $this->manager->createData((new Item($item, new CatalogTransformer())))->toArray();

        return $this->buildJsonResponse($data);
    }

    public function listCategories(array $args): JsonResponse
    {
        $this->validateToken();

        $id = $args['id'] ?? null;

        if (!$item = $this->catalogRepository->findById((int)$id)) {
            return $this->buildPageNotFound('catalog not found by id');
        }

        $criteria = ProductCategoryCriteria::create()->setFilterByCatalogId($item->getId());

        $items = $this->productCategoryRepository->findByCriteria($criteria);

        $data = $this->manager->createData(
            (new Collection($items, new CategoryTransformer()))->setMetaValue('total', $this->productCategoryRepository->count($criteria))
        );

        return $this->buildJsonResponse($data->toArray());
    }

    public function showCategory(array $args): JsonResponse
    {
        $this->validateToken();

        $id = $args['id'] ?? null;

        $categoryId = $args['category_id'] ?? null;

        if (!$category = $this->productCategoryRepository->findByCriteria(
            ProductCategoryCriteria::create()->setFilterByCatalogId((int)$id)->setFilterById((int)$categoryId)
        )->current()) {
            return $this->buildPageNotFound('category not found by id ' . $categoryId);
        }

        $data = $this->manager->createData((new Item($category, new CategoryTransformer())))->toArray();

        return $this->buildJsonResponse($data);
    }
}