<?php

class OrderProblemSomme implements OrderProblemInterface
{
    /**
     * @var Order
     */
    protected $order;

    /**
     * @var OrderDetail[]
     */
    protected $details;

    /**
     * @var OrderCartRule[]
     */
    protected $discounts;

    /**
     * @return array<string, float>
     */
    protected function getOrderSubtotals()
    {
        return [
            // Montant des produits HT
            'product_total_tax_excl' => round(array_reduce(
                $this->details,
                function ($sum, OrderDetail $orderDetail) {
                    return $sum + $orderDetail->total_price_tax_excl;
                },
                0
            ), 2),
            // Montant des produits TTC
            'product_total_tax_incl' => round(array_reduce(
                $this->details,
                function ($sum, OrderDetail $orderDetail) {
                    return $sum + $orderDetail->total_price_tax_incl;
                },
                0
            ), 2),
            // Montant total des réductions (HT)
            'discount_total_tax_excl' => round(array_reduce(
                $this->discounts,
                function ($sum, OrderCartRule $orderCartRule) {
                    return $sum + $orderCartRule->value_tax_excl;
                },
                0
            ), 2),
            // Montant total des réductions (TTC)
            'discount_total_tax_incl' => round(array_reduce(
                $this->discounts,
                function ($sum, OrderCartRule $orderCartRule) {
                    return $sum + $orderCartRule->value;
                },
                0
            ), 2),
        ];
    }

    public function __construct(Order $order)
    {
        $this->order = $order;
        $this->details = ObjectModel::hydrateCollection(OrderDetail::class, $order->getOrderDetailList());
        $this->discounts = ObjectModel::hydrateCollection(OrderCartRule::class, $order->getCartRules());
    }

    public function getErrorMessage(): string
    {
        return 'Les sommes des produits et fdp ne correspondent pas au total de la commande';
    }

    public function isProblematic(): bool
    {
        $subTotals = $this->getOrderSubtotals();

        if (round(floatval($this->order->total_products), 2) != $subTotals['product_total_tax_excl']) {
            return true;
        }

        if (round(floatval($this->order->total_products_wt), 2) != $subTotals['product_total_tax_incl']) {
            return true;
        }

        if (round(floatval($this->order->total_discounts_tax_excl), 2) != $subTotals['discount_total_tax_excl']) {
            return true;
        }

        if (round(floatval($this->order->total_discounts_tax_incl), 2) != $subTotals['discount_total_tax_incl']) {
            return true;
        }

        // Si le total HT n'est pas bon, erreur
        if ($subTotals['product_total_tax_excl']
            + round(floatval($this->order->total_shipping_tax_excl), 2)
            - $subTotals['discount_total_tax_excl'] != round(floatval($this->order->total_paid_tax_excl), 2)) {
            return true;
        }

        // Si le total TTC n'et pas bon, erreur
        if ($subTotals['product_total_tax_incl']
            + round(floatval($this->order->total_shipping_tax_incl), 2)
            - $subTotals['discount_total_tax_incl'] != round(floatval($this->order->total_paid_tax_incl), 2)) {
            return true;
        }

        return false;
    }

    public function isRepairable(): bool
    {
        $subTotals = $this->getOrderSubtotals();

        if (round(floatval($this->order->total_products), 2) != $subTotals['product_total_tax_excl']) {
            return true;
        }

        if (round(floatval($this->order->total_products_wt), 2) != $subTotals['product_total_tax_incl']) {
            return true;
        }

        if (round(floatval($this->order->total_discounts_tax_excl), 2) != $subTotals['discount_total_tax_excl']) {
            return true;
        }

        if (round(floatval($this->order->total_discounts_tax_incl), 2) != $subTotals['discount_total_tax_incl']) {
            return true;
        }

        // Si le total HT n'est pas bon, erreur
        if ($subTotals['product_total_tax_excl']
            + round(floatval($this->order->total_shipping_tax_excl), 2)
            - $subTotals['discount_total_tax_excl'] != round(floatval($this->order->total_paid_tax_excl), 2)) {
            return true;
        }

        // SI le total TTC n'et pas bon, erreur
        if ($subTotals['product_total_tax_incl']
            + round(floatval($this->order->total_shipping_tax_incl), 2)
            - $subTotals['discount_total_tax_incl'] != round(floatval($this->order->total_paid_tax_incl), 2)) {
            return false;
        }

        return false;
    }

    public function repair(): bool
    {
        $subTotals = $this->getOrderSubtotals();

        $this->order->total_products = $subTotals['product_total_tax_excl'];
        $this->order->total_products_wt = $subTotals['product_total_tax_incl'];
        $this->order->total_discounts_tax_excl = $subTotals['discount_total_tax_excl'];
        $this->order->total_discounts_tax_incl = $subTotals['discount_total_tax_incl'];

        // Si le total HT n'est pas bon, erreur
        $this->order->total_paid_tax_excl = $subTotals['product_total_tax_excl'] + $this->order->total_shipping_tax_excl - $subTotals['discount_total_tax_excl'];

        return true;
    }
}
