import { z } from "zod";
import { createRouter, publicQuery } from "../middleware";
import { getDb } from "../queries/connection";
import { carts, products } from "@db/schema";
import { eq, and } from "drizzle-orm";

function getSessionId(headers: Headers): string {
  let sessionId = headers.get("x-session-id");
  if (!sessionId) {
    sessionId = `sess_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
  }
  return sessionId;
}

export const cartRouter = createRouter({
  get: publicQuery.query(async ({ ctx }) => {
    const db = getDb();
    const sessionId = getSessionId(ctx.req.headers);
    const items = await db
      .select({
        cartId: carts.id,
        productId: carts.productId,
        plan: carts.plan,
        quantity: carts.quantity,
        priceAtAdd: carts.priceAtAdd,
        name: products.name,
        slug: products.slug,
        image: products.image,
        badge: products.badge,
        category: products.category,
      })
      .from(carts)
      .leftJoin(products, eq(carts.productId, products.id))
      .where(eq(carts.sessionId, sessionId));
    return { items, sessionId };
  }),

  add: publicQuery
    .input(
      z.object({
        productId: z.number(),
        plan: z.string().optional(),
        quantity: z.number().default(1),
      })
    )
    .mutation(async ({ ctx, input }) => {
      const db = getDb();
      const sessionId = getSessionId(ctx.req.headers);

      const [product] = await db
        .select()
        .from(products)
        .where(eq(products.id, input.productId))
        .limit(1);

      if (!product) throw new Error("Product not found");

      const [existing] = await db
        .select()
        .from(carts)
        .where(
          and(
            eq(carts.sessionId, sessionId),
            eq(carts.productId, input.productId),
            eq(carts.plan, input.plan || "Default")
          )
        )
        .limit(1);

      if (existing) {
        const currentQty = existing.quantity ?? 1;
        await db
          .update(carts)
          .set({ quantity: currentQty + (input.quantity || 1) })
          .where(eq(carts.id, existing.id));
      } else {
        await db.insert(carts).values({
          sessionId,
          productId: input.productId,
          plan: input.plan || "Default",
          quantity: input.quantity || 1,
          priceAtAdd: product.price,
        });
      }

      return { success: true, sessionId };
    }),

  updateQuantity: publicQuery
    .input(z.object({ cartItemId: z.number(), quantity: z.number().min(1) }))
    .mutation(async ({ input }) => {
      const db = getDb();
      await db
        .update(carts)
        .set({ quantity: input.quantity })
        .where(eq(carts.id, input.cartItemId));
      return { success: true };
    }),

  remove: publicQuery
    .input(z.object({ cartItemId: z.number() }))
    .mutation(async ({ input }) => {
      const db = getDb();
      await db.delete(carts).where(eq(carts.id, input.cartItemId));
      return { success: true };
    }),

  clear: publicQuery.mutation(async ({ ctx }) => {
    const db = getDb();
    const sessionId = getSessionId(ctx.req.headers);
    await db.delete(carts).where(eq(carts.sessionId, sessionId));
    return { success: true };
  }),
});
