import { MutationCtx, QueryCtx } from "../_generated/server";
import { Id } from "../_generated/dataModel";

const CART_EXPIRY_MS = 30 * 24 * 60 * 60 * 1000; // 30 days

type CartReadCtx = Pick<QueryCtx, "db">;

/**
 * Get cart by userId or sessionId (read-only). Returns null if not found.
 */
export async function getCart(
  ctx: CartReadCtx,
  userId?: Id<"users">,
  sessionId?: string
) {
  if (userId) {
    return await ctx.db
      .query("carts")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .unique();
  }
  if (sessionId) {
    return await ctx.db
      .query("carts")
      .withIndex("by_session", (q) => q.eq("sessionId", sessionId))
      .unique();
  }
  return null;
}

/**
 * Get existing cart or create a new one. Mutation-only; use from addItem, updateItem, removeItem, clear, merge.
 * At least one of userId or sessionId must be provided.
 */
export async function getOrCreateCart(
  ctx: MutationCtx,
  userId?: Id<"users">,
  sessionId?: string
): Promise<{ _id: Id<"carts">; items: { productId: Id<"products">; variantId?: Id<"productVariants">; quantity: number; price: number }[] }> {
  if (!userId && !sessionId) {
    throw new Error("Either userId or sessionId must be provided");
  }

  const now = Date.now();
  const expiresAt = now + CART_EXPIRY_MS;

  if (userId) {
    const existing = await ctx.db
      .query("carts")
      .withIndex("by_user", (q) => q.eq("userId", userId))
      .unique();
    if (existing) return existing;
    const id = await ctx.db.insert("carts", {
      userId,
      items: [],
      createdAt: now,
      updatedAt: now,
      expiresAt,
    });
    const cart = await ctx.db.get(id);
    if (!cart) throw new Error("Failed to create cart");
    return cart;
  }

  const existing = await ctx.db
    .query("carts")
    .withIndex("by_session", (q) => q.eq("sessionId", sessionId!))
    .unique();
  if (existing) return existing;
  const id = await ctx.db.insert("carts", {
    sessionId: sessionId!,
    items: [],
    createdAt: now,
    updatedAt: now,
    expiresAt,
  });
  const cart = await ctx.db.get(id);
  if (!cart) throw new Error("Failed to create cart");
  return cart;
}
