const toNum = (v, fallback = 0) => (v == null ? fallback : Number(v));

export function validateOffers(
  item,
  OverAllproductBasedOfferDatas,
  CartData = [],
  TakAwayId,
  DineinId
) {
  const qty = toNum(item.OrderQty);
  const amount = toNum(item.TotalAmt);

  const allOffers =
    (OverAllproductBasedOfferDatas?.ProdDtl || []).filter(
      (offer) =>
        offer.OfferType !== "S" &&
        offer.ProdId === item?.ProdId &&
        (offer.LimitUsage > 0 || offer.LimitUsage == null) &&
        (offer.ProdVariantDetails || []).some((variant) =>
          (variant.StockDetails || []).some(
            (stock) => stock.InwardDtlId === item?.InwardDtlId
          )
        )
    ) || [];

  // filter by offer applicability
  const applicableOffers = allOffers.filter((offer) => {
    if (offer.OfferType === "I") {
      return amount >= (offer.MinPurchase || 0) || qty >= (offer.MinQty || 0);
    }
    if (offer.OfferType === "Q") {
      return qty >= (offer.FromQty || 0) && qty <= (offer.ToQty || Infinity);
    }
    if (offer.OfferType === "B") {
      const cartQty = CartData?.filter((c) => c.ProdId === item.ProdId).reduce(
        (acc, cur) => acc + toNum(cur.OrderQty),
        0
      );
      return cartQty >= (offer.MinQty || 0);
    }
    return false;
  });

  // separate B (buy/get) from others
  const buyGetOffers = [];
  let bestNonB = null;
  let bestDiscount = 0;

  for (const offer of applicableOffers) {
    if (offer.OfferType === "B") buyGetOffers.push(offer);
    else {
      const discount =
        offer.ValueType === "F"
          ? toNum(offer.OfferAmt)
          : (toNum(offer.OfferAmt) * amount) / 100;
      if (discount >= bestDiscount) {
        bestDiscount = discount;
        bestNonB = offer;
      }
    }
  }

  // dedupe circular buy/get relationships (keep simpler: remove offers that are circular duplicates)
  const dedupedBuyGet = buyGetOffers.filter((o, idx, arr) => {
    if (!o.FreeProducts && !o.FreeProductsList) return true;
    return !o.FreeProductsList?.some((fp) =>
      arr.some(
        (other) =>
          other !== o &&
          other.ProdId === fp.FreeProdId &&
          other.FreeProductsList?.some((ofp) => ofp.FreeProdId === o.ProdId)
      )
    );
  });

  const results = [];
  if (dedupedBuyGet.length > 0) {
    for (const o of dedupedBuyGet)
      results.push(buildOfferObj(o, o.OfferAmt || 0, item, DineinId, TakAwayId));
  } else if (bestNonB) {
    results.push(
      buildOfferObj(bestNonB, bestDiscount, item, DineinId, TakAwayId)
    );
  }

  return results;
}

function buildOfferObj(offer, discount, item, DineinId, TakAwayId) {
  const freeProductsRaw = offer.FreeProducts || offer.FreeProductsList;
  const freeProductsArray = freeProductsRaw
    ? Array.isArray(freeProductsRaw)
      ? freeProductsRaw
      : [freeProductsRaw]
    : [];

  return {
    OfferId: offer.OfferId || "",
    OfferAmount: discount || 0,
    OfferMode: offer.OfferType, // I/Q/B
    AcuvalOfferAmount: offer.OfferAmt,
    OfferValue: offer.OfferAmt || 0,
    TableName: offer.TableName || "",
    TableUniqueName: offer.TableUniqueName || "",
    TableUniqueId: offer.TableUniqueId || "",
    ActualFreeQty: offer.ActualFreeQty || 0,
    OfferType: offer.ValueType || "", // F / P
    Detail: offer.Detail || [],
    OfferCode: offer.OfferCode || "",
    CustId: offer.CustId || "",
    UsedCount: offer.UsedCount || 0,
    AppliesTo: offer.AppliesTo || "",
    BookingType: item.BookingTypeName === "Dine In" ? DineinId : TakAwayId,
    FreeProductsList: freeProductsArray.map((fp) => ({
      FreeProdId: fp.FreeProdId || "",
      FreeQty: fp.FreeQty || 0,
      FreeProdName: fp.FreeProdName || "",
      ProdVariantDetails: fp.ProdVariantDetails || [],
    })),
    // product-level fields
    ProdId: item?.ProdId || "",
    SinglePc: item?.SinglePc || "",
    StockAvailable: item?.StockAvailable || "",
    ProdVariantName: item?.ProdVariantName || "",
    Type: item?.Type || "",
    BookingType: item?.BookingType || 0,
    InwardDtlId: item?.InwardDtlId || "",
    ProdCat: item?.ProdCat || "",
    HalfPrice: offer?.HalfPrice,
    MinQty: offer?.MinQty,
  };
}

