"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

exports.useDynamicPricing = useDynamicPricing;
var _react = require("react");
var _util = require("@ocap/util");
var _util2 = require("../libs/util");
function extractQuoteMeta(items) {
  if (!items?.length) {
    return null;
  }
  let exchangeRate = null;
  let baseCurrency = null;
  let expiresAt = null;
  let providerName = null;
  let providerId = null;
  let rateTimestampMs = null;
  let slippagePercent = null;
  items.forEach(item => {
    const price = item.upsell_price || item.price;
    const rate = item?.exchange_rate;
    if (!exchangeRate && rate) {
      exchangeRate = rate;
    }
    const base = price?.base_currency;
    if (!baseCurrency && base) {
      baseCurrency = base;
    }
    const expires = item?.expires_at;
    if (expires) {
      expiresAt = expiresAt === null ? expires : Math.min(expiresAt, expires);
    }
    const itemProviderName = item?.rate_provider_name;
    if (!providerName && itemProviderName) {
      providerName = itemProviderName;
    }
    const itemProviderId = item?.rate_provider_id;
    if (!providerId && itemProviderId) {
      providerId = itemProviderId;
    }
    const itemRateTimestamp = item?.rate_timestamp_ms;
    if (!rateTimestampMs && Number.isFinite(Number(itemRateTimestamp))) {
      rateTimestampMs = Number(itemRateTimestamp);
    }
    const itemSlippage = item?.slippage_percent;
    if (slippagePercent === null && Number.isFinite(Number(itemSlippage))) {
      slippagePercent = Number(itemSlippage);
    }
  });
  return {
    exchangeRate,
    baseCurrency: baseCurrency || "USD",
    expiresAt,
    providerName,
    providerId,
    rateTimestampMs,
    slippagePercent
  };
}
function calculateTokenAmount(items, rate, currencyDecimal, trialing = false) {
  const usdTotal = items.reduce((acc, item) => {
    const price = item.upsell_price || item.price;
    if (trialing && price?.type === "recurring") {
      return acc;
    }
    if (price?.type === "recurring" && price?.recurring?.usage_type === "metered") {
      return acc;
    }
    const baseAmount = price?.base_amount;
    if (baseAmount) {
      const quantity = item.quantity || 1;
      return acc + Number(baseAmount) * quantity;
    }
    return acc;
  }, 0);
  if (usdTotal <= 0) {
    return null;
  }
  const rateNum = Number(rate);
  if (rateNum <= 0) {
    return null;
  }
  const tokenAmount = usdTotal / rateNum;
  const tokenAmountUnit = (0, _util.fromTokenToUnit)(tokenAmount.toFixed(currencyDecimal || 8), currencyDecimal || 8);
  return tokenAmountUnit.toString();
}
function extractQuoteLockedAt(paymentIntent, checkoutSession) {
  if (paymentIntent?.quote_locked_at) {
    const lockedAtMs = new Date(paymentIntent.quote_locked_at).getTime();
    if (Number.isFinite(lockedAtMs)) {
      return Math.floor(lockedAtMs / 1e3);
    }
  }
  const metaLockedAt = checkoutSession?.metadata?.quote_locked_at;
  if (typeof metaLockedAt === "number") {
    return metaLockedAt;
  }
  if (typeof metaLockedAt === "string") {
    const parsed = Number(metaLockedAt);
    if (Number.isFinite(parsed)) {
      return parsed;
    }
  }
  return null;
}
function useDynamicPricing(options) {
  const {
    items,
    currency,
    liveRate,
    liveQuoteSnapshot,
    checkoutSession,
    paymentIntent,
    locale = "en",
    isStripePayment = false,
    isSubscription = checkoutSession?.mode === "subscription" || checkoutSession?.mode === "setup",
    slippageConfig,
    trialInDays = 0,
    trialEnd = 0,
    discounts
  } = options;
  const currentTime = Math.floor(Date.now() / 1e3);
  const trialing = trialInDays > 0 || trialEnd > currentTime;
  const hasDynamicPricing = (0, _react.useMemo)(() => items.some(item => (item.upsell_price || item.price)?.pricing_type === "dynamic"), [items]);
  const quoteMeta = (0, _react.useMemo)(() => hasDynamicPricing ? extractQuoteMeta(items) : null, [items, hasDynamicPricing]);
  const rateInfo = (0, _react.useMemo)(() => ({
    exchangeRate: isStripePayment ? null : liveRate?.rate || quoteMeta?.exchangeRate || null,
    baseCurrency: liveRate?.base_currency || quoteMeta?.baseCurrency || "USD",
    providerName: isStripePayment ? null : liveRate?.provider_name || quoteMeta?.providerName || null,
    providerId: isStripePayment ? null : liveRate?.provider_id || quoteMeta?.providerId || null,
    timestampMs: isStripePayment ? null : liveRate?.timestamp_ms || quoteMeta?.rateTimestampMs || null,
    fetchedAt: isStripePayment ? null : liveRate?.fetched_at || null
    // When we fetched the data
  }), [liveRate, quoteMeta, isStripePayment]);
  const calculatedTokenAmount = (0, _react.useMemo)(() => {
    if (isStripePayment || !hasDynamicPricing || !liveRate?.rate) {
      return null;
    }
    return calculateTokenAmount(items, liveRate.rate, currency.decimal, trialing);
  }, [hasDynamicPricing, liveRate?.rate, items, currency.decimal, isStripePayment, trialing]);
  const calculatedDiscountAmount = (0, _react.useMemo)(() => {
    if (!discounts?.length) {
      return null;
    }
    const couponDetails = discounts[0]?.coupon_details;
    if (!couponDetails) {
      return null;
    }
    if (isStripePayment) {
      const discountableSubtotalCents = items.reduce((sum, item) => {
        if (!item.discountable) {
          return sum;
        }
        const price = item.upsell_price || item.price;
        if (trialing && price?.type === "recurring") {
          return sum;
        }
        if (price?.type === "recurring" && price?.recurring?.usage_type === "metered") {
          return sum;
        }
        const isDynamic = price?.pricing_type === "dynamic";
        const baseAmount = price?.base_amount;
        let amountCents;
        if (isDynamic && baseAmount !== void 0 && baseAmount !== null) {
          amountCents = Number(baseAmount) * 100;
        } else {
          const unitAmount = price?.unit_amount;
          if (!unitAmount) {
            return sum;
          }
          amountCents = Number(unitAmount);
        }
        const quantity = item.quantity || 1;
        return sum + amountCents * quantity;
      }, 0);
      if (discountableSubtotalCents <= 0) {
        return null;
      }
      if (couponDetails.percent_off && couponDetails.percent_off > 0) {
        const discountCents = Math.round(discountableSubtotalCents * couponDetails.percent_off / 100);
        return discountCents.toString();
      }
      if (couponDetails.amount_off) {
        const amountOffCents = Number(couponDetails.amount_off);
        if (Number.isFinite(amountOffCents) && amountOffCents > 0) {
          return Math.min(amountOffCents, discountableSubtotalCents).toString();
        }
      }
      return null;
    }
    if (!hasDynamicPricing || !liveRate?.rate) {
      return null;
    }
    const rateNum = Number(liveRate.rate);
    if (rateNum <= 0) {
      return null;
    }
    const discountableSubtotal = items.reduce((sum, item) => {
      if (!item.discountable) {
        return sum;
      }
      const price = item.upsell_price || item.price;
      if (trialing && price?.type === "recurring") {
        return sum;
      }
      if (price?.type === "recurring" && price?.recurring?.usage_type === "metered") {
        return sum;
      }
      const baseAmount = price?.base_amount;
      if (!baseAmount) {
        return sum;
      }
      const quantity = item.quantity || 1;
      const tokenAmount = Number(baseAmount) * quantity / rateNum;
      return sum + tokenAmount;
    }, 0);
    if (discountableSubtotal <= 0) {
      return null;
    }
    if (couponDetails.percent_off && couponDetails.percent_off > 0) {
      const discountAmount = discountableSubtotal * couponDetails.percent_off / 100;
      const discountAmountUnit = (0, _util.fromTokenToUnit)(discountAmount.toFixed(currency.decimal || 8), currency.decimal || 8);
      return discountAmountUnit.toString();
    }
    if (couponDetails.amount_off) {
      const amountOff = couponDetails.currency_id === currency.id ? couponDetails.amount_off : couponDetails.currency_options?.[currency.id]?.amount_off;
      if (!amountOff) {
        return null;
      }
      const subtotalUnit = (0, _util.fromTokenToUnit)(discountableSubtotal.toFixed(currency.decimal || 8), currency.decimal || 8);
      const amountOffBN = new _util.BN(amountOff);
      const subtotalBN = new _util.BN(subtotalUnit);
      return _util.BN.min(amountOffBN, subtotalBN).toString();
    }
    return null;
  }, [isStripePayment, hasDynamicPricing, liveRate?.rate, discounts, items, trialing, currency.decimal, currency.id]);
  const rateDisplay = (0, _react.useMemo)(() => {
    if (!rateInfo.exchangeRate) {
      return null;
    }
    const formattedRate = (0, _util2.formatExchangeRate)(rateInfo.exchangeRate);
    if (!formattedRate) {
      return null;
    }
    if (rateInfo.baseCurrency === "USD") {
      return `$${formattedRate}`;
    }
    return `${formattedRate} ${rateInfo.baseCurrency}`;
  }, [rateInfo]);
  const quoteLockedAt = (0, _react.useMemo)(() => extractQuoteLockedAt(paymentIntent, checkoutSession), [paymentIntent, checkoutSession]);
  const isPriceLocked = (0, _react.useMemo)(() => {
    if (!quoteLockedAt) return false;
    const now = Math.floor(Date.now() / 1e3);
    const lockRemaining = quoteLockedAt + 180 - now;
    return lockRemaining > 0;
  }, [quoteLockedAt]);
  const lockExpired = (0, _react.useMemo)(() => {
    if (!quoteLockedAt) return false;
    const now = Math.floor(Date.now() / 1e3);
    const lockRemaining = quoteLockedAt + 180 - now;
    return lockRemaining <= 0;
  }, [quoteLockedAt]);
  const currentSlippagePercent = (0, _react.useMemo)(() => {
    let slippageValue = quoteMeta?.slippagePercent;
    if (slippageValue === null || slippageValue === void 0) {
      slippageValue = slippageConfig?.percent ?? checkoutSession?.metadata?.slippage?.percent ?? checkoutSession?.slippage_percent;
    }
    if (slippageValue === null || slippageValue === void 0) {
      slippageValue = 0.5;
    }
    return slippageValue;
  }, [quoteMeta?.slippagePercent, slippageConfig?.percent, checkoutSession]);
  const providerDisplay = (0, _react.useMemo)(() => {
    const fallback = "\u2014";
    if (liveRate?.provider_display) {
      return liveRate.provider_display;
    }
    if (!rateInfo.providerName && !rateInfo.providerId) {
      return fallback;
    }
    return rateInfo.providerName || rateInfo.providerId || fallback;
  }, [liveRate?.provider_display, rateInfo.providerName, rateInfo.providerId]);
  const formatTotalDisplay = (totalAmountValue, fallback = "\u2014") => {
    if (hasDynamicPricing && calculatedTokenAmount) {
      const displayAmount = (0, _util.fromUnitToToken)(calculatedTokenAmount, currency.decimal);
      const numericValue2 = Number(displayAmount);
      if (Number.isFinite(numericValue2)) {
        return (0, _util2.formatDynamicPrice)(displayAmount, true, 6);
      }
    }
    if (hasDynamicPricing && liveQuoteSnapshot?.quoted_amount) {
      const snapshotAmount = (0, _util.fromUnitToToken)(liveQuoteSnapshot.quoted_amount, currency.decimal);
      const numericValue2 = Number(snapshotAmount);
      if (Number.isFinite(numericValue2)) {
        return (0, _util2.formatDynamicPrice)(snapshotAmount, true, 6);
      }
    }
    if (totalAmountValue === null || totalAmountValue === void 0 || totalAmountValue === "") {
      return fallback;
    }
    const numericValue = Number(totalAmountValue);
    if (!Number.isFinite(numericValue)) {
      return fallback;
    }
    return (0, _util2.formatDynamicPrice)(totalAmountValue, hasDynamicPricing, 6);
  };
  const calculateUsdDisplay = totalAmountValue => {
    const fallback = "\u2014";
    if (!hasDynamicPricing || !totalAmountValue || totalAmountValue === fallback) {
      return null;
    }
    const numericValue = Number(totalAmountValue);
    if (!Number.isFinite(numericValue) || numericValue < 0) {
      return null;
    }
    if (numericValue === 0) {
      return (0, _util2.formatUsdAmount)("0", locale);
    }
    const {
      exchangeRate
    } = rateInfo;
    if (!exchangeRate) {
      return null;
    }
    const totalAmountInUnits = (0, _util.fromTokenToUnit)(totalAmountValue, currency.decimal);
    const totalUsd = (0, _util2.getUsdAmountFromTokenUnits)(new _util.BN(totalAmountInUnits), currency.decimal, exchangeRate);
    if (!totalUsd) {
      return null;
    }
    return (0, _util2.formatUsdAmount)(totalUsd, locale);
  };
  const buildQuoteDetailRows = t => {
    if (!hasDynamicPricing) {
      return [];
    }
    const rows = [];
    const fallback = "\u2014";
    if (rateDisplay) {
      const displayTimestamp = rateInfo.fetchedAt || rateInfo.timestampMs;
      const updatedAt = displayTimestamp ? (0, _util2.formatDateTime)(displayTimestamp) : fallback;
      rows.push({
        label: t("payment.checkout.quote.detailProvider"),
        value: providerDisplay
      }, {
        label: t("payment.checkout.quote.detailUpdatedAt"),
        value: updatedAt
      });
    }
    if (isSubscription) {
      let slippageDisplay = `${currentSlippagePercent}%`;
      if (slippageConfig?.mode === "rate" && slippageConfig.min_acceptable_rate) {
        const formattedRate = (0, _util2.formatExchangeRate)(slippageConfig.min_acceptable_rate);
        const displayRate = formattedRate || slippageConfig.min_acceptable_rate;
        const displayCurrency = slippageConfig.base_currency || rateInfo.baseCurrency || "USD";
        const displayText = displayCurrency === "USD" ? `$${displayRate}` : `${displayRate} ${displayCurrency}`;
        slippageDisplay = `${displayText}`;
      }
      rows.push({
        label: t("payment.checkout.quote.detailSlippage"),
        value: slippageDisplay,
        isSlippage: true,
        tooltip: t("payment.checkout.quote.slippage.tooltip")
      });
    }
    return rows;
  };
  return {
    // Flags
    hasDynamicPricing,
    isPriceLocked,
    lockExpired,
    // Data
    quoteMeta,
    rateInfo,
    quoteLockedAt,
    calculatedTokenAmount,
    calculatedDiscountAmount,
    currentSlippagePercent,
    // Display helpers
    rateDisplay,
    providerDisplay,
    formatTotalDisplay,
    calculateUsdDisplay,
    buildQuoteDetailRows
  };
}
module.exports = useDynamicPricing;