import { convexTest } from "convex-test";
import { describe, it, expect } from "vitest";
import { api } from "./_generated/api";
import schema from "./schema";

const modules = import.meta.glob("./**/*.ts");

async function setupUserAndVariant(t: ReturnType<typeof convexTest>) {
  const asCustomer = t.withIdentity({
    name: "Alice",
    email: "alice@example.com",
    subject: "clerk_alice_123",
  });
  await asCustomer.mutation(api.users.store, {});

  let categoryId: any;
  let variantId: any;
  await t.run(async (ctx) => {
    categoryId = await ctx.db.insert("categories", {
      name: "Toys",
      slug: "toys",
    });
    const productId = await ctx.db.insert("products", {
      name: "Ball",
      slug: "ball",
      status: "active",
      categoryId,
      tags: [],
      parentCategorySlug: "toys",
      childCategorySlug: "toys",
    });
    variantId = await ctx.db.insert("productVariants", {
      productId,
      name: "Red Ball",
      sku: "BALL-RED-001",
      price: 999,
      stockQuantity: 50,
      attributes: { color: "Red" },
      isActive: true,
      weight: 100,
      weightUnit: "g",
    });
  });

  return { asCustomer, variantId };
}

describe("carts", () => {
  it("addItem adds a line; second addItem with same variantId increases quantity", async () => {
    const t = convexTest(schema, modules);
    const { asCustomer, variantId } = await setupUserAndVariant(t);

    await asCustomer.mutation(api.carts.addItem, {
      variantId,
      quantity: 2,
    });
    let cart = await asCustomer.query(api.carts.get, {});
    expect(cart).not.toBeNull();
    expect(cart!.items).toHaveLength(1);
    expect(cart!.items[0].quantity).toBe(2);

    await asCustomer.mutation(api.carts.addItem, {
      variantId,
      quantity: 3,
    });
    cart = await asCustomer.query(api.carts.get, {});
    expect(cart!.items).toHaveLength(1);
    expect(cart!.items[0].quantity).toBe(5);
  });

  it("updateItem with quantity 0 removes the line", async () => {
    const t = convexTest(schema, modules);
    const { asCustomer, variantId } = await setupUserAndVariant(t);

    await asCustomer.mutation(api.carts.addItem, { variantId, quantity: 1 });
    await asCustomer.mutation(api.carts.updateItem, {
      variantId,
      quantity: 0,
    });
    const cart = await asCustomer.query(api.carts.get, {});
    expect(cart!.items).toHaveLength(0);
  });

  it("clear empties the cart", async () => {
    const t = convexTest(schema, modules);
    const { asCustomer, variantId } = await setupUserAndVariant(t);

    await asCustomer.mutation(api.carts.addItem, { variantId, quantity: 2 });
    await asCustomer.mutation(api.carts.clear, {});
    const cart = await asCustomer.query(api.carts.get, {});
    expect(cart!.items).toHaveLength(0);
  });

  it("guest cart with sessionId; merge into authenticated user cart", async () => {
    const t = convexTest(schema, modules);
    const { variantId } = await setupUserAndVariant(t);
    const sessionId = "guest-session-123";

    await t.mutation(api.carts.addItem, {
      variantId,
      quantity: 2,
      sessionId,
    });
    const guestCart = await t.query(api.carts.get, { sessionId });
    expect(guestCart).not.toBeNull();
    expect(guestCart!.items).toHaveLength(1);
    expect(guestCart!.items[0].quantity).toBe(2);

    const asCustomer = t.withIdentity({
      name: "Alice",
      email: "alice@example.com",
      subject: "clerk_alice_123",
    });
    await asCustomer.mutation(api.users.store, {});
    await asCustomer.mutation(api.carts.addItem, { variantId, quantity: 1 });
    await asCustomer.mutation(api.carts.merge, { sessionId });

    const userCart = await asCustomer.query(api.carts.get, {});
    expect(userCart!.items).toHaveLength(1);
    expect(userCart!.items[0].quantity).toBe(3);

    const guestCartAfter = await t.query(api.carts.get, { sessionId });
    expect(guestCartAfter!.items).toHaveLength(0);
  });
});
