// Dynamic import to avoid build-time CDP SDK type checking

/**
 * Configuration for JWT generation
 */
export interface JWTConfig {
  method?: string;
  host?: string;
  path?: string;
  expiresIn?: number;
}

/**
 * Address configuration for session tokens
 */
export interface AddressConfig {
  address: string;
  blockchains: string[];
}

/**
 * Session token request parameters
 */
export interface SessionTokenParams {
  addresses: AddressConfig[];
  assets?: string[];
}

/**
 * Onramp URL generation parameters
 */
export interface OnrampUrlParams {
  addresses: AddressConfig[];
  assets?: string[];
  defaultAsset?: string;
  defaultNetwork?: string;
  presetFiatAmount?: number;
  presetCryptoAmount?: number;
  redirectUrl?: string;
  partnerUserId?: string;
}

/**
 * Generate a JSON Web Token (JWT) for CDP API authentication.
 * Uses the CDP SDK to handle all key formats automatically.
 * 
 * @param config - JWT configuration options
 * @returns Promise<string> - The generated JWT token
 * 
 * @example
 * ```typescript
 * const jwt = await generateJWT({
 *   method: 'POST',
 *   path: '/onramp/v1/token'
 * });
 * ```
 */
export async function generateJWT(config: JWTConfig = {}): Promise<string> {
  const privateKeyString = process.env.CDP_API_KEY_PRIVATE_KEY || process.env.CDP_SECRET_KEY;
  const keyName = process.env.CDP_API_KEY_NAME || process.env.CDP_SECRET_KEY_NAME;

  if (!privateKeyString || !keyName) {
    throw new Error(
      'CDP API credentials are required. Set CDP_API_KEY_PRIVATE_KEY and CDP_API_KEY_NAME environment variables.'
    );
  }

  const {
    method = 'POST',
    host = 'api.developer.coinbase.com',
    path = '/onramp/v1/token',
    expiresIn = 120
  } = config;

  try {
    // Use eval to avoid TypeScript trying to resolve the module during build time
    const cdpSdkAuth = await eval('import("@coinbase/cdp-sdk/auth")');
    
    // Use CDP SDK to generate JWT - handles all key formats correctly
    const jwt = await cdpSdkAuth.generateJwt({
      apiKeyId: keyName,
      apiKeySecret: privateKeyString,
      requestMethod: method,
      requestHost: host,
      requestPath: path,
      expiresIn
    });

    return jwt;
  } catch (error) {
    console.error('JWT generation failed:', error);
    console.error('Key format detected:', privateKeyString.startsWith('-----BEGIN') ? 'PEM' : 'Base64');
    throw new Error(
      'Failed to generate JWT. Make sure you have @coinbase/cdp-sdk installed:\n' +
      'npm install @coinbase/cdp-sdk\n\n' +
      'Original error: ' + (error instanceof Error ? error.message : 'Unknown error')
    );
  }
}

/**
 * Create a session token for initializing the onramp widget.
 * Session tokens are single-use and expire after 5 minutes.
 * 
 * @param jwt - The JWT token for authentication
 * @param params - Session token parameters
 * @returns Promise<string> - The session token
 * 
 * @example
 * ```typescript
 * const jwt = await generateJWT();
 * const sessionToken = await createSessionToken(jwt, {
 *   addresses: [{
 *     address: '0x1234...5678',
 *     blockchains: ['base', 'ethereum']
 *   }],
 *   assets: ['USDC', 'ETH']
 * });
 * ```
 */
export async function createSessionToken(
  jwt: string,
  params: SessionTokenParams
): Promise<string> {
  const response = await fetch('https://api.developer.coinbase.com/onramp/v1/token', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${jwt}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(params)
  });

  if (!response.ok) {
    const errorText = await response.text();
    let errorMessage = `Failed to create session token: ${response.status}`;
    
    try {
      const errorData = JSON.parse(errorText);
      errorMessage = errorData.message || errorData.error || errorMessage;
    } catch {
      errorMessage += ` - ${errorText}`;
    }
    
    throw new Error(errorMessage);
  }

  const data = await response.json();
  return data.token || data.data?.token;
}

/**
 * Generate a complete onramp URL with session token and parameters.
 * This is a convenience function that combines JWT generation, session token creation, and URL building.
 * 
 * @param params - Onramp URL parameters
 * @returns Promise<string> - The complete onramp URL
 * 
 * @example
 * ```typescript
 * const onrampUrl = await generateOnrampUrl({
 *   addresses: [{
 *     address: '0x1234...5678',
 *     blockchains: ['base']
 *   }],
 *   defaultAsset: 'USDC',
 *   presetFiatAmount: 50
 * });
 * ```
 */
export async function generateOnrampUrl(params: OnrampUrlParams): Promise<string> {
  // Generate JWT and session token
  const jwt = await generateJWT();
  const sessionToken = await createSessionToken(jwt, {
    addresses: params.addresses,
    assets: params.assets
  });

  // Build URL with session token and optional parameters
  const url = new URL('https://pay.coinbase.com/buy/select-asset');
  url.searchParams.set('sessionToken', sessionToken);
  
  if (params.defaultAsset) {
    url.searchParams.set('defaultAsset', params.defaultAsset);
  }
  
  if (params.defaultNetwork) {
    url.searchParams.set('defaultNetwork', params.defaultNetwork);
  }
  
  if (params.presetFiatAmount) {
    url.searchParams.set('presetFiatAmount', params.presetFiatAmount.toString());
  }
  
  if (params.presetCryptoAmount) {
    url.searchParams.set('presetCryptoAmount', params.presetCryptoAmount.toString());
  }
  
  if (params.redirectUrl) {
    url.searchParams.set('redirectUrl', params.redirectUrl);
  }
  
  if (params.partnerUserId) {
    url.searchParams.set('partnerUserId', params.partnerUserId);
  }

  return url.toString();
}

/**
 * Guest checkout limits as defined by Coinbase
 */
export const GUEST_CHECKOUT_LIMITS = {
  minimumAmount: 5,    // $5 minimum
  weeklyLimit: 500,    // $500 weekly limit
  country: 'US'        // US residents only
} as const;

/**
 * Supported blockchain networks
 */
export const SUPPORTED_NETWORKS = {
  BASE: 'base',
  ETHEREUM: 'ethereum',
  ARBITRUM: 'arbitrum',
  OPTIMISM: 'optimism',
  POLYGON: 'polygon'
} as const;

/**
 * Common asset symbols
 */
export const SUPPORTED_ASSETS = {
  ETHEREUM: 'ETH',
  USD_COIN: 'USDC',
  BITCOIN: 'BTC',
  TETHER: 'USDT',
  DAI: 'DAI'
} as const;

/**
 * Validate wallet address format
 */
export function isValidEthereumAddress(address: string): boolean {
  return /^0x[a-fA-F0-9]{40}$/.test(address);
}

/**
 * Validate amount within guest checkout limits
 */
export function validateGuestCheckoutAmount(amount: number): {
  isValid: boolean;
  error?: string;
} {
  if (amount < GUEST_CHECKOUT_LIMITS.minimumAmount) {
    return {
      isValid: false,
      error: `Amount must be at least $${GUEST_CHECKOUT_LIMITS.minimumAmount}`
    };
  }
  
  if (amount > GUEST_CHECKOUT_LIMITS.weeklyLimit) {
    return {
      isValid: false,
      error: `Amount cannot exceed $${GUEST_CHECKOUT_LIMITS.weeklyLimit} (weekly limit)`
    };
  }
  
  return { isValid: true };
}