export interface ExchangeRates {
	base: string;
	date: string;
	rates: Record<string, number>;
}

export const CURRENCY_MARKET_MAP: Record<string, string> = {
	EUR: "EU",
	USD: "US",
	GBP: "UK",
	JPY: "JP",
	CAD: "CA",
	AUD: "AU",
};

export function getMarketForCurrency(currency: string): string {
	return CURRENCY_MARKET_MAP[currency] ?? currency;
}

// In-memory cache
let cachedRates: ExchangeRates | null = null;
let cacheExpiry = 0;

const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
const FRANKFURTER_URL = "https://api.frankfurter.app/latest?from=EUR";

export async function getExchangeRates(): Promise<ExchangeRates> {
	const now = Date.now();

	// Return cached rates if still valid
	if (cachedRates && now < cacheExpiry) {
		return cachedRates;
	}

	try {
		const response = await fetch(FRANKFURTER_URL);
		if (!response.ok) {
			throw new Error(`frankfurter.app returned ${response.status}`);
		}

		const data = (await response.json()) as {
			base: string;
			date: string;
			rates: Record<string, number>;
		};

		// Validate response shape
		if (!data.base || !data.rates || typeof data.rates !== "object") {
			throw new Error("Invalid exchange rate response shape");
		}

		// Reject if any rate is negative or zero
		for (const [currency, rate] of Object.entries(data.rates)) {
			if (typeof rate !== "number" || rate <= 0) {
				throw new Error(`Invalid rate for ${currency}: ${rate}`);
			}
		}

		// Include base currency in rates for conversion math
		const rates: ExchangeRates = {
			base: data.base,
			date: data.date,
			rates: { ...data.rates, [data.base]: 1 },
		};

		cachedRates = rates;
		cacheExpiry = now + CACHE_TTL_MS;

		return rates;
	} catch (error) {
		// Stale-serve: return cached rates if available
		if (cachedRates) {
			return cachedRates;
		}
		throw error;
	}
}

/**
 * Convert price in cents from one currency to another.
 * All conversions go through EUR as the base currency.
 */
export function convertPrice(
	cents: number,
	from: string,
	to: string,
	rates: ExchangeRates,
): number {
	if (from === to) return cents;

	const fromRate = rates.rates[from];
	const toRate = rates.rates[to];

	if (fromRate == null || toRate == null) {
		// Unknown currency — return original
		return cents;
	}

	// Convert: from → EUR → to
	const centsInEur = cents / fromRate;
	const result = centsInEur * toRate;

	return Math.round(result);
}

/**
 * Reset cache — for testing only.
 */
export function resetCache(): void {
	cachedRates = null;
	cacheExpiry = 0;
}
