import dayjs from 'dayjs';
import Decimal from 'decimal.js';
function toFiniteNumber(value) {
  var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
  var parsedValue = Number(value);
  if (!Number.isFinite(parsedValue)) return fallback;
  return parsedValue;
}
function toPositiveInt(value) {
  var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  var parsedValue = Math.floor(Number(value));
  if (!Number.isFinite(parsedValue) || parsedValue < 1) return fallback;
  return parsedValue;
}
function toPriceString(value) {
  return new Decimal(Number(value) || 0).toDecimalPlaces(2).toFixed(2);
}
function normalizeDateTime(value) {
  if (typeof value !== 'string' || !value.trim()) return null;
  var normalized = value.includes(':') ? value : "".concat(value, " 00:00:00");
  var datetime = dayjs(normalized);
  if (!datetime.isValid()) return null;
  return datetime;
}
function buildBookingDateTime(date, time) {
  if (typeof date !== 'string' || !date.trim()) return null;
  var timeText = typeof time === 'string' && time.trim() ? time.trim() : '00:00';
  var datetime = dayjs("".concat(date.trim(), " ").concat(timeText));
  if (!datetime.isValid()) return null;
  return datetime;
}
function getDurationUnit(type) {
  var normalizedType = String(type || '').toLowerCase();
  if (normalizedType === 'day' || normalizedType === 'days') return 'day';
  if (normalizedType === 'minute' || normalizedType === 'minutes') return 'minute';
  return null;
}
function getProductId(product) {
  var _product$product_id;
  var productId = toFiniteNumber((_product$product_id = product.product_id) !== null && _product$product_id !== void 0 ? _product$product_id : product.id, NaN);
  if (!Number.isFinite(productId)) return null;
  return productId;
}
function getProductVariantId(product) {
  var _product$product_vari;
  var variantId = toFiniteNumber((_product$product_vari = product.product_variant_id) !== null && _product$product_vari !== void 0 ? _product$product_vari : product.variant_id, 0);
  if (!Number.isFinite(variantId) || variantId <= 0) return undefined;
  return variantId;
}
function getFallbackPrice(params) {
  var _ref, _ref2, _ref3, _params$fallback_pric;
  var product = params.product || {};
  return toPriceString((_ref = (_ref2 = (_ref3 = (_params$fallback_pric = params.fallback_price) !== null && _params$fallback_pric !== void 0 ? _params$fallback_pric : product.price) !== null && _ref3 !== void 0 ? _ref3 : product.selling_price) !== null && _ref2 !== void 0 ? _ref2 : product.original_price) !== null && _ref !== void 0 ? _ref : 0);
}
function getProductQuantity(product) {
  var _product$num;
  return toPositiveInt((_product$num = product.num) !== null && _product$num !== void 0 ? _product$num : product.quantity, 1);
}
function shouldSplitByDuration(duration, start, end) {
  if (!duration) return false;
  if (!start || !end || !end.isAfter(start)) return false;
  var unit = getDurationUnit(duration.type);
  var value = toFiniteNumber(duration.value);
  return !!unit && value > 0;
}
function buildTimeSegments(params) {
  var booking = params.booking || {};
  var explicitDatetime = normalizeDateTime(params.datetime);
  var bookingStart = buildBookingDateTime(booking.start_date, booking.start_time);
  var start = bookingStart || explicitDatetime || dayjs();
  var bookingEnd = buildBookingDateTime(booking.end_date, booking.end_time);
  if (!shouldSplitByDuration(params.duration, start, bookingEnd)) {
    return [{
      start: start
    }];
  }
  var unit = getDurationUnit(params.duration.type);
  var value = toFiniteNumber(params.duration.value);
  var segments = [];
  var cursor = start;
  var guard = 0;
  while (cursor.isBefore(bookingEnd) && guard < 10000) {
    var next = cursor.add(value, unit);
    segments.push({
      start: cursor,
      end: next.isBefore(bookingEnd) ? next : bookingEnd !== null && bookingEnd !== void 0 ? bookingEnd : undefined
    });
    cursor = next;
    guard += 1;
  }
  return segments.length ? segments : [{
    start: start
  }];
}
function formatTimePoint(datetime) {
  return datetime.format('YYYY-MM-DD HH:mm:ss');
}
function buildPriceSegment(params) {
  var timePoint = formatTimePoint(params.segment.start);
  var quotedPrice = params.quotation && params.productId !== null ? params.quotation.getPriceForProduct({
    productId: params.productId,
    variantId: params.variantId,
    datetime: timePoint,
    customer_id: params.customerId
  }) : null;
  var unitPrice = toPriceString(quotedPrice !== null && quotedPrice !== void 0 ? quotedPrice : params.fallbackPrice);
  var quotationShelfId = quotedPrice !== null && params.quotation && params.productId !== null ? params.quotation.getQuotationShelfId({
    productId: params.productId,
    variantId: params.variantId,
    datetime: timePoint,
    customer_id: params.customerId
  }) : 0;
  return {
    start_datetime: timePoint,
    end_datetime: params.segment.end ? formatTimePoint(params.segment.end) : undefined,
    time_point: timePoint,
    unit_price: unitPrice,
    quantity: 1,
    total_price: unitPrice,
    quotation_shelf_id: quotationShelfId,
    source: quotedPrice !== null ? 'quotation' : 'fallback'
  };
}
export function calculateBaseSalesProductBookingPrice(params) {
  var _segments$find;
  var product = params.product || {};
  var productId = getProductId(product);
  var variantId = getProductVariantId(product);
  var productQuantity = getProductQuantity(product);
  var fallbackPrice = getFallbackPrice(params);
  var segments = buildTimeSegments(params).map(function (segment) {
    return buildPriceSegment({
      quotation: params.quotation,
      productId: productId,
      variantId: variantId,
      customerId: params.customer_id,
      fallbackPrice: fallbackPrice,
      segment: segment
    });
  });
  var unitPrice = segments.reduce(function (total, segment) {
    return total.plus(segment.total_price);
  }, new Decimal(0));
  var totalPrice = unitPrice.times(productQuantity);
  var quotationShelfId = ((_segments$find = segments.find(function (segment) {
    return segment.quotation_shelf_id;
  })) === null || _segments$find === void 0 ? void 0 : _segments$find.quotation_shelf_id) || 0;
  return {
    product_id: productId,
    product_variant_id: variantId !== null && variantId !== void 0 ? variantId : 0,
    customer_id: params.customer_id,
    unit_price: unitPrice.toDecimalPlaces(2).toFixed(2),
    total_price: totalPrice.toDecimalPlaces(2).toFixed(2),
    quantity: productQuantity,
    duration: params.duration,
    quotation_shelf_id: quotationShelfId,
    segments: segments
  };
}