<?php

declare(strict_types=1);

namespace KupShop\ReturnsBundle\ReturnList;

use KupShop\KupShopBundle\CollectionList;
use KupShop\KupShopBundle\Context\CurrencyContext;
use KupShop\KupShopBundle\Util\Contexts;
use KupShop\KupShopBundle\Util\Price\Price;
use KupShop\ReturnsBundle\Entity\ReturnEntity;
use KupShop\ReturnsBundle\Query\Returns;
use KupShop\ReturnsBundle\Util\ReturnsUtil;

/**
 * @method ReturnCollection getCollection(int &$totalCount = null)
 */
class ReturnList extends CollectionList
{
    protected static string $collectionClass = ReturnCollection::class;

    public function __construct(
        private readonly ReturnsUtil $returnsUtil,
        private readonly MultiFetch $multiFetch,
    ) {
    }

    public function fetchItems(): self
    {
        $this->addResultModifiers(fn (ReturnCollection $returns) => $this->multiFetch->fetchItems($returns));

        return $this;
    }

    public function fetchReplacements(): self
    {
        $this->addResultModifiers(fn (ReturnCollection $returns) => $this->multiFetch->fetchReplacements($returns));

        return $this;
    }

    protected function createItem(array $item): mixed
    {
        $currency = Contexts::get(CurrencyContext::class)->getOrDefault($item['currency']);

        $delivery = array_filter($item, fn ($k) => in_array($k, $this->returnsUtil->getAddressFields()), ARRAY_FILTER_USE_KEY);

        return (new ReturnEntity())
            ->setId($item['id'])
            ->setIdLanguage($item['id_language'])
            ->setIdCurrency($item['currency'])
            ->setCurrency($currency)
            ->setCode($item['code'])
            ->setBankAccount($item['bank_account'])
            ->setDateCreated($item['date_created'])
            ->setDateAccepted($item['date_accepted'])
            ->setDateHandle($item['date_handle'])
            ->setEmail($item['email'])
            ->setAddress($delivery)
            ->setDeliveryCountry($item['country'])
            ->setStatus($item['status'])
            ->setStatusName($this->returnsUtil->getStatuses()[$item['status']] ?? '')
            ->setFlags(explodeFlags($item['flags']))
            ->setHistory(
                $this->createHistory($item)
            )
            ->setReturnDelivery(json_decode($item['data'] ?: '', true)['return_delivery'] ?? false)
            ->setIsClosed(in_array($item['status'], $this->returnsUtil->getHandleStatuses()))
            ->setIdOrder($item['id_order'])
            ->setIdReturnDelivery($item['id_return_delivery'])
            ->setIdReplacementDeliveryType($item['id_replacement_delivery_type'])
            ->setReturnDeliveryPrice(new Price(toDecimal($item['return_delivery'])->removeVat(getVat()), $currency, getVat()))
            ->setReplacementDeliveryPrice(new Price(toDecimal($item['replacement_delivery'])->removeVat(getVat()), $currency, getVat()))
            // Tady to je blbe, nelze odebirat jednotne dph z cele objednavky, ale neni cas to predelavat
            ->setTotalPrice(new Price(toDecimal($item['total_price'])->removeVat(getVat()), $currency, getVat()))
            ->setIdAdmin($item['id_admin']);
    }

    protected function createQueryBuilder(): \Query\QueryBuilder
    {
        return sqlQueryBuilder()
            ->select('r.*, o.id_language, o.currency, o.invoice_email as email, o.delivery_country as country')
            ->from('returns', 'r')
            ->andWhere(Returns::joinOrders())
            ->groupBy('r.id');
    }

    private function createHistory(array $item): array
    {
        static $admins;

        if ($admins === null) {
            $admins = sqlQueryBuilder()
                ->select('id, login')
                ->from('admins')
                ->execute()->fetchAllKeyValue();
        }

        $history = json_decode($item['history'] ?: '', true) ?: [];

        foreach ($history as $h) {
            $h['status_name'] = $this->returnsUtil->getStatuses()[$h['status']] ?? null;
            $h['admin_name'] = $admins[$h['admin']]['login'] ?? null;
        }

        return $history;
    }
}
