<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Checkout;

use Gls\GlsPoland\EventDispatcher\Adapter\EventDispatcher;
use Gls\GlsPoland\PrestaShop\Checkout\Event\AbstractCheckoutEvent;
use Gls\GlsPoland\PrestaShop\ModuleRepository;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;

final class CheckoutResolver implements CheckoutResolverInterface
{
    private const CHECKOUT_MODULE_CONTROLLERS = [
        'supercheckout' => 'supercheckout',
        'steasycheckout' => 'default',
        'thecheckout' => 'front',
        'ets_onepagecheckout' => 'order',
    ];

    private $container;
    private $controller;
    private $moduleRepository;
    private $dispatcher;

    private $resolved;

    public function __construct(ContainerInterface $container, \FrontController $controller, ModuleRepository $moduleRepository)
    {
        $this->container = $container;
        $this->controller = $controller;
        $this->moduleRepository = $moduleRepository;
        $this->dispatcher = new EventDispatcher();
    }

    public function resolve(Request $request = null): ?CheckoutInterface
    {
        if (null !== $this->resolved) {
            return $this->resolved;
        }

        [$isCheckoutController, $moduleName] = $this->getControllerInfo($request);
        if (!$isCheckoutController) {
            return null;
        }

        $this->resolved = $this
            ->doGetCheckout($moduleName)
            ->setController($this->controller);

        $this->dispatcher->addSubscriber($this->resolved);

        return $this->resolved;
    }

    public function dispatch(AbstractCheckoutEvent $event): AbstractCheckoutEvent
    {
        $this->resolve($event->getRequest());

        return $this->dispatcher->dispatch($event);
    }

    private function getControllerInfo(?Request $request): array
    {
        if ($this->controller instanceof \OrderControllerCore) {
            $moduleName = $this->moduleRepository->isEnabled('wkonepagecheckout') ? 'wkonepagecheckout' : null;

            return [true, $moduleName];
        }

        if (!$this->controller instanceof \ModuleFrontControllerCore || null === $request) {
            return [false, null];
        }

        $moduleName = $this->controller->module->name;
        $isCheckoutController = isset(self::CHECKOUT_MODULE_CONTROLLERS[$moduleName])
            && self::CHECKOUT_MODULE_CONTROLLERS[$moduleName] === $this->getModuleControllerName($request);

        return [$isCheckoutController, $moduleName];
    }

    private function getModuleControllerName(Request $request): string
    {
        $controller = $request->query->get('controller', '');
        $parts = explode('-', $controller);

        return end($parts);
    }

    private function doGetCheckout(?string $moduleName): CheckoutInterface
    {
        switch ($moduleName) {
            default:
                return $this->container->get(NativeCheckout::class);
        }
    }
}
