<?php

namespace App\Payment\Gateway;

use App\Config\Repository\SiteConfigRepository;

/**
 * انتخاب/ساخت درگاه پرداخت (Factory + Strategy).
 *
 * تمام منطقِ «کدام درگاه، فعال است یا نه، حالت تست» اینجا متمرکز است تا کنترلر
 * فقط Orchestration کند. افزودن درگاه جدید = ثبت آن به‌عنوان سرویس و اضافه‌کردن
 * یک case در map + یک برچسب، بدون تغییر کنترلر.
 */
class GatewayFactory
{
    /** @var array<string, PaymentGatewayInterface> */
    private array $gateways;

    /** @var array<string, string> برچسب فارسی هر درگاه */
    private const LABELS = [
        'mellat' => 'بانک ملت',
        'sep'    => 'سپ (سامان کیش)',
    ];

    public function __construct(
        MellatGateway $mellat,
        SepGateway $sep,
        private readonly MockGateway $mock,
        private readonly SiteConfigRepository $configRepo,
    ) {
        $this->gateways = [
            $mellat->getName() => $mellat,
            $sep->getName()    => $sep,
        ];
    }

    public function isTestMode(): bool
    {
        return $this->configRepo->get('payment_test_mode') === '1';
    }

    /** حالت sandbox ملت (banktest.ir) — اتصال واقعی، جدا از test_mode/Mock. موقت. */
    public function isMellatSandbox(): bool
    {
        return $this->configRepo->get('mellat_sandbox') === '1';
    }

    /**
     * درگاهِ قابل‌استفاده برای این نام؛ در حالت تست همیشه Mock، در غیر این‌صورت
     * درگاه واقعی در صورت فعال بودن. null یعنی نامعتبر/غیرفعال.
     */
    public function resolve(string $name): ?PaymentGatewayInterface
    {
        // sandbox ملت: اتصال واقعی به banktest، نه Mock.
        if ($name === 'mellat' && $this->isMellatSandbox()) {
            return $this->gateways['mellat'] ?? null;
        }
        if ($this->isTestMode()) {
            return $this->mock;
        }
        if (!$this->isEnabled($name)) {
            return null;
        }
        return $this->gateways[$name] ?? null;
    }

    /** آیا درگاه در تنظیمات فعال است؟ کلید تنظیم‌نشده = فعال (سازگاری با نصب‌های قبلی). */
    public function isEnabled(string $name): bool
    {
        $v = $this->configRepo->get($name . '_enabled');
        return $v === null || $v === '1';
    }

    /**
     * درگاه‌های قابل‌انتخاب برای نمایش به کاربر: در حالت تست فقط درگاه آزمایشی،
     * در غیر این‌صورت هر درگاهی که اعتبارنامه‌اش ست شده و فعال است.
     *
     * @return array<int, array{name: string, label: string}>
     */
    public function activeGateways(): array
    {
        if ($this->isMellatSandbox()) {
            return [['name' => 'mellat', 'label' => 'بانک ملت (Sandbox)']];
        }
        if ($this->isTestMode()) {
            return [['name' => 'mellat', 'label' => 'بانک ملت (آزمایشی)']];
        }

        $out = [];
        foreach ($this->gateways as $name => $gateway) {
            if ($gateway->isConfigured() && $this->isEnabled($name)) {
                $out[] = ['name' => $name, 'label' => self::LABELS[$name] ?? $name];
            }
        }
        return $out;
    }
}
