<?php
/**
 * Copyright © Simplyin. All rights reserved.
 */
declare(strict_types=1);

namespace Simplyin\Payment\Service;

use Psr\Log\LoggerInterface;
use Simplyin\Payment\Service\Api\PaymentApiClient;

/**
 * Decides whether the merchant has any SimplyIN payment method configured.
 *
 * Single source of truth for gating the SimplyIN checkout branding: the Luma
 * payment model and the Hyva ViewModels all consult this service, so the
 * availability API is queried at most once per request (result cached below).
 */
class PaymentMethodAvailability
{
    /**
     * @var PaymentApiClient
     */
    private PaymentApiClient $paymentApiClient;

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * Per-request cache of the availability decision (null = not yet resolved).
     *
     * @var bool|null
     */
    private ?bool $hasAvailableMethods = null;

    /**
     * Constructor
     *
     * @param PaymentApiClient $paymentApiClient
     * @param LoggerInterface $logger
     */
    public function __construct(PaymentApiClient $paymentApiClient, LoggerInterface $logger)
    {
        $this->paymentApiClient = $paymentApiClient;
        $this->logger = $logger;
    }

    /**
     * Whether the merchant has at least one payment method configured.
     *
     * Fail-closed: SimplyIN is shown ONLY when the availability call
     * succeeds and returns at least one method. On any error, exception or
     * unauthenticated response the merchant's configuration is unknown, so we hide
     * SimplyIN rather than show it against a backend we can't confirm is working —
     * matching the WooCommerce and PrestaShop plugins' fail-closed behaviour.
     *
     * @return bool
     */
    public function hasAvailablePaymentMethods(): bool
    {
        if ($this->hasAvailableMethods !== null) {
            return $this->hasAvailableMethods;
        }

        try {
            $response = $this->paymentApiClient->getAvailablePaymentMethodsList();

            if (!($response['success'] ?? false)) {
                // Uncertain (error / unauthenticated response): fail closed.
                $this->hasAvailableMethods = false;
                return $this->hasAvailableMethods;
            }

            // methods is already the normalized flat list (handles the nested
            // data.paymentMethods shape); empty here genuinely means "none configured".
            $methods = is_array($response['methods'] ?? null) ? $response['methods'] : [];
            $this->hasAvailableMethods = $methods !== [];
        } catch (\Throwable $e) {
            // Uncertain (transport/decoding failure, incl. \Error): fail closed, but record why.
            $this->logger->error(
                'SimplyIN payment-method availability check failed: ' . $e->getMessage(),
                ['exception' => $e]
            );
            $this->hasAvailableMethods = false;
        }

        return $this->hasAvailableMethods;
    }
}
