<?php

namespace Myvetshop\Module\Clinique\Accounting\Export\Repository;

class OrderDetailRepository implements BulkRepositoryInterface
{
    protected \Db $db;

    /**
     * @var array<int, list<\OrderDetail>>
     */
    protected array $byOrderCache;

    public function __construct(\Db $db)
    {
        $this->db = $db;
        $this->byOrderCache = [];
    }

    /**
     * Preload payment for orders
     *
     * @param \Order[] $orders
     */
    public function preload(array $orders): void
    {
        $orderIds = \array_map(
            fn (\Order $order): int => (int) $order->id,
            $orders
        );

        /**
         * @var list<array{id_order: int, id_order_detail: int, rate: string, amount: string}>|mixed $rows
         */
        $rows = $this->db->executeS(
            'SELECT * FROM `' . _DB_PREFIX_ . 'order_detail` od'
            . ' WHERE od.id_order IN (' . \implode(',', $orderIds) . ')',
            true,
            false
        );
        if (!\is_array($rows)) {
            throw new \Exception("Can't preload");
        }

        $this->byOrderCache = \array_reduce(
            $rows,
            function (array $carry, array $row): array {
                $orderDetail = new \OrderDetail();
                $orderDetail->hydrate($row);

                if (!isset($carry[$orderDetail->id_order])) {
                    $carry[$orderDetail->id_order] = [];
                }

                $carry[$orderDetail->id_order][] = $orderDetail;

                return $carry;
            },
            []
        );
    }

    /**
     * @return list<\OrderDetail>
     */
    public function getByOrder(\Order $order): array
    {
        $id = (int) $order->id;

        $ret = $this->byOrderCache[$id] ?? null;

        if (null === $ret) {
            $rows = $this->db->executeS(
                'SELECT * FROM `' . _DB_PREFIX_ . 'order_detail` od'
                . ' WHERE od.id_order = ' . (int) $order->id,
                true,
                false
            );

            if (!\is_array($rows)) {
                throw new \Exception();
            }

            /** @var \OrderDetail[] $ret */
            $ret = \ObjectModel::hydrateCollection(\OrderDetail::class, $rows);
            $this->byOrderCache[$id] = $ret;
        }

        return $ret;
    }

    public function clear(): void
    {
        $this->byOrderCache = [];
    }
}
