<?php

namespace Kylin\Payment;

use Illuminate\Contracts\Container\Container;
use Kylin\Payment\Services\ConfigCacheService;
use Kylin\Payment\Contracts\GatewayInterface;

/**
 * 支付管理器
 */
class PaymentManager
{
    /**
     * 支持的网关类型
     */
    private const SUPPORTED_GATEWAYS = [
        'wechat' => Gateways\WechatGateway::class,
        'alipay' => Gateways\AlipayGateway::class,
        'unionpay' => Gateways\UnionpayGateway::class,
        'douyin' => Gateways\DouyinGateway::class,
        'jsbank' => Gateways\JsbankGateway::class,
        'alipay_global' => Gateways\AlipayGlobalGateway::class,
        'paypal' => Gateways\PaypalGateway::class,
        'stripe' => Gateways\StripeGateway::class,
        'google_pay' => Gateways\GooglePayGateway::class,
        'apple_pay' => Gateways\ApplePayGateway::class,
    ];

    /**
     * 支付网关实例
     */
    protected array $gateways = [];

    /**
     * 构造函数
     */
    public function __construct(
        private readonly Container $app,
        private readonly ?ConfigCacheService $configCacheService = null
    ) {
        $this->configCacheService ??= new ConfigCacheService($app);
    }

    /**
     * 获取微信支付实例
     */
    public function wechat(string $name = 'default'): Gateways\WechatGateway
    {
        return $this->gateway('wechat', $name);
    }

    /**
     * 获取支付宝支付实例
     */
    public function alipay(string $name = 'default'): Gateways\AlipayGateway
    {
        return $this->gateway('alipay', $name);
    }

    /**
     * 获取银联支付实例
     */
    public function unionpay(string $name = 'default'): Gateways\UnionpayGateway
    {
        return $this->gateway('unionpay', $name);
    }

    /**
     * 获取抖音支付实例
     */
    public function douyin(string $name = 'default'): Gateways\DouyinGateway
    {
        return $this->gateway('douyin', $name);
    }

    /**
     * 获取江苏银行支付实例
     */
    public function jsbank(string $name = 'default'): Gateways\JsbankGateway
    {
        return $this->gateway('jsbank', $name);
    }

    /**
     * 获取支付宝国际版实例
     */
    public function alipayGlobal(string $name = 'default'): Gateways\AlipayGlobalGateway
    {
        return $this->gateway('alipay_global', $name);
    }

    /**
     * 获取PayPal实例
     */
    public function paypal(string $name = 'default'): Gateways\PaypalGateway
    {
        return $this->gateway('paypal', $name);
    }

    /**
     * 获取Stripe实例
     */
    public function stripe(string $name = 'default'): Gateways\StripeGateway
    {
        return $this->gateway('stripe', $name);
    }

    /**
     * 获取Google Pay实例
     */
    public function googlePay(string $name = 'default'): Gateways\GooglePayGateway
    {
        return $this->gateway('google_pay', $name);
    }

    /**
     * 获取Apple Pay实例
     */
    public function applePay(string $name = 'default'): Gateways\ApplePayGateway
    {
        return $this->gateway('apple_pay', $name);
    }

    /**
     * 获取支付网关实例
     *
     * @throws \InvalidArgumentException 如果网关类型不支持
     */
    public function gateway(string $type, string $name = 'default'): GatewayInterface
    {
        if (!isset(self::SUPPORTED_GATEWAYS[$type])) {
            throw new \InvalidArgumentException(sprintf('不支持的支付类型: %s', $type));
        }

        $key = "{$type}.{$name}";

        return $this->gateways[$key] ??= $this->createGateway($type, $this->getConfig($type, $name));
    }

    /**
     * 创建支付网关实例
     */
    protected function createGateway(string $type, array $config): GatewayInterface
    {
        $gatewayClass = self::SUPPORTED_GATEWAYS[$type];

        return new $gatewayClass($config);
    }

    /**
     * 获取支付配置
     *
     * @throws \InvalidArgumentException 如果配置不存在
     */
    protected function getConfig(string $type, string $name): array
    {
        $config = $this->configCacheService->getPaymentConfig($type, $name);

        if (!empty($config)) {
            return $config;
        }

        throw new \InvalidArgumentException(sprintf('配置不存在: payment.%s.%s', $type, $name));
    }

    /**
     * 动态调用
     */
    public function __call(string $method, array $parameters): mixed
    {
        if (method_exists($this, $method)) {
            return $this->{$method}(...$parameters);
        }

        throw new \BadMethodCallException(sprintf('方法不存在: %s', $method));
    }

    /**
     * 获取所有支持的网关类型
     */
    public function getSupportedGateways(): array
    {
        return array_keys(self::SUPPORTED_GATEWAYS);
    }

    /**
     * 检查网关类型是否支持
     */
    public function isGatewaySupported(string $type): bool
    {
        return isset(self::SUPPORTED_GATEWAYS[$type]);
    }

    /**
     * 清除指定网关的缓存
     */
    public function forgetGateway(string $type, string $name = 'default'): void
    {
        $key = "{$type}.{$name}";
        unset($this->gateways[$key]);
    }

    /**
     * 清除所有网关缓存
     */
    public function forgetAllGateways(): void
    {
        $this->gateways = [];
    }
}
