const LNBITS_URL = (process.env.LNBITS_URL || 'https://legend.lnbits.com').replace(/\/$/, '');
const LNBITS_API_KEY = process.env.LNBITS_API_KEY || '';

export interface CreateInvoiceResult {
  payment_hash: string;
  payment_request: string;
  checking_id: string;
}

function pickBolt11(data: Record<string, unknown>): string {
  const pr = data.payment_request ?? data.bolt11;
  if (typeof pr === 'string' && pr.length > 0) return pr;
  return '';
}

export async function createIncomingInvoice(params: {
  amountSats: number;
  memo: string;
  webhookUrl: string;
  expirySeconds?: number;
}): Promise<CreateInvoiceResult> {
  if (!LNBITS_API_KEY) {
    throw new Error('LNBITS_API_KEY is not configured');
  }

  const body: Record<string, unknown> = {
    out: false,
    amount: params.amountSats,
    unit: 'sat',
    memo: params.memo,
    expiry: params.expirySeconds ?? 3600,
    webhook: params.webhookUrl,
  };

  const res = await fetch(`${LNBITS_URL}/api/v1/payments`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': LNBITS_API_KEY,
    },
    body: JSON.stringify(body),
  });

  const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;

  if (!res.ok) {
    const detail =
      typeof data.detail === 'string'
        ? data.detail
        : Array.isArray(data.detail)
          ? JSON.stringify(data.detail)
          : typeof data.message === 'string'
            ? data.message
            : res.statusText;
    throw new Error(`LNbits invoice failed: ${detail || res.status}`);
  }

  const payment_hash = typeof data.payment_hash === 'string' ? data.payment_hash : '';
  const payment_request = pickBolt11(data);
  const checking_id =
    typeof data.checking_id === 'string' && data.checking_id.length > 0
      ? data.checking_id
      : payment_hash;

  if (!payment_hash || !payment_request) {
    throw new Error('LNbits returned an unexpected invoice payload');
  }

  return { payment_hash, payment_request, checking_id };
}

export interface PaymentVerifyResult {
  paid: boolean;
  amountMsat?: number;
}

/** Verify invoice belongs to our wallet and is paid (requires API key). */
export async function verifyIncomingPaymentPaid(paymentHash: string): Promise<PaymentVerifyResult> {
  if (!LNBITS_API_KEY) {
    throw new Error('LNBITS_API_KEY is not configured');
  }

  const res = await fetch(`${LNBITS_URL}/api/v1/payments/${paymentHash}`, {
    headers: { 'X-Api-Key': LNBITS_API_KEY },
  });

  if (res.status === 404) {
    return { paid: false };
  }

  const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;

  if (!res.ok) {
    return { paid: false };
  }

  const paid = data.paid === true;
  let amountMsat: number | undefined;
  const details = data.details as Record<string, unknown> | undefined;
  if (details && typeof details.amount === 'number') {
    amountMsat = details.amount;
  }

  return { paid, amountMsat };
}

/** Public LNbits poll (no key): { paid: boolean } */
export async function getPublicPaymentStatus(paymentHash: string): Promise<boolean> {
  const res = await fetch(`${LNBITS_URL}/api/v1/payments/${paymentHash}`);
  if (!res.ok) return false;
  const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;
  return data.paid === true;
}
