/**
 * MoonPay API utilities — fiat-to-crypto on-ramp.
 *
 * MoonPay widget URLs are built with query params and signed server-side
 * with HMAC-SHA256 using the API secret. No session API needed.
 *
 * Environment: MOONPAY_ENV controls sandbox vs production.
 * Docs: https://dev.moonpay.com/
 */

import { createHmac } from 'crypto';

export type MoonPayEnv = 'sandbox' | 'production';

const WIDGET_URLS = {
	sandbox: 'https://buy-sandbox.moonpay.com',
	production: 'https://buy.moonpay.com',
} as const;

/** Get current MoonPay environment */
export function getMoonPayEnv(): MoonPayEnv {
	const env = process.env.MOONPAY_ENV?.toLowerCase();
	return env === 'production' ? 'production' : 'sandbox';
}

/** Get MoonPay publishable API key */
export function getMoonPayApiKey(): string {
	const env = getMoonPayEnv();
	return (env === 'production'
		? process.env.MOONPAY_API_KEY_PRODUCTION
		: process.env.MOONPAY_API_KEY_SANDBOX
	) || process.env.MOONPAY_API_KEY || '';
}

/** Get MoonPay secret key (for URL signing) */
export function getMoonPaySecretKey(): string {
	const env = getMoonPayEnv();
	return (env === 'production'
		? process.env.MOONPAY_SECRET_KEY_PRODUCTION
		: process.env.MOONPAY_SECRET_KEY_SANDBOX
	) || process.env.MOONPAY_SECRET_KEY || '';
}

/** Chain ID to MoonPay network name */
const NETWORK_MAP: Record<number, string> = {
	8453: 'base',
	84532: 'base',
	1: 'ethereum',
	137: 'polygon',
	42161: 'arbitrum',
};

/** Token symbol to MoonPay currency code */
const CURRENCY_MAP: Record<string, Record<string, string>> = {
	USDC: {
		base: 'usdc_base',
		ethereum: 'usdc',
		polygon: 'usdc_polygon',
		arbitrum: 'usdc_arbitrum',
	},
	ETH: {
		base: 'eth_base',
		ethereum: 'eth',
		arbitrum: 'eth_arbitrum',
	},
};

export interface MoonPayWidgetParams {
	walletAddress: string;
	email?: string;
	currencyCode?: string;         // e.g. 'usdc_base'
	baseCurrencyCode?: string;     // e.g. 'usd'
	baseCurrencyAmount?: number;   // fiat amount
	quoteCurrencyAmount?: number;  // crypto amount
	externalTransactionId?: string;
	colorCode?: string;            // hex without # (e.g. '6366f1')
	redirectURL?: string;
	showWalletAddressForm?: boolean;
}

/**
 * Build a signed MoonPay widget URL.
 * The URL is signed with HMAC-SHA256 using the secret key.
 */
export function createMoonPayWidgetUrl(params: MoonPayWidgetParams): string {
	const env = getMoonPayEnv();
	const apiKey = getMoonPayApiKey();
	const secretKey = getMoonPaySecretKey();

	if (!apiKey) throw new Error('MoonPay API key not configured');
	if (!secretKey) throw new Error('MoonPay secret key not configured');

	const base = WIDGET_URLS[env];
	const url = new URL(base);

	url.searchParams.set('apiKey', apiKey);
	url.searchParams.set('walletAddress', params.walletAddress);

	if (params.currencyCode) url.searchParams.set('currencyCode', params.currencyCode);
	if (params.baseCurrencyCode) url.searchParams.set('baseCurrencyCode', params.baseCurrencyCode);
	if (params.baseCurrencyAmount) url.searchParams.set('baseCurrencyAmount', String(params.baseCurrencyAmount));
	if (params.quoteCurrencyAmount) url.searchParams.set('quoteCurrencyAmount', String(params.quoteCurrencyAmount));
	if (params.email) url.searchParams.set('email', params.email);
	if (params.externalTransactionId) url.searchParams.set('externalTransactionId', params.externalTransactionId);
	if (params.colorCode) url.searchParams.set('colorCode', params.colorCode);
	if (params.redirectURL) url.searchParams.set('redirectURL', params.redirectURL);
	if (params.showWalletAddressForm === false) url.searchParams.set('showWalletAddressForm', 'false');

	// Sign the URL: HMAC-SHA256 of the query string (including the leading '?')
	const signature = createHmac('sha256', secretKey)
		.update(url.search)
		.digest('base64url');
	url.searchParams.set('signature', signature);

	return url.toString();
}

/**
 * Build a MoonPay widget URL for a payment request.
 * Convenience wrapper that maps token/chainId to MoonPay currency codes.
 */
export function createMoonPayPaymentUrl(opts: {
	walletAddress: string;
	token: string;
	chainId: number;
	amount?: string;
	fiatAmount?: string;
	fiatCurrency?: string;
	email?: string;
	paymentId?: string;
}): string {
	const network = NETWORK_MAP[opts.chainId] || 'base';
	const currencyCode = CURRENCY_MAP[opts.token]?.[network] || 'usdc_base';

	const params: MoonPayWidgetParams = {
		walletAddress: opts.walletAddress,
		currencyCode,
		email: opts.email,
		externalTransactionId: opts.paymentId ? `pay-${opts.paymentId}` : undefined,
		colorCode: '6366f1',
		showWalletAddressForm: false,
	};

	// Prefer fiat amount if available, otherwise use crypto amount
	if (opts.fiatAmount && parseFloat(opts.fiatAmount) > 0) {
		params.baseCurrencyAmount = parseFloat(opts.fiatAmount);
		params.baseCurrencyCode = (opts.fiatCurrency || 'USD').toLowerCase();
	} else if (opts.amount && parseFloat(opts.amount) > 0) {
		params.quoteCurrencyAmount = parseFloat(opts.amount);
	}

	return createMoonPayWidgetUrl(params);
}
