import type {
  StorefrontCart,
  StorefrontCartItem,
  StorefrontProductCard,
  StorefrontProductDetail,
  StorefrontProductVariation,
} from "@/types/storefront";

export function parseLocalizedMoney(value: string) {
  const numeric = value.replace(/[^\d,.-]/g, "").trim();

  if (!numeric) {
    return null;
  }

  const normalized = numeric.includes(",")
    ? numeric.replace(/\./g, "").replace(",", ".")
    : numeric;

  const amount = Number.parseFloat(normalized);

  return Number.isFinite(amount) ? amount : null;
}

export function formatEuroAmount(value: number) {
  return new Intl.NumberFormat("hr-HR", {
    style: "currency",
    currency: "EUR",
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  }).format(value);
}

function buildOptimisticCartItemKey(productId: number) {
  return `optimistic:${productId}:${Date.now()}:${Math.random().toString(36).slice(2, 8)}`;
}

function buildVariationSummary(variation?: StorefrontProductVariation | null) {
  if (!variation) {
    return [];
  }

  return variation.attributes.map((attribute) => ({
    label: attribute.label,
    value: attribute.value,
  }));
}

export function createOptimisticCartItemFromProductCard(
  product: StorefrontProductCard,
  quantity: number,
): StorefrontCartItem {
  const unitPrice = product.salePrice || product.price;
  const unitAmount = parseLocalizedMoney(unitPrice) ?? 0;

  return {
    key: buildOptimisticCartItemKey(product.id),
    productId: product.id,
    name: product.name,
    href: product.href,
    label: product.brand?.name ?? product.category?.name ?? "Proizvod",
    image: product.featuredImage,
    quantity,
    variation: [],
    unitPrice,
    total: formatEuroAmount(unitAmount * quantity),
    regularPrice: product.regularPrice,
    isOnSale: product.isOnSale,
  };
}

export function createOptimisticCartItemFromProductDetail(
  product: StorefrontProductDetail,
  quantity: number,
  variation?: StorefrontProductVariation | null,
): StorefrontCartItem {
  const unitPrice = variation?.price || product.salePrice || product.price;
  const unitAmount = parseLocalizedMoney(unitPrice) ?? 0;

  return {
    key: buildOptimisticCartItemKey(product.id),
    productId: product.id,
    name: product.name,
    href: product.href,
    label: product.brand?.name ?? product.category?.name ?? "Proizvod",
    image: product.featuredImage,
    quantity,
    variation: buildVariationSummary(variation),
    unitPrice,
    total: formatEuroAmount(unitAmount * quantity),
    regularPrice: variation?.regularPrice || product.regularPrice,
    isOnSale: variation?.isOnSale ?? product.isOnSale,
  };
}

export function applyOptimisticCartAddition(
  cart: StorefrontCart,
  item: StorefrontCartItem,
): StorefrontCart {
  const lineTotal = parseLocalizedMoney(item.total) ?? 0;
  const currentTotal = parseLocalizedMoney(cart.total) ?? 0;
  const currentSubtotal = parseLocalizedMoney(cart.subtotal) ?? 0;

  return {
    ...cart,
    itemCount: cart.itemCount + item.quantity,
    subtotal: formatEuroAmount(currentSubtotal + lineTotal),
    total: formatEuroAmount(currentTotal + lineTotal),
    isEmpty: false,
    items: [item, ...cart.items],
  };
}

export function applyOptimisticCartQuantity(
  cart: StorefrontCart,
  key: string,
  quantity: number,
): StorefrontCart {
  const item = cart.items.find((entry) => entry.key === key);

  if (!item || quantity < 1 || item.quantity === quantity) {
    return cart;
  }

  const unitPrice = parseLocalizedMoney(item.unitPrice);
  const currentLineTotal = parseLocalizedMoney(item.total);
  const currentCartTotal = parseLocalizedMoney(cart.total);
  const currentCartSubtotal = parseLocalizedMoney(cart.subtotal);

  if (
    unitPrice === null ||
    currentLineTotal === null ||
    currentCartTotal === null ||
    currentCartSubtotal === null
  ) {
    return {
      ...cart,
      itemCount: cart.itemCount - item.quantity + quantity,
      items: cart.items.map((entry) =>
        entry.key === key
          ? {
              ...entry,
              quantity,
            }
          : entry,
      ),
    };
  }

  const nextLineTotal = unitPrice * quantity;
  const lineDelta = nextLineTotal - currentLineTotal;

  return {
    ...cart,
    itemCount: cart.itemCount - item.quantity + quantity,
    subtotal: formatEuroAmount(currentCartSubtotal + lineDelta),
    total: formatEuroAmount(currentCartTotal + lineDelta),
    items: cart.items.map((entry) =>
      entry.key === key
        ? {
            ...entry,
            quantity,
            total: formatEuroAmount(nextLineTotal),
          }
        : entry,
    ),
  };
}
