<?php

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

class OrderSlipDetailRepository implements BulkRepositoryInterface
{
    protected \Db $db;

    /**
     * @var array<
     *     int,
     *     list<
     *         array{
     *             id_order_detail: int,
     *             product_quantity: int,
     *             amount_tax_excl: float,
     *             amount_tax_incl: float
     *         }
     *     >
     * >
     */
    protected array $byOrderSlipCache;

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

    /**
     * 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_slip: int,
         *      id_order_detail: int,
         *      product_quantity: int,
         *      total_price_tax_excl: float,
         *      total_price_tax_incl: float,
         *      amount_tax_excl: float,
         *      amount_tax_incl: float}>|mixed $rows
         */
        $rows = $this->db->executeS(
            'SELECT osd.* FROM `' . _DB_PREFIX_ . 'order_slip_detail` osd'
            . ' INNER JOIN `' . _DB_PREFIX_ . 'order_detail` od ON od.id_order_detail = osd.id_order_detail'
            . ' WHERE od.id_order IN (' . \implode(',', $orderIds) . ')',
            true,
            false
        );
        if (!\is_array($rows)) {
            throw new \Exception("Can't preload");
        }

        $this->byOrderSlipCache = \array_reduce(
            $rows,
            function (array $carry, array $row): array {
                $idOrderSlip = $row['id_order_slip'];

                if (!isset($carry[$idOrderSlip])) {
                    $carry[$idOrderSlip] = [];
                }

                $carry[$idOrderSlip][] = $row;

                return $carry;
            },
            []
        );
    }

    /**
     * @return list<array{
     *     id_order_detail: int,
     *     product_quantity: int,
     *     total_price_tax_excl: float,
     *     total_price_tax_incl: float,
     *     amount_tax_excl: float,
     *     amount_tax_incl: float
     * }>
     */
    public function getByOrderSlip(\OrderSlip $orderSlip): array
    {
        $id = (int) $orderSlip->id;

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

        if (null === $ret) {
            $ret = $this->db->executeS(
                'SELECT * FROM `' . _DB_PREFIX_ . 'order_slip_detail` osd'
                    . ' WHERE osd.id_order_slip = ' . $id,
                true,
                false
            );

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

            /* @var list<array{
             *      id_order_slip: int,
             *      id_order_detail: int,
             *      product_quantity: int,
             *      total_price_tax_excl: float,
             *      total_price_tax_incl: float,
              *     amount_tax_excl: float,
             *      amount_tax_incl: float
             *  }> $ret */
            $this->byOrderSlipCache[$id] = $ret;
        }

        return $ret;
    }

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