/**
 * Stripe Price Management
 *
 * Fetches Stripe price IDs from JSON config for subscription checkout
 * Supports multi-currency pricing with fallback to QAR
 *
 * @server-only - Uses Redis caching (server-only dependency)
 */
import 'server-only';
import stripePricesConfig from '@/lib/config/stripe-prices.json';
import multiCurrencyConfig from '@/lib/config/stripe-prices-multi-currency.json';
import { cache } from './cache';

export interface StripePriceMapping {
  tier_id: string;
  product_id: string;
  monthly_price_id: string;
  yearly_price_id: string;
}

// Currencies that have Stripe prices configured
type MultiCurrencyConfig = typeof multiCurrencyConfig;
type AvailableCurrency = keyof MultiCurrencyConfig['currencies'];
const PRICING_CACHE_TTL_SECONDS = 60 * 60; // 1 hour

/**
 * Get list of currencies that have Stripe prices configured
 */
export function getAvailableCurrencies(): string[] {
  return Object.keys(multiCurrencyConfig.currencies);
}

/**
 * Check if a currency has Stripe prices configured
 */
export function isCurrencyAvailable(currency: string): boolean {
  const currencyUpper = currency.toUpperCase();
  return currencyUpper in multiCurrencyConfig.currencies;
}

/**
 * Get Stripe price ID for a tier, billing period, and currency
 *
 * Supports multi-currency pricing using stripe-prices-multi-currency.json
 * Falls back to QAR if requested currency is not available
 *
 * @param tierId - Tier ID (tier1-tier5)
 * @param billingPeriod - 'monthly' or 'yearly'
 * @param currency - Currency code (QAR, GBP, USD, EUR, AED, SAR)
 * @returns Stripe price ID or null if not found
 * @throws Error if currency is not available and no fallback exists
 */
export async function getStripePriceId(
  tierId: string,
  billingPeriod: 'monthly' | 'yearly',
  currency: string = 'QAR'
): Promise<string | null> {
  const currencyUpper = currency.toUpperCase();
  const cacheKey = `pricing:v1:${currencyUpper}:${tierId}:${billingPeriod}`;

  return cache.getOrSet(
    cacheKey,
    async () => {
      // Check if currency is available in multi-currency config
      if (!isCurrencyAvailable(currencyUpper)) {
        const availableCurrencies = getAvailableCurrencies();
        throw new Error(
          `Currency ${currencyUpper} is not yet supported. Available currencies: ${availableCurrencies.join(', ')}`
        );
      }

      // Fetch from multi-currency config
      const currencyConfig = multiCurrencyConfig.currencies[currencyUpper as AvailableCurrency];
      if (!currencyConfig) {
        return null;
      }

      const tierConfig = currencyConfig[tierId as keyof typeof currencyConfig];
      if (!tierConfig) {
        return null;
      }

      return billingPeriod === 'monthly' ? tierConfig.monthly : tierConfig.yearly;
    },
    PRICING_CACHE_TTL_SECONDS
  );
}

/**
 * Get all Stripe price mappings from JSON config
 * NOTE: stripe_prices database table doesn't exist yet. All prices are in JSON config.
 */
export async function getAllStripePrices(): Promise<StripePriceMapping[]> {
  // Return from JSON config - QAR only
  return Object.entries(stripePricesConfig.tiers).map(([tierId, config]) => ({
    tier_id: tierId,
    product_id: config.productId,
    monthly_price_id: config.monthly,
    yearly_price_id: config.yearly,
  }));
}

/**
 * Setup fee in cents (919 QAR)
 */
export const SETUP_FEE = stripePricesConfig.setupFee;

/**
 * Trial period in days
 */
export const TRIAL_DAYS = stripePricesConfig.trialDays;

/**
 * Get the pre-created setup fee price ID for a tier
 * Uses pre-created Stripe prices to avoid Search API eventual consistency issues
 *
 * @param tierId - The tier ID (tier1-tier5)
 * @returns The Stripe price ID for the setup fee
 */
export function getSetupFeePriceId(tierId: string): string {
  // Tier5 (Ultimate) has a higher setup fee
  if (tierId === 'tier5') {
    return (stripePricesConfig as { setupFeePriceIdTier5?: string }).setupFeePriceIdTier5 ||
           (stripePricesConfig as { setupFeePriceId?: string }).setupFeePriceId || '';
  }
  // All other tiers use the standard setup fee
  return (stripePricesConfig as { setupFeePriceId?: string }).setupFeePriceId || '';
}

/**
 * Get the setup fee amount for a tier (in cents)
 *
 * @param tierId - The tier ID (tier1-tier5)
 * @returns The setup fee amount in cents
 */
export function getSetupFeeAmount(tierId: string): number {
  // Tier5 (Ultimate) has a higher setup fee
  if (tierId === 'tier5') {
    return (stripePricesConfig as { setupFeeTier5?: number }).setupFeeTier5 || stripePricesConfig.setupFee;
  }
  return stripePricesConfig.setupFee;
}

/**
 * Get the setup fee price ID for a specific currency and tier
 *
 * @param tierId - The tier ID (tier1-tier5)
 * @param currency - Currency code (QAR, GBP, USD, EUR, AED, SAR)
 * @returns The Stripe price ID for the setup fee, or null if not found
 */
export function getSetupFeePriceIdMultiCurrency(tierId: string, currency: string): string | null {
  const currencyUpper = currency.toUpperCase();
  const tier = tierId === 'tier5' ? 'premium' : 'standard';

  const setupFees = (multiCurrencyConfig as { setupFees?: Record<string, Record<string, string>> }).setupFees;
  if (!setupFees) {
    // Fallback to QAR-only config
    return getSetupFeePriceId(tierId);
  }

  const currencySetupFees = setupFees[currencyUpper];
  if (!currencySetupFees) {
    // Currency not found, fallback to QAR
    return setupFees['QAR']?.[tier] || getSetupFeePriceId(tierId);
  }

  return currencySetupFees[tier] || null;
}

/**
 * Get the additional seat price ID for a specific currency
 *
 * @param currency - Currency code (QAR, GBP, USD, EUR, AED, SAR)
 * @param billingPeriod - 'monthly' or 'yearly' (default: yearly for seats)
 * @returns The Stripe price ID for additional seats, or null if not found
 */
export function getAdditionalSeatPriceId(
  currency: string,
  billingPeriod: 'monthly' | 'yearly' = 'yearly'
): string | null {
  const currencyUpper = currency.toUpperCase();

  const additionalSeat = (multiCurrencyConfig as {
    additionalSeat?: {
      productId: string;
      prices: Record<string, { monthly?: string; yearly?: string }>;
    };
  }).additionalSeat;

  if (!additionalSeat?.prices) {
    return null;
  }

  const currencyPrices = additionalSeat.prices[currencyUpper];
  if (!currencyPrices) {
    // Currency not found, fallback to GBP
    const fallback = additionalSeat.prices['GBP'];
    return fallback?.[billingPeriod] || null;
  }

  return currencyPrices[billingPeriod] || null;
}

/**
 * Get the additional seat product ID
 *
 * @returns The Stripe product ID for additional seats
 */
export function getAdditionalSeatProductId(): string {
  const additionalSeat = (multiCurrencyConfig as {
    additionalSeat?: { productId: string };
  }).additionalSeat;

  return additionalSeat?.productId || 'prod_TYYJBSSbRs3h5K';
}
