<?php

namespace Myvetshop\Module\Clinique\Adapter;

use Myvetshop\Module\Clinique\Adapter\Hook\ActionCartUpdateQuantityBeforeInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionFrontControllerSetMediaInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCartUpdateBeforeInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCliniqueAddAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCliniqueUpdateAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCustomerAddAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectCustomerUpdateAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectMyvetshopThemeAddAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\ActionObjectMyvetshopThemeUpdateAfterInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\DisplayFooterProductListenerInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\DisplayOrderConfirmation1ListenerInterface;
use Myvetshop\Module\Clinique\Adapter\Hook\HookListenerInterface;

class PrestashopHookAdapter
{
    /**
     * @var list<HookListenerInterface>
     */
    private array $hookListeners;

    /**
     * @param iterable<HookListenerInterface> $hookListeners
     */
    public function __construct(iterable $hookListeners)
    {
        $this->hookListeners = \is_array($hookListeners)
            ? \array_values($hookListeners)
            : \iterator_to_array($hookListeners, false);
    }

    public function actionCartUpdateQuantityBefore(
        \Cart $cart,
        \Product $product,
        int $idProductAttribute,
        int $quantity,
        string $operator,
        \Shop $shop
    ): void {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionCartUpdateQuantityBeforeInterface) {
                continue;
            }

            $hookListener->actionCartUpdateQuantityBefore(
                $cart,
                $product,
                $idProductAttribute,
                $quantity,
                $operator,
                $shop
            );
        }
    }

    public function actionFrontControllerSetMedia(): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionFrontControllerSetMediaInterface) {
                continue;
            }

            $hookListener->actionFrontControllerSetMedia();
        }
    }

    public function actionObjectCartUpdateBefore(\Cart $cart): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectCartUpdateBeforeInterface) {
                continue;
            }

            $hookListener->actionObjectCartUpdateBefore($cart);
        }
    }

    public function actionObjectCliniqueAddAfter(\Clinique $clinique): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectCliniqueAddAfterInterface) {
                continue;
            }

            $hookListener->actionObjectCliniqueAddAfter($clinique);
        }
    }

    public function actionObjectCliniqueUpdateAfter(\Clinique $clinique): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectCliniqueUpdateAfterInterface) {
                continue;
            }

            $hookListener->actionObjectCliniqueUpdateAfter($clinique);
        }
    }

    public function actionObjectCustomerAddAfter(\Customer $customer): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectCustomerAddAfterInterface) {
                continue;
            }

            $hookListener->actionObjectCustomerAddAfter($customer);
        }
    }

    public function actionObjectCustomerUpdateAfter(\Customer $customer): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectCustomerUpdateAfterInterface) {
                continue;
            }

            $hookListener->actionObjectCustomerUpdateAfterInterface($customer);
        }
    }

    public function actionObjectMyvetshopThemeAddAfter(\MyvetshopTheme $myvetshopTheme): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectMyvetshopThemeAddAfterInterface) {
                continue;
            }

            $hookListener->actionObjectMyvetshopThemeAddAfter($myvetshopTheme);
        }
    }

    public function actionObjectMyvetshopThemeUpdateAfter(\MyvetshopTheme $myvetshopTheme): void
    {
        foreach ($this->hookListeners as $hookListener) {
            if (!$hookListener instanceof ActionObjectMyvetshopThemeUpdateAfterInterface) {
                continue;
            }

            $hookListener->actionObjectMyvetshopThemeUpdateAfter($myvetshopTheme);
        }
    }

    public function displayFooterProduct(\Category $category, \Product $product): string
    {
        return \array_reduce(
            $this->hookListeners,
            function (string $carry, HookListenerInterface $hookListener) use ($category, $product): string {
                if ($hookListener instanceof DisplayFooterProductListenerInterface) {
                    $carry .= $hookListener->displayFooterProduct($category, $product);
                }

                return $carry;
            },
            ''
        );
    }

    public function displayOrderConfirmation1(): string
    {
        return \array_reduce(
            $this->hookListeners,
            function (string $carry, HookListenerInterface $hookListener): string {
                if ($hookListener instanceof DisplayOrderConfirmation1ListenerInterface) {
                    $carry .= $hookListener->displayOrderConfirmation1();
                }

                return $carry;
            },
            ''
        );
    }
}
