import { getBreezSDK } from "$lib/breez.svelte";
import { payBolt11Invoice as payBolt11InvoiceUsingCashu } from "$lib/cashu.svelte";
import type {
  InputType,
  PreparePayOnchainRequest,
  PreparePayOnchainResponse,
  PrepareSendRequest,
  PrepareSendResponse,
} from "@breeztech/breez-sdk-liquid/web";

export async function* send(
  destination: string,
  amount = 0,
  parsed?: InputType,
) {
  try {
    yield {
      status: "Parsing destination…",
      error: null,
    };

    const breezSDK = await getBreezSDK();
    const parsedInvoice: InputType = parsed ??
      await breezSDK.parse(destination);

    if (parsedInvoice.type === "bolt11") {
      try {
        yield {
          status: "Attempting Cashu payment…",
          error: null,
        };
        await payBolt11InvoiceUsingCashu(destination);
        return {
          status: "✅ Payment sent",
          error: null,
          preimage: undefined,
          paymentHash: (parsedInvoice as any).invoice.paymentHash,
        };
      } catch (cashuErr) {
        console.warn("Cashu payment failed, falling back to Breez", cashuErr);
      }
    }

    if (parsedInvoice.type === "bitcoinAddress") {
      if (amount <= 0) {
        return {
          status: null,
          error: "Amount required for bitcoin address",
        };
      }

      const req: PreparePayOnchainRequest = {
        amount: { type: "bitcoin", receiverAmountSat: amount },
      };

      yield {
        status: "Preparing on-chain payment…",
        error: null,
      };
      const prep: PreparePayOnchainResponse = await breezSDK.preparePayOnchain(
        req,
      );

      yield {
        status: "Broadcasting…",
        error: null,
      };
      await breezSDK.payOnchain({
        address: parsedInvoice.address.address,
        prepareResponse: prep,
      });
    } else {
      const req: PrepareSendRequest = { destination };
      if (amount > 0) {
        req.amount = {
          type: "bitcoin",
          receiverAmountSat: amount,
        };
      }

      yield {
        status: "Preparing…",
        error: null,
      };
      const prep: PrepareSendResponse = await breezSDK.prepareSendPayment(req);
      yield {
        status: "Sending…",
        error: null,
      };
      const res = await breezSDK.sendPayment({ prepareResponse: prep });
      return {
        status: "✅ Payment sent",
        error: null,
        preimage: (res.payment as any)?.paymentPreimage,
        paymentHash: (res.payment as any)?.paymentHash,
      };
    }

    return {
      status: "✅ Payment sent",
      error: null,
      preimage: undefined,
      paymentHash: undefined,
    };
  } catch (e: unknown) {
    console.error("Send failed", e);
    if (e instanceof Error) {
      const raw = e.message;
      const protoMatch = raw.match(/Generic error:.*?\(\"(.+?)\"\)/);
      return {
        status: null,
        error: protoMatch ? protoMatch[1] : raw,
      };
    }
    return {
      status: null,
      error: "Send failed",
    };
  }
}
