"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const index$2 = require("./user-v6mfWQ2d.cjs");
const utils = require("./utils-U8_Jj24h.cjs");
const getRawBody = require("raw-body");
const z = require("zod");
const lightningTools = require("@getalby/lightning-tools");
const uuid = require("uuid");
const errorCodes = require("./errorCodes-ifTrQJQk.cjs");
const svix = require("svix");
const CalEventParser = require("./CalEventParser-60bHdlQO.cjs");
const httpError = require("./http-error-mkY8Ke7V.cjs");
const handlePaymentSuccess = require("./handlePaymentSuccess-7PBkBz0V.cjs");
async function handler$1(req, res) {
  if (!req.session?.user?.id) {
    return res.status(401).json({ message: "You must be logged in to do this" });
  }
  const appType = utils.config.type;
  try {
    const alreadyInstalled = await index$2.prisma.credential.findFirst({
      where: {
        type: appType,
        userId: req.session.user.id
      }
    });
    if (alreadyInstalled) {
      throw new Error("Already installed");
    }
    const installation = await index$2.prisma.credential.create({
      data: {
        type: appType,
        key: {},
        userId: req.session.user.id,
        appId: "alby"
      }
    });
    if (!installation) {
      throw new Error("Unable to create user credential for Alby");
    }
  } catch (error) {
    if (error instanceof Error) {
      return res.status(500).json({ message: error.message });
    }
    return res.status(500);
  }
  return res.status(200).json({ url: "/apps/alby/setup" });
}
const albyCredentialKeysSchema = z.object({
  account_id: z.string(),
  account_email: z.string(),
  account_lightning_address: z.string(),
  webhook_endpoint_id: z.string(),
  webhook_endpoint_secret: z.string()
});
const log = index$2.logger.getSubLogger({ prefix: ["payment-service:alby"] });
class PaymentService {
  constructor(credentials) {
    const keyParsing = albyCredentialKeysSchema.safeParse(credentials.key);
    if (keyParsing.success) {
      this.credentials = keyParsing.data;
    } else {
      this.credentials = null;
    }
  }
  async create(payment, bookingId) {
    try {
      const booking = await index$2.prisma.booking.findUnique({
        select: {
          uid: true,
          title: true
        },
        where: {
          id: bookingId
        }
      });
      if (!booking || !this.credentials?.account_lightning_address) {
        throw new Error("Alby: Booking or Lightning address not found");
      }
      const uid = uuid.v4();
      const lightningAddress = new lightningTools.LightningAddress(this.credentials.account_lightning_address);
      await lightningAddress.fetch();
      const invoice = await lightningAddress.requestInvoice({
        satoshi: payment.amount,
        payerdata: {
          appId: "cal.com",
          referenceId: uid
        }
      });
      console.log("Created invoice", invoice, uid);
      const paymentData = await index$2.prisma.payment.create({
        data: {
          uid,
          app: {
            connect: {
              slug: "alby"
            }
          },
          booking: {
            connect: {
              id: bookingId
            }
          },
          amount: payment.amount,
          externalId: invoice.paymentRequest,
          currency: payment.currency,
          data: Object.assign(
            {},
            { invoice: { ...invoice, isPaid: false } }
          ),
          fee: 0,
          refunded: false,
          success: false
        }
      });
      if (!paymentData) {
        throw new Error();
      }
      return paymentData;
    } catch (error) {
      log.error("Alby: Payment could not be created", bookingId, index$2.safeStringify(error));
      throw new Error(errorCodes.ErrorCode.PaymentCreationFailure);
    }
  }
  async update() {
    throw new Error("Method not implemented.");
  }
  async refund() {
    throw new Error("Method not implemented.");
  }
  async collectCard(_payment, _bookingId, _bookerEmail, _paymentOption) {
    throw new Error("Method not implemented");
  }
  chargeCard(_payment, _bookingId) {
    throw new Error("Method not implemented.");
  }
  getPaymentPaidStatus() {
    throw new Error("Method not implemented.");
  }
  getPaymentDetails() {
    throw new Error("Method not implemented.");
  }
  afterPayment(_event, _booking, _paymentData) {
    return Promise.resolve();
  }
  deletePayment(_paymentId) {
    return Promise.resolve(false);
  }
  isSetupAlready() {
    return !!this.credentials;
  }
}
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  PaymentService,
  albyCredentialKeysSchema
}, Symbol.toStringTag, { value: "Module" }));
function parseInvoice(body, headers, webhookEndpointSecret) {
  try {
    const wh = new svix.Webhook(webhookEndpointSecret);
    return wh.verify(body, headers);
  } catch (err) {
    console.error(err);
  }
  return null;
}
const config = {
  api: {
    bodyParser: false
  }
};
async function handler(req, res) {
  try {
    if (req.method !== "POST") {
      throw new httpError.HttpError({ statusCode: 405, message: "Method Not Allowed" });
    }
    const bodyRaw = await getRawBody(req);
    const headers = req.headers;
    const bodyAsString = bodyRaw.toString();
    const parseHeaders = webhookHeadersSchema.safeParse(headers);
    if (!parseHeaders.success) {
      console.error(parseHeaders.error);
      throw new httpError.HttpError({ statusCode: 400, message: "Bad Request" });
    }
    const { data: parsedHeaders } = parseHeaders;
    const parse = eventSchema.safeParse(JSON.parse(bodyAsString));
    if (!parse.success) {
      console.error(parse.error);
      throw new httpError.HttpError({ statusCode: 400, message: "Bad Request" });
    }
    const { data: parsedPayload } = parse;
    if (parsedPayload.metadata?.payer_data?.appId !== "cal.com") {
      throw new httpError.HttpError({ statusCode: 204, message: "Payment not for cal.com" });
    }
    const payment = await index$2.prisma.payment.findFirst({
      where: {
        uid: parsedPayload.metadata.payer_data.referenceId
      },
      select: {
        id: true,
        amount: true,
        bookingId: true,
        booking: {
          select: {
            user: {
              select: {
                credentials: {
                  where: {
                    type: "alby_payment"
                  }
                }
              }
            }
          }
        }
      }
    });
    if (!payment)
      throw new httpError.HttpError({ statusCode: 204, message: "Payment not found" });
    const key = payment.booking?.user?.credentials?.[0].key;
    if (!key)
      throw new httpError.HttpError({ statusCode: 204, message: "Credentials not found" });
    const parseCredentials = albyCredentialKeysSchema.safeParse(key);
    if (!parseCredentials.success) {
      console.error(parseCredentials.error);
      throw new httpError.HttpError({ statusCode: 500, message: "Credentials not valid" });
    }
    const credentials = parseCredentials.data;
    const albyInvoice = await parseInvoice(bodyAsString, parsedHeaders, credentials.webhook_endpoint_secret);
    if (!albyInvoice)
      throw new httpError.HttpError({ statusCode: 204, message: "Invoice not found" });
    if (albyInvoice.amount !== payment.amount) {
      throw new httpError.HttpError({ statusCode: 400, message: "invoice amount does not match payment amount" });
    }
    return await handlePaymentSuccess.handlePaymentSuccess(payment.id, payment.bookingId);
  } catch (_err) {
    const err = CalEventParser.getErrorFromUnknown(_err);
    console.error(`Webhook Error: ${err.message}`);
    return res.status(err.statusCode || 500).send({
      message: err.message,
      stack: index$2.IS_PRODUCTION ? void 0 : err.stack
    });
  }
}
const payerDataSchema = z.z.object({
  appId: z.z.string().optional(),
  referenceId: z.z.string().optional()
}).optional();
const metadataSchema = z.z.object({
  payer_data: payerDataSchema
}).optional();
const eventSchema = z.z.object({
  metadata: metadataSchema
});
const webhookHeadersSchema = z.z.object({
  "svix-id": z.z.string(),
  "svix-timestamp": z.z.string(),
  "svix-signature": z.z.string()
}).passthrough();
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  add: handler$1,
  config,
  webhook: handler
}, Symbol.toStringTag, { value: "Module" }));
exports.api = index;
exports.lib = index$1;
