/**
 * سبد خرید در دیتابیس.
 * کاربر واردشده: سبد متصل به حساب. مهمان: سبد با توکن تصادفی در کوکی httpOnly (فقط هش آن ذخیره می‌شود).
 * هنگام ورود، سبد مهمان در سبد کاربر ادغام می‌شود.
 */
import "server-only";
import { cookies } from "next/headers";
import { db } from "@/lib/db";
import { randomToken, sha256 } from "@/lib/crypto";
import { getCurrentUser } from "@/server/auth/session";

const CART_COOKIE = "zh_cart";
export const MAX_QTY_PER_ITEM = 10;

export interface CartLineDTO {
  variantId: string;
  productId: number;
  qty: number;
}

async function findCart(create: boolean) {
  const user = await getCurrentUser();
  if (user) {
    const existing = await db.cart.findUnique({ where: { userId: user.id } });
    if (existing || !create) return existing;
    return db.cart.create({ data: { userId: user.id } });
  }
  const jar = await cookies();
  const token = jar.get(CART_COOKIE)?.value;
  if (token) {
    const existing = await db.cart.findUnique({ where: { guestToken: sha256(token) } });
    if (existing || !create) return existing;
  }
  if (!create) return null;
  const fresh = randomToken();
  jar.set(CART_COOKIE, fresh, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", maxAge: 60 * 86_400 });
  return db.cart.create({ data: { guestToken: sha256(fresh) } });
}

async function linesOf(cartId: string | undefined): Promise<CartLineDTO[]> {
  if (!cartId) return [];
  const items = await db.cartItem.findMany({ where: { cartId }, include: { variant: { select: { productId: true } } }, orderBy: { id: "asc" } });
  return items.map((i) => ({ variantId: i.variantId, productId: i.variant.productId, qty: i.qty }));
}

export async function getCartLines() {
  return linesOf((await findCart(false))?.id);
}

/** تعداد مجاز با توجه به موجودی و سقف هر قلم؛ تنوع نامعتبر ← null */
async function allowedQty(variantId: string, qty: number) {
  const v = await db.productVariant.findFirst({ where: { id: variantId, isActive: true, product: { isActive: true } }, select: { stock: true } });
  if (!v) return null;
  return Math.max(0, Math.min(qty, MAX_QTY_PER_ITEM, v.stock));
}

export async function addToCart(variantId: string, qty: number) {
  const cart = (await findCart(true))!;
  const current = await db.cartItem.findUnique({ where: { cartId_variantId: { cartId: cart.id, variantId } } });
  const allowed = await allowedQty(variantId, (current?.qty ?? 0) + qty);
  if (allowed) {
    await db.cartItem.upsert({
      where: { cartId_variantId: { cartId: cart.id, variantId } },
      create: { cartId: cart.id, variantId, qty: allowed },
      update: { qty: allowed },
    });
  }
  return linesOf(cart.id);
}

export async function setCartQty(variantId: string, qty: number) {
  const cart = await findCart(false);
  if (!cart) return [];
  const allowed = qty > 0 ? await allowedQty(variantId, qty) : 0;
  if (!allowed) await db.cartItem.deleteMany({ where: { cartId: cart.id, variantId } });
  else await db.cartItem.updateMany({ where: { cartId: cart.id, variantId }, data: { qty: allowed } });
  return linesOf(cart.id);
}

export async function clearCart() {
  const cart = await findCart(false);
  if (cart) await db.cartItem.deleteMany({ where: { cartId: cart.id } });
  return [];
}

/** بعد از ورود: انتقال اقلام سبد مهمان به سبد کاربر */
export async function mergeGuestCart(userId: string) {
  const jar = await cookies();
  const token = jar.get(CART_COOKIE)?.value;
  if (!token) return;
  const guest = await db.cart.findUnique({ where: { guestToken: sha256(token) }, include: { items: true } });
  jar.delete(CART_COOKIE);
  if (!guest) return;
  const userCart = await db.cart.upsert({ where: { userId }, create: { userId }, update: {} });
  for (const item of guest.items) {
    const existing = await db.cartItem.findUnique({ where: { cartId_variantId: { cartId: userCart.id, variantId: item.variantId } } });
    const qty = await allowedQty(item.variantId, Math.max(item.qty, existing?.qty ?? 0));
    if (qty) {
      await db.cartItem.upsert({
        where: { cartId_variantId: { cartId: userCart.id, variantId: item.variantId } },
        create: { cartId: userCart.id, variantId: item.variantId, qty },
        update: { qty },
      });
    }
  }
  await db.cart.delete({ where: { id: guest.id } });
}
