<?php
/**
 * BookiFlex Onboarding Extension
 *
 * @package    BookiFlex
 * @subpackage Onboarding
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */

declare(strict_types=1);

namespace BookiFlex\Extensions\Onboarding\Factory;

use BookiFlex\Extensions\Onboarding\ValueObject\Currency;
use Brick\Money\ISOCurrencyProvider;

defined( 'ABSPATH' ) || exit;

/**
 * Currency Factory
 *
 * Creates Currency value objects from brick/money ISO currency data.
 * Provides complete list of ISO 4217 currencies with symbols.
 *
 * @package BookiFlex\Extensions\Onboarding\Factory
 * @since   1.0.0
 */
class CurrencyFactory
{
    /**
     * @var array<string, string> Currency symbol map 
     */
    private array $symbols = [
        'USD' => '$',
        'EUR' => '€',
        'GBP' => '£',
        'JPY' => '¥',
        'RUB' => '₽',
        'CNY' => '¥',
        'CHF' => 'CHF',
        'CAD' => 'C$',
        'AUD' => 'A$',
        'NZD' => 'NZ$',
        'INR' => '₹',
        'BRL' => 'R$',
        'KRW' => '₩',
        'MXN' => '$',
        'SEK' => 'kr',
        'NOK' => 'kr',
        'DKK' => 'kr',
        'PLN' => 'zł',
        'TRY' => '₺',
        'ZAR' => 'R',
    ];

    /**
     * Get all available currencies
     *
     * @return Currency[] Array of Currency value objects
     */
    public function getAllCurrencies(): array
    {
        $currencies = [];
        $provider = ISOCurrencyProvider::getInstance();
        $availableCurrencies = $provider->getAvailableCurrencies();

        foreach ($availableCurrencies as $currency) {
            $code = $currency->getCurrencyCode();
            $name = $currency->getName();

            $currencies[] = new Currency(
                value: $code,
                label: sprintf('%s - %s', $code, $name),
                symbol: $this->getCurrencySymbol($code)
            );
        }

        // Sort by currency code
        usort($currencies, fn($a, $b) => strcmp($a->value, $b->value));

        return $currencies;
    }

    /**
     * Get currency symbol for code
     *
     * @param  string $code ISO 4217 currency code
     * @return string Currency symbol or code if symbol unknown
     */
    private function getCurrencySymbol(string $code): string
    {
        return $this->symbols[$code] ?? $code;
    }

    /**
     * Get popular currencies (subset for default selection)
     *
     * @return Currency[] Array of popular currencies
     */
    public function getPopularCurrencies(): array
    {
        $popularCodes = ['USD', 'EUR', 'GBP', 'RUB', 'JPY', 'CNY', 'CHF', 'CAD', 'AUD'];
        $allCurrencies = $this->getAllCurrencies();

        return array_filter(
            $allCurrencies,
            fn(Currency $c) => in_array($c->value, $popularCodes, true)
        );
    }
}
