<?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\Common\CommonOrderIdResolver;
use PaymentWebhooks\Gateway\Common\CommonPayloadValidator;
use PaymentWebhooks\Gateway\Common\PaymentDataResolver;
use PaymentWebhooks\Gateway\PayPal\PayPalAuthenticator;
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 AdyenAuthenticator(),
                new CommonPayloadValidator(),
                new AdyenPostValidator(),
                new AdyenStatusMapper($gateway),
                $updater,
                Logger::forGateway($gateway),
                new CommonOrderIdResolver($gateway),
                new PaymentDataResolver($gateway)
            ),
            'paypal' => new PayPalWebhookHandler(
                new PayPalAuthenticator(),
                new CommonPayloadValidator(),
                new PayPalPostValidator(),
                new PayPalStatusMapper($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', false);

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

        return new SynchronousOrderUpdater();

    }
}
