<?php

namespace PaymentWebhooks\Application;

use PaymentWebhooks\Contract\OrderUpdaterInterface;
use PaymentWebhooks\Core\AbstractWebhookHandler;
use PaymentWebhooks\Core\AsynchronousOrderUpdater;
use PaymentWebhooks\Core\SynchronousOrderUpdater;
use PaymentWebhooks\Gateway\Adyen\AdyenAuthenticator;
use PaymentWebhooks\Gateway\Adyen\AdyenPostValidator;
use PaymentWebhooks\Gateway\Adyen\AdyenStatusMapper;
use PaymentWebhooks\Gateway\Adyen\AdyenWebhookHandler;
use PaymentWebhooks\Gateway\Checkout\CheckoutPostValidator;
use PaymentWebhooks\Gateway\Checkout\CheckoutStatusMapper;
use PaymentWebhooks\Gateway\Checkout\CheckoutWebhookHandler;
use PaymentWebhooks\Gateway\Common\CommonOrderIdResolver;
use PaymentWebhooks\Gateway\Common\CommonPayloadValidator;
use PaymentWebhooks\Gateway\Common\NullAdditionalRequester;
use PaymentWebhooks\Gateway\Common\NullAuthenticator;
use PaymentWebhooks\Gateway\Common\NullPostValidator;
use PaymentWebhooks\Gateway\Common\PaymentDataResolver;
use PaymentWebhooks\Gateway\Mollie\MollieAdditionalRequester;
use PaymentWebhooks\Gateway\Mollie\MollieStatusMapper;
use PaymentWebhooks\Gateway\Mollie\MollieWebhookHandler;
use PaymentWebhooks\Gateway\PayPal\PayPalPostValidator;
use PaymentWebhooks\Gateway\PayPal\PayPalStatusMapper;
use PaymentWebhooks\Gateway\PayPal\PayPalWebhookHandler;
use PaymentWebhooks\Infrastructure\Config;
use PaymentWebhooks\Infrastructure\Logger;

final class WebhookHandlerFactory
{
    public static function make(string $gateway): ?AbstractWebhookHandler
    {
        $updater = self::makeUpdater($gateway);
        return match ($gateway) {
            'adyen' => new AdyenWebhookHandler(
                new NullAdditionalRequester(),
                new AdyenAuthenticator(),
                new CommonPayloadValidator(),
                new AdyenPostValidator(),
                new AdyenStatusMapper($gateway),
                $updater,
                Logger::forGateway($gateway),
                new CommonOrderIdResolver($gateway),
                new PaymentDataResolver($gateway)
            ),
            'paypal' => new PayPalWebhookHandler(
                new NullAdditionalRequester(),
                new NullAuthenticator(),
                new CommonPayloadValidator(),
                new PayPalPostValidator(),
                new PayPalStatusMapper($gateway),
                $updater,
                Logger::forGateway($gateway),
                new CommonOrderIdResolver($gateway),
                new PaymentDataResolver($gateway),
            ),
            'mollie' => new MollieWebhookHandler(
                new MollieAdditionalRequester(),
                new NullAuthenticator(),
                new CommonPayloadValidator(),
                new NullPostValidator(),
                new MollieStatusMapper($gateway),
                $updater,
                Logger::forGateway($gateway),
                new CommonOrderIdResolver($gateway),
                new PaymentDataResolver($gateway),
            ),
            'checkoutcom' => new CheckoutWebhookHandler(
                new NullAdditionalRequester(),
                new NullAuthenticator(),
                new CommonPayloadValidator(),
                new CheckoutPostValidator(),
                new CheckoutStatusMapper($gateway),
                $updater,
                Logger::forGateway($gateway),
                new CommonOrderIdResolver($gateway),
                new PaymentDataResolver($gateway),
            ),

            default => null,
        };
    }
    private static function makeUpdater(string $gateway): OrderUpdaterInterface
    {
        $isAsync = Config::get('PW_ASYNC_UPDATE');

        if ($isAsync) {
            static $instances = [];
            if (!isset($instances[$gateway])) {
                $instances[$gateway] = new AsynchronousOrderUpdater($gateway);
            }
            return $instances[$gateway];
        }

        return new SynchronousOrderUpdater();

    }
}
