import { v4 } from "uuid";
import { E as ErrorCode } from "./errorCodes-E8kmN1h5.js";
import { p as prisma, l as logger, a as safeStringify } from "./i18n-tiaWqB1b.js";
import { c as appConfig } from "./utils-kKqt-Je5.js";
import z from "zod";
class PrismaBookingPaymentRepository {
  constructor(prismaClient = prisma) {
    this.prismaClient = prismaClient;
  }
  async findByExternalIdIncludeBookingUserCredentials(externalId, credentialType) {
    return await this.prismaClient.payment.findFirst({
      where: {
        externalId
      },
      select: {
        id: true,
        amount: true,
        success: true,
        bookingId: true,
        booking: {
          select: {
            user: {
              select: {
                credentials: {
                  where: { type: credentialType },
                  select: { key: true }
                }
              }
            }
          }
        }
      }
    });
  }
  async createPaymentRecord(data) {
    const createdPayment = await this.prismaClient.payment.create({
      data
    });
    return createdPayment;
  }
}
const btcpayCredentialKeysSchema = z.object({
  serverUrl: z.string().url(),
  storeId: z.string(),
  apiKey: z.string(),
  webhookSecret: z.string()
});
const zeroDecimalCurrencies = ["SATS", "BTC", "JPY"];
const convertFromSmallestToPresentableCurrencyUnit = (amount, currency) => {
  if (zeroDecimalCurrencies.includes(currency.toUpperCase())) {
    return amount;
  }
  return amount / 100;
};
const log = logger.getSubLogger({ prefix: ["payment-service:btcpayserver"] });
class PaymentService {
  constructor(credentials, bookingPaymentRepository = new PrismaBookingPaymentRepository()) {
    const keyParsing = btcpayCredentialKeysSchema.safeParse(credentials.key);
    if (keyParsing.success) {
      this.credentials = keyParsing.data;
    } else {
      this.credentials = null;
    }
    this.bookingPaymentRepository = bookingPaymentRepository;
  }
  async BTCPayApiCall(endpoint, options = {}) {
    if (!this.credentials)
      throw new Error("BTCPay server credentials not found");
    const serverUrl = this.credentials.serverUrl.endsWith("/") ? this.credentials.serverUrl.slice(0, -1) : this.credentials.serverUrl;
    const url = `${serverUrl}${endpoint}`;
    const headers = {
      Authorization: `token ${this.credentials.apiKey}`,
      "Content-Type": "application/json",
      Accept: "application/json",
      ...options.headers
    };
    try {
      const response = await fetch(url, { ...options, headers });
      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`BTCPay server API error (${response.status}): ${errorText}`);
      }
      return await response.json();
    } catch (error) {
      throw error;
    }
  }
  async create(payment, bookingId, userId, username, bookerName, paymentOption, bookerEmail, bookerPhoneNumber, eventTitle, bookingTitle) {
    try {
      if (!this.credentials?.storeId) {
        throw new Error("BTCPay server: Store ID not found");
      }
      const uid = v4();
      const invoiceRequest = {
        metadata: {
          orderId: `cal-booking-${bookingId}`,
          itemDesc: bookingTitle || `Booking #${bookingId}`,
          appId: "cal.com",
          referenceId: uid,
          customerName: bookerName,
          customerEmail: bookerEmail,
          bookingDescription: bookingTitle || `Booking with ${bookerName}`
        },
        checkout: {
          buyerEmail: bookerEmail
        },
        receipt: {
          enabled: true
        },
        amount: convertFromSmallestToPresentableCurrencyUnit(payment.amount, payment.currency),
        currency: payment.currency === "BTC" ? "SATS" : payment.currency,
        additionalSearchTerms: [`cal-booking-${bookingId}`, bookerName, bookerEmail]
      };
      const invoiceResponse = await this.BTCPayApiCall(
        `/api/v1/stores/${this.credentials.storeId}/invoices`,
        { method: "POST", body: JSON.stringify(invoiceRequest) }
      );
      const paymentData = await this.bookingPaymentRepository.createPaymentRecord({
        uid,
        app: { connect: { slug: appConfig.slug } },
        booking: { connect: { id: bookingId } },
        amount: payment.amount,
        externalId: invoiceResponse.id,
        currency: payment.currency,
        fee: 0,
        success: false,
        refunded: false,
        data: Object.assign(
          {},
          {
            invoice: {
              ...invoiceResponse,
              isPaid: false,
              attendee: { name: bookerName, email: bookerEmail }
            }
          }
        )
      });
      if (!paymentData)
        throw new Error("Failed to store Payment data");
      return paymentData;
    } catch (error) {
      log.error("BTCPay server: 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("BTCPay Server does not support automatic refunds for Bitcoin payments");
  }
  async collectCard(_payment, _bookingId, _bookerEmail, _paymentOption) {
    throw new Error("Method not implemented");
  }
  chargeCard(_payment, _bookingId) {
    throw new Error("Method not implemented.");
  }
  async getPaymentPaidStatus() {
    throw new Error("Method not implemented.");
  }
  async getPaymentDetails() {
    throw new Error("Method not implemented.");
  }
  async afterPayment(_event, _booking, _paymentData) {
    return Promise.resolve();
  }
  deletePayment(_paymentId) {
    return Promise.resolve(false);
  }
  isSetupAlready() {
    return !!this.credentials;
  }
}
export {
  PaymentService
};
