/**
 * LNbits API client for Lightning Network payments
 * 
 * Uses LNbits API to create and manage Lightning invoices with webhook support
 * for payment detection.
 */

// Read environment variables dynamically to ensure dotenv has loaded
function getConfig() {
  return {
    url: process.env.LNBITS_URL || '',
    apiKey: process.env.LNBITS_API_KEY || '', // Invoice/read key
    webhookSecret: process.env.LNBITS_WEBHOOK_SECRET || '',
  };
}

export interface LNbitsInvoice {
  paymentHash: string;
  paymentRequest: string; // BOLT11 invoice string
  checkingId: string;
  amount: number; // Amount in satoshis (after conversion)
  fiatAmount?: number; // Original fiat amount
  fiatCurrency?: string; // Original fiat currency
  memo: string;
  expiry: string;
  status: string;
  extra?: Record<string, any>;
}

export interface CreateInvoiceParams {
  amount: number; // Amount in the specified unit
  unit?: string; // Currency unit: 'sat', 'USD', 'PYG', etc. (default: 'sat')
  memo: string;
  webhookUrl?: string;
  expiry?: number; // Expiry in seconds (default 3600 = 1 hour)
  extra?: Record<string, any>; // Additional metadata
}

// How long a booking's Lightning invoice is valid for, in seconds. Shared
// between initial booking creation and invoice regeneration so both produce
// invoices with the same lifetime.
export const LNBITS_INVOICE_EXPIRY_SECONDS = 900; // 15 minutes

/**
 * Check if LNbits is configured
 */
export function isLNbitsConfigured(): boolean {
  const config = getConfig();
  return !!(config.url && config.apiKey);
}


/**
 * Create a Lightning invoice using LNbits
 * LNbits supports fiat currencies directly - it will convert to sats automatically
 */
export async function createInvoice(params: CreateInvoiceParams): Promise<LNbitsInvoice> {
  const config = getConfig();
  
  if (!config.url || !config.apiKey) {
    throw new Error('LNbits is not configured. Please set LNBITS_URL and LNBITS_API_KEY.');
  }

  const apiEndpoint = '/api/v1/payments';
  
  // LNbits supports fiat currencies via the 'unit' parameter
  // It will automatically convert to sats using its exchange rate provider
  const payload: any = {
    out: false, // false = create invoice for receiving payment
    amount: params.amount,
    unit: params.unit || 'sat', // Support fiat currencies like 'USD', 'PYG', etc.
    memo: params.memo,
  };

  if (params.webhookUrl) {
    payload.webhook = params.webhookUrl;
  }

  if (params.expiry) {
    payload.expiry = params.expiry;
  }

  if (params.extra) {
    payload.extra = params.extra;
  }

  console.log('Creating LNbits invoice:', {
    amount: params.amount,
    unit: payload.unit,
  });

  const response = await fetch(`${config.url}${apiEndpoint}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': config.apiKey,
    },
    body: JSON.stringify(payload),
  });

  if (!response.ok) {
    const errorText = await response.text();
    console.error('LNbits invoice creation failed:', {
      status: response.status,
      statusText: response.statusText,
      error: errorText,
    });
    throw new Error(`Failed to create Lightning invoice: ${errorText}`);
  }

  const data = await response.json();
  
  // LNbits returns amount in millisatoshis for the actual invoice
  // Convert to satoshis for display
  const amountSats = data.amount ? Math.round(data.amount / 1000) : params.amount;
  
  console.log('LNbits invoice created successfully:', {
    paymentHash: data.payment_hash,
    amountMsats: data.amount,
    amountSats,
    hasPaymentRequest: !!data.payment_request,
  });
  
  return {
    paymentHash: data.payment_hash,
    paymentRequest: data.payment_request || data.bolt11,
    checkingId: data.checking_id,
    amount: amountSats, // Amount in satoshis
    fiatAmount: params.unit && params.unit !== 'sat' ? params.amount : undefined,
    fiatCurrency: params.unit && params.unit !== 'sat' ? params.unit : undefined,
    memo: params.memo,
    expiry: data.expiry || '',
    status: data.status || 'pending',
    extra: params.extra,
  };
}

/**
 * Get invoice/payment status from LNbits
 */
export async function getPaymentStatus(paymentHash: string): Promise<{
  paid: boolean;
  status: string;
  preimage?: string;
} | null> {
  const config = getConfig();
  
  if (!config.url || !config.apiKey) {
    throw new Error('LNbits is not configured');
  }

  const apiEndpoint = `/api/v1/payments/${paymentHash}`;

  const response = await fetch(`${config.url}${apiEndpoint}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': config.apiKey,
    },
  });

  if (!response.ok) {
    if (response.status === 404) {
      return null;
    }
    throw new Error('Failed to get payment status from LNbits');
  }

  const data = await response.json();
  
  // LNbits payment status: "pending", "complete", "failed"
  // For incoming payments, "complete" means paid
  const isPaid = data.status === 'complete' || data.paid === true;
  
  return {
    paid: isPaid,
    status: data.status,
    preimage: data.preimage,
  };
}

/**
 * Verify webhook payload from LNbits
 * LNbits webhooks don't have signature verification by default,
 * but we can verify the payment hash matches and check payment status
 */
export async function verifyWebhookPayment(paymentHash: string): Promise<boolean> {
  try {
    const status = await getPaymentStatus(paymentHash);
    return status?.paid === true;
  } catch (error) {
    console.error('Error verifying webhook payment:', error);
    return false;
  }
}

/**
 * Payment status types
 */
export type LNbitsPaymentStatus = 'pending' | 'complete' | 'failed' | 'expired';

/**
 * Check if payment is complete
 */
export function isPaymentComplete(status: string): boolean {
  return status === 'complete';
}

/**
 * Check if payment is still pending
 */
export function isPaymentPending(status: string): boolean {
  return status === 'pending';
}
