import { describe, it, expect } from "vitest";
import { computeSubtotal, computeCartTotals, type CartLine } from "../cartTotals";
import type { Product } from "../payload";

const product = (overrides: Partial<Product> = {}): Product => ({
  id: "todo-karten",
  numericId: 1,
  name: "ToDo-Karten",
  subline: null,
  layout: [],
  description: null,
  descriptionText: "",
  sku: null,
  price: 12.9,
  compareAtPrice: null,
  image: "",
  gallery: [],
  href: null,
  active: true,
  updatedAt: new Date().toISOString(),
  spotlight: false,
  spotlightEyebrow: null,
  spotlightHeadline: null,
  spotlightText: null,
  spotlightImage: null,
  spotlightShowWishlist: false,
  variants: [],
  outOfStock: false,
  lowStock: false,
  maxQty: null,
  taxRatePercent: null,
  noShippingCost: false,
  categories: [],
  relatedProduct: null,
  usps: [],
  badge: "none",
  ...overrides,
});

const line = (qty: number, productOverrides: Partial<Product> = {}): CartLine => ({ entry: { qty }, product: product(productOverrides) });

describe("computeSubtotal", () => {
  it("sums quantity × price across lines", () => {
    expect(computeSubtotal([line(2, { price: 10 }), line(1, { price: 5 })])).toBe(25);
  });

  it("returns 0 for an empty cart", () => {
    expect(computeSubtotal([])).toBe(0);
  });
});

describe("computeCartTotals", () => {
  it("adds shipping on top of the subtotal with no discount", () => {
    const totals = computeCartTotals([line(1, { price: 20 })], 2.9, null);
    expect(totals.subtotal).toBe(20);
    expect(totals.total).toBeCloseTo(22.9, 6);
    expect(totals.discountAmount).toBe(0);
  });

  it("applies a percent discount before adding shipping", () => {
    const totals = computeCartTotals([line(1, { price: 100 })], 5, { type: "percent", value: 10 });
    expect(totals.discountAmount).toBe(10);
    expect(totals.total).toBe(95); // 100 - 10 + 5
  });

  it("applies a fixed discount, clamped so the total never goes negative", () => {
    const totals = computeCartTotals([line(1, { price: 5 })], 0, { type: "fixed", value: 50 });
    expect(totals.discountAmount).toBe(5); // clamped to subtotal
    expect(totals.total).toBe(0);
  });

  it("computes totalSavings from compareAtPrice, separately from the discount code", () => {
    const totals = computeCartTotals([line(2, { price: 10, compareAtPrice: 15 })], 0, null);
    expect(totals.totalSavings).toBe(10); // 2 × (15 - 10)
    expect(totals.subtotal).toBe(20); // uses price, not compareAtPrice
  });

  it("ignores compareAtPrice when it isn't actually higher than price", () => {
    const totals = computeCartTotals([line(1, { price: 10, compareAtPrice: 10 })], 0, null);
    expect(totals.totalSavings).toBe(0);
  });
});
