<?php

declare(strict_types=1);

namespace KupShop\GraphQLBundle\ApiAdmin\Util;

use KupShop\GraphQLBundle\ApiAdmin\Types\Collection\SaleCollection;
use KupShop\GraphQLBundle\ApiAdmin\Types\Parameters;
use KupShop\GraphQLBundle\ApiAdmin\Types\Sale\Input\SaleFilterInput;
use KupShop\GraphQLBundle\ApiAdmin\Types\Sale\Sale;
use KupShop\GraphQLBundle\ApiShared\ApiUtil;
use KupShop\GraphQLBundle\ApiShared\Types\Enums\SortEnum;
use KupShop\GraphQLBundle\Exception\GraphQLNotFoundException;
use KupShop\SalesBundle\SaleList\SaleList;
use KupShop\SalesBundle\Util\SalesUtil;
use Query\Operator;

readonly class SaleUtil
{
    public function __construct(
        private ?SalesUtil $salesUtil,
        private ?SaleList $saleList,
    ) {
    }

    public function getSale(int $id): Sale
    {
        if (!($sale = $this->salesUtil->getSale($id))) {
            throw new GraphQLNotFoundException('Sale not found!');
        }

        $sales = $this->saleList->getSales($totalCount);

        return new Sale($sale, $sales);
    }

    public function getSales(?int $offset, int $limit, ?Parameters $sort, ?SaleFilterInput $filter, bool $fetchItems = false): SaleCollection
    {
        $saleList = (clone $this->saleList)
            ->limit(ApiUtil::getLimit($limit), $offset);

        if ($filter?->id) {
            $saleList->andSpec(Operator::inIntArray($filter->id, 's.id'));
        }

        if ($filter?->code) {
            $saleList->andSpec(Operator::inIntArray($filter->code, 's.code'));
        }

        if ($filter?->dateCreated) {
            $saleList->andSpec(ApiUtil::getDateTimeFilter($filter->dateCreated, 's.date_created'));
        }

        if ($fetchItems) {
            $saleList->fetchItems();
        }

        if ($sort) {
            /** @var SortEnum $value */
            foreach (array_filter($sort->getData()) as $field => $value) {
                $saleList->orderBy("s.{$field}", $value->value);
            }
        }

        return (new SaleCollection($saleList->getSales($totalCount)))
            ->setItemsTotalCount($totalCount)
            ->setLimit($limit)
            ->setOffset($offset);
    }
}
