import type { Currency, CurrencyInfo } from '@/lib/types/pricing';

export class CurrencyManager {
  private static readonly EXCHANGE_RATES: Record<Currency, CurrencyInfo> = {
    GBP: { rate: 1, symbol: '£', code: 'GBP' },
    USD: { rate: 1.27, symbol: '$', code: 'USD' },
    EUR: { rate: 1.17, symbol: '€', code: 'EUR' },
    SAR: { rate: 4.76, symbol: 'ر.س', code: 'SAR' },
    AED: { rate: 4.66, symbol: 'د.إ', code: 'AED' },
    QAR: { rate: 4.62, symbol: 'ر.ق', code: 'QAR' },
    KWD: { rate: 0.39, symbol: 'د.ك', code: 'KWD' },
    BHD: { rate: 0.48, symbol: 'د.ب', code: 'BHD' },
    OMR: { rate: 0.49, symbol: 'ر.ع', code: 'OMR' },
  };

  /**
   * Detect user's currency based on timezone
   * Server-safe: returns 'GBP' when called server-side
   *
   * Mappings:
   * - GCC countries → their respective currencies (SAR, AED, QAR, KWD, BHD, OMR)
   * - United States → USD
   * - Europe (excluding UK) → EUR
   * - United Kingdom → GBP
   * - All others → GBP (default)
   */
  static detectUserCurrency(): Currency {
    if (typeof window === 'undefined') return 'GBP';

    try {
      const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;

      // GCC timezone mapping (most specific first)
      if (timezone.includes('Riyadh') || timezone.includes('Saudi')) return 'SAR';
      if (timezone.includes('Dubai') || timezone.includes('Abu_Dhabi')) return 'AED';
      if (timezone.includes('Qatar') || timezone.includes('Doha')) return 'QAR';
      if (timezone.includes('Kuwait')) return 'KWD';
      if (timezone.includes('Bahrain') || timezone.includes('Manama')) return 'BHD';
      if (timezone.includes('Muscat') || timezone.includes('Oman')) return 'OMR';

      // United States (multiple timezone regions)
      if (
        timezone.includes('America/New_York') ||
        timezone.includes('America/Chicago') ||
        timezone.includes('America/Denver') ||
        timezone.includes('America/Los_Angeles') ||
        timezone.includes('America/Phoenix') ||
        timezone.includes('America/Anchorage') ||
        timezone.includes('Pacific/Honolulu') ||
        timezone.includes('US/')
      ) {
        return 'USD';
      }

      // United Kingdom (explicit check before Europe)
      if (timezone.includes('Europe/London')) return 'GBP';

      // Europe (EUR zone) - comprehensive list of major cities
      const eurZones = [
        'Europe/Paris',
        'Europe/Berlin',
        'Europe/Madrid',
        'Europe/Rome',
        'Europe/Amsterdam',
        'Europe/Brussels',
        'Europe/Vienna',
        'Europe/Dublin',
        'Europe/Lisbon',
        'Europe/Athens',
        'Europe/Helsinki',
        'Europe/Stockholm',
        'Europe/Copenhagen',
        'Europe/Prague',
        'Europe/Warsaw',
        'Europe/Budapest',
        'Europe/Bucharest',
        'Europe/Luxembourg',
        'Europe/Zagreb',
        'Europe/Bratislava',
        'Europe/Ljubljana',
        'Europe/Tallinn',
        'Europe/Riga',
        'Europe/Vilnius',
      ];

      if (eurZones.some((zone) => timezone.includes(zone))) {
        return 'EUR';
      }

      // Generic Europe fallback (excluding London)
      if (timezone.includes('Europe/') && !timezone.includes('London')) {
        return 'EUR';
      }

      // Default to GBP for all other regions
      return 'GBP';
    } catch (error) {
      // Fallback to GBP if timezone detection fails
      console.warn('Currency detection failed, using GBP as default', error);
      return 'GBP';
    }
  }

  /**
   * Convert price from GBP to target currency
   */
  static convert(priceGBP: number, toCurrency: Currency): number {
    const rate = this.EXCHANGE_RATES[toCurrency]?.rate || 1;
    return Math.round(priceGBP * rate);
  }

  /**
   * Format price with currency symbol and locale formatting
   */
  static formatPrice(amount: number, currency: Currency): string {
    const info = this.EXCHANGE_RATES[currency];
    return `${info.symbol}${amount.toLocaleString()}`;
  }

  /**
   * Get currency info by code
   */
  static getCurrencyInfo(currency: Currency): CurrencyInfo {
    return this.EXCHANGE_RATES[currency];
  }

  /**
   * Get all available currencies
   */
  static getAllCurrencies(): Currency[] {
    return Object.keys(this.EXCHANGE_RATES) as Currency[];
  }

  /**
   * Find appropriate Stripe price for currency and billing period
   */
  static findStripePrice<T extends { currency: string; interval: string | null }>(
    prices: T[],
    currency: Currency,
    interval: 'month' | 'year'
  ): T | undefined {
    return prices.find(
      (p) =>
        p.currency === currency.toLowerCase() &&
        p.interval === interval
    );
  }
}
