<?php

namespace Kylin\Wechat\Wechat;

use Illuminate\Support\Manager;
use Illuminate\Contracts\Container\Container;
use EasyWeChat\Factory;
use EasyWeChat\OfficialAccount\Application as OfficialAccountApplication;
use EasyWeChat\MiniProgram\Application as MiniProgramApplication;
use EasyWeChat\OpenPlatform\Application as OpenPlatformApplication;
use EasyWeChat\Work\Application as WorkApplication;
use EasyWeChat\OpenWork\Application as OpenWorkApplication;
use EasyWeChat\Payment\Application as PaymentApplication;
use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application as OpenPlatformMiniProgramApplication;
use EasyWeChat\OpenPlatform\Authorizer\OfficialAccount\Application as OpenPlatformOfficialAccountApplication;

/**
 * 微信服务管理器
 */
final class WechatManager extends Manager
{
    /**
     * 支持的驱动类型
     */
    private const SUPPORTED_DRIVERS = [
        'official_account',
        'mini_program',
        'open_platform',
        'work',
        'open_work',
        'payment',
    ];

    /**
     * 创建一个新的微信管理器实例
     */
    public function __construct(
        private readonly Container $app
    ) {
        parent::__construct($app);
    }

    /**
     * 获取默认驱动名称
     */
    public function getDefaultDriver(): string
    {
        return 'official_account';
    }

    /**
     * 获取微信配置
     *
     * @throws \InvalidArgumentException 如果配置不存在
     */
    protected function getConfig(string $type, string $name = 'default'): array
    {
        $defaultConfig = $this->app['config']->get('wechat.default', []);
        $typeConfig = $this->app['config']->get("wechat.accounts.{$type}.{$name}", []);

        if (empty($typeConfig)) {
            throw new \InvalidArgumentException("微信{$type}配置 '{$name}' 未找到。");
        }

        return array_merge($defaultConfig, $typeConfig);
    }

    /**
     * 创建公众号驱动
     */
    protected function createOfficialAccountDriver(string $name): OfficialAccountApplication
    {
        $config = $this->getConfig('official_account', $name);
        return Factory::officialAccount($config);
    }

    /**
     * 创建小程序驱动
     */
    protected function createMiniProgramDriver(string $name): MiniProgramApplication
    {
        $config = $this->getConfig('mini_program', $name);
        return Factory::miniProgram($config);
    }

    /**
     * 创建开放平台驱动
     */
    protected function createOpenPlatformDriver(string $name): OpenPlatformApplication
    {
        $config = $this->getConfig('open_platform', $name);
        return Factory::openPlatform($config);
    }

    /**
     * 创建企业微信驱动
     */
    protected function createWorkDriver(string $name): WorkApplication
    {
        $config = $this->getConfig('work', $name);
        return Factory::work($config);
    }

    /**
     * 创建企业微信开放平台驱动
     */
    protected function createOpenWorkDriver(string $name): OpenWorkApplication
    {
        $config = $this->getConfig('open_work', $name);
        return Factory::openWork($config);
    }

    /**
     * 创建微信支付驱动
     */
    protected function createPaymentDriver(string $name): PaymentApplication
    {
        $config = $this->getConfig('payment', $name);
        return Factory::payment($config);
    }

    /**
     * 获取公众号实例
     */
    public function officialAccount(string $name = 'default'): OfficialAccountApplication
    {
        return $this->driver('official_account', $name);
    }

    /**
     * 获取小程序实例
     */
    public function miniProgram(string $name = 'default'): MiniProgramApplication
    {
        return $this->driver('mini_program', $name);
    }

    /**
     * 获取开放平台实例
     */
    public function openPlatform(string $name = 'default'): OpenPlatformApplication
    {
        return $this->driver('open_platform', $name);
    }

    /**
     * 获取企业微信实例
     */
    public function work(string $name = 'default'): WorkApplication
    {
        return $this->driver('work', $name);
    }

    /**
     * 获取企业微信开放平台实例
     */
    public function openWork(string $name = 'default'): OpenWorkApplication
    {
        return $this->driver('open_work', $name);
    }

    /**
     * 获取微信支付实例
     */
    public function payment(string $name = 'default'): PaymentApplication
    {
        return $this->driver('payment', $name);
    }

    /**
     * 通过开放平台获取小程序实例
     */
    public function miniProgramByOpenPlatform(
        string $appId,
        string $refreshToken,
        string $openPlatformName = 'default'
    ): OpenPlatformMiniProgramApplication {
        $openPlatform = $this->openPlatform($openPlatformName);

        return $openPlatform->miniProgram($appId, $refreshToken);
    }

    /**
     * 通过开放平台获取公众号实例
     */
    public function officialAccountByOpenPlatform(
        string $appId,
        string $refreshToken,
        string $openPlatformName = 'default'
    ): OpenPlatformOfficialAccountApplication {
        $openPlatform = $this->openPlatform($openPlatformName);

        return $openPlatform->officialAccount($appId, $refreshToken);
    }

    /**
     * 获取驱动实例
     *
     * @throws \InvalidArgumentException 如果驱动类型不支持
     */
    public function driver(?string $driver = null, string $name = 'default'): mixed
    {
        $driver ??= $this->getDefaultDriver();

        if (!in_array($driver, self::SUPPORTED_DRIVERS, true)) {
            throw new \InvalidArgumentException("不支持的微信驱动类型: {$driver}");
        }

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

        return $this->drivers[$key] ??= $this->{'create' . ucfirst($driver) . 'Driver'}($name);
    }

    /**
     * 获取所有支持的驱动类型
     */
    public function getSupportedDrivers(): array
    {
        return self::SUPPORTED_DRIVERS;
    }

    /**
     * 检查驱动类型是否支持
     */
    public function isDriverSupported(string $driver): bool
    {
        return in_array($driver, self::SUPPORTED_DRIVERS, true);
    }

    /**
     * 清除指定驱动的缓存
     */
    public function forgetDriver(string $driver, string $name = 'default'): void
    {
        $key = "{$driver}.{$name}";
        unset($this->drivers[$key]);
    }

    /**
     * 清除所有驱动缓存
     */
    public function forgetAllDrivers(): void
    {
        $this->drivers = [];
    }
}