<?php

namespace GriffinForms\Includes\Helpers;

use GriffinForms\Traits\Singleton;

/**
 * Utility helper for currency formatting and validation.
 */
class Currency
{
    use Singleton;

    /**
     * Default currency code.
     *
     * @var string
     */
    protected $default_currency = 'USD';

    /**
     * Return supported currencies in code => label format.
     *
     * @return array<string,string>
     */
    public function getSupportedCurrencies(): array
    {
        $currencies = [
            'USD' => __('US Dollar (USD)', 'griffinforms-form-builder'),
            'EUR' => __('Euro (EUR)', 'griffinforms-form-builder'),
            'GBP' => __('British Pound (GBP)', 'griffinforms-form-builder'),
            'AUD' => __('Australian Dollar (AUD)', 'griffinforms-form-builder'),
            'CAD' => __('Canadian Dollar (CAD)', 'griffinforms-form-builder'),
            'INR' => __('Indian Rupee (INR)', 'griffinforms-form-builder'),
        ];

        /**
         * Allow plugins to register additional currencies.
         *
         * @param array $currencies
         */
        return apply_filters('griffinforms_supported_currencies', $currencies);
    }

    /**
     * Determine if a code is supported.
     */
    public function isSupportedCurrency(string $currency): bool
    {
        $currency = strtoupper(sanitize_key($currency));
        $currencies = $this->getSupportedCurrencies();
        return isset($currencies[$currency]);
    }

    /**
     * Sanitize currency code. Returns default when unsupported.
     */
    public function sanitizeCurrency(?string $currency): string
    {
        $currency = strtoupper(sanitize_key((string) $currency));
        if (!$this->isSupportedCurrency($currency)) {
            return $this->default_currency;
        }

        return $currency;
    }

    /**
     * Format amount with currency symbol.
     */
    public function formatAmount($amount, ?string $currency = null, int $precision = 2): string
    {
        $currency = $this->sanitizeCurrency($currency ?? $this->default_currency);
        $symbol = $this->getCurrencySymbol($currency);
        $formatted = number_format_i18n((float) $amount, $precision);

        /**
         * Filter the formatted amount before returning.
         *
         * @param string $formatted_amount
         * @param float $amount
         * @param string $currency
         */
        return apply_filters('griffinforms_formatted_amount', $symbol . $formatted, (float) $amount, $currency);
    }

    /**
     * Return symbol for a currency.
     */
    public function getCurrencySymbol(string $currency): string
    {
        $currency = strtoupper($currency);
        $symbols = [
            'USD' => '$',
            'EUR' => '€',
            'GBP' => '£',
            'AUD' => 'A$',
            'CAD' => 'C$',
            'INR' => '₹',
        ];

        $symbol = $symbols[$currency] ?? ($this->default_currency === $currency ? '$' : ($currency . ' '));

        /**
         * Filter the symbol used for a currency.
         *
         * @param string $symbol
         * @param string $currency
         */
        return apply_filters('griffinforms_currency_symbol', $symbol, $currency);
    }
}
