import { p as prisma, l as logger, b as safeStringify, ax as IS_PRODUCTION } from "./user--mpkKOwW.js";
import { c as config$1 } from "./utils-xu1OORoz.js";
import getRawBody from "raw-body";
import z__default, { z } from "zod";
import { LightningAddress } from "@getalby/lightning-tools";
import { v4 } from "uuid";
import { E as ErrorCode } from "./errorCodes-E8kmN1h5.js";
import { Webhook } from "svix";
import { l as getErrorFromUnknown } from "./CalEventParser-ZzmnrFso.js";
import { H as HttpError } from "./http-error-RJXCPZV2.js";
import { h as handlePaymentSuccess } from "./handlePaymentSuccess-U0logfNl.js";
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 = config$1.type;
  try {
    const alreadyInstalled = await prisma.credential.findFirst({
      where: {
        type: appType,
        userId: req.session.user.id
      }
    });
    if (alreadyInstalled) {
      throw new Error("Already installed");
    }
    const installation = await 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__default.object({
  account_id: z__default.string(),
  account_email: z__default.string(),
  account_lightning_address: z__default.string(),
  webhook_endpoint_id: z__default.string(),
  webhook_endpoint_secret: z__default.string()
});
const log = 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 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 = v4();
      const lightningAddress = new 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 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, safeStringify(error));
      throw new Error(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 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({ 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({ 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({ statusCode: 400, message: "Bad Request" });
    }
    const { data: parsedPayload } = parse;
    if (parsedPayload.metadata?.payer_data?.appId !== "cal.com") {
      throw new HttpError({ statusCode: 204, message: "Payment not for cal.com" });
    }
    const payment = await 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({ statusCode: 204, message: "Payment not found" });
    const key = payment.booking?.user?.credentials?.[0].key;
    if (!key)
      throw new HttpError({ statusCode: 204, message: "Credentials not found" });
    const parseCredentials = albyCredentialKeysSchema.safeParse(key);
    if (!parseCredentials.success) {
      console.error(parseCredentials.error);
      throw new 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({ statusCode: 204, message: "Invoice not found" });
    if (albyInvoice.amount !== payment.amount) {
      throw new HttpError({ statusCode: 400, message: "invoice amount does not match payment amount" });
    }
    return await handlePaymentSuccess(payment.id, payment.bookingId);
  } catch (_err) {
    const err = getErrorFromUnknown(_err);
    console.error(`Webhook Error: ${err.message}`);
    return res.status(err.statusCode || 500).send({
      message: err.message,
      stack: IS_PRODUCTION ? void 0 : err.stack
    });
  }
}
const payerDataSchema = z.object({
  appId: z.string().optional(),
  referenceId: z.string().optional()
}).optional();
const metadataSchema = z.object({
  payer_data: payerDataSchema
}).optional();
const eventSchema = z.object({
  metadata: metadataSchema
});
const webhookHeadersSchema = z.object({
  "svix-id": z.string(),
  "svix-timestamp": z.string(),
  "svix-signature": z.string()
}).passthrough();
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  add: handler$1,
  config,
  webhook: handler
}, Symbol.toStringTag, { value: "Module" }));
export {
  index as api,
  index$1 as lib
};
