<?php

declare(strict_types=1);

namespace KupShop\GraphQLBundle\ApiAdmin\Util\Catalog;

use KupShop\GraphQLBundle\ApiAdmin\Types\Catalog\PriceList\Input\PriceListInput;
use KupShop\GraphQLBundle\ApiAdmin\Types\Catalog\PriceList\Response\PriceListMutateResponse;
use KupShop\GraphQLBundle\ApiAdmin\Types\Collection\PriceListCollection;
use KupShop\GraphQLBundle\ApiShared\ApiUtil;
use KupShop\GraphQLBundle\ApiShared\Types\PriceList\PriceList;
use KupShop\GraphQLBundle\Exception\GraphQLDuplicatedException;
use KupShop\GraphQLBundle\Exception\GraphQLNotFoundException;
use KupShop\GraphQLBundle\Exception\GraphQLValidationException;
use KupShop\PricelistBundle\Util\PriceListWorker;
use Query\Operator;

class PriceListUtil
{
    private ?PriceListWorker $priceListWorker;

    public function __construct(?PriceListWorker $priceListWorker)
    {
        $this->priceListWorker = $priceListWorker;
    }

    public function getPriceLists(): PriceListCollection
    {
        $priceLists = $this->priceListWorker ? $this->priceListWorker->getPriceLists() : [];

        return (new PriceListCollection(
            ApiUtil::wrapItems(
                $priceLists,
                PriceList::class
            )
        ))->setItemsTotalCount(count($priceLists));
    }

    public function getPriceList(int $id): PriceList
    {
        if ($this->priceListWorker && ($priceList = $this->priceListWorker->getPriceList($id))) {
            return new PriceList($priceList);
        }

        throw new GraphQLNotFoundException('PriceList not found');
    }

    public function createPriceList(PriceListInput $input): PriceListMutateResponse
    {
        if (empty($input->name)) {
            throw new GraphQLValidationException('Parameter "name" is required when creating PriceList!');
        }

        $priceListExists = sqlQueryBuilder()
            ->select('id')
            ->from('pricelists')
            ->where(Operator::equals(['name' => $input->name]))
            ->execute()->fetchOne();

        if ($priceListExists) {
            throw new GraphQLDuplicatedException(
                sprintf('PriceList with name "%s" already exists!', $input->name)
            );
        }

        $currencyExists = sqlQueryBuilder()
            ->select('id')
            ->from('currencies')
            ->where(Operator::equals(['id' => $input->currency]))
            ->execute()->fetchOne();

        if (!$currencyExists) {
            throw new GraphQLValidationException(
                sprintf('Currency "%s" does not exists!', $input->currency)
            );
        }

        $priceList = sqlGetConnection()->transactional(function () use ($input) {
            sqlQueryBuilder()
                ->insert('pricelists')
                ->directValues(
                    [
                        'name' => $input->name,
                        'currency' => $input->currency,
                    ]
                )->execute();

            $priceListId = (int) sqlInsertId();

            return $this->getPriceList($priceListId);
        });

        return new PriceListMutateResponse(true, $priceList);
    }
}
