import { cookies } from "next/headers";
import type { NextResponse } from "next/server";
import type { StorefrontWishlist, StorefrontWishlistItem } from "@/types/storefront";

export const WISHLIST_COOKIE = "shop_starter_wishlist";

function isWishlistImage(value: unknown) {
  if (!value || typeof value !== "object") {
    return false;
  }

  return typeof (value as { src?: string }).src === "string";
}

function isWishlistItem(value: unknown): value is StorefrontWishlistItem {
  if (!value || typeof value !== "object") {
    return false;
  }

  const item = value as StorefrontWishlistItem;

  return (
    Number.isInteger(item.id) &&
    (typeof item.productId === "undefined" || Number.isInteger(item.productId)) &&
    (typeof item.variationId === "undefined" || Number.isInteger(item.variationId)) &&
    typeof item.slug === "string" &&
    typeof item.type === "string" &&
    typeof item.name === "string" &&
    typeof item.href === "string" &&
    typeof item.label === "string" &&
    typeof item.price === "string" &&
    (item.image === null || typeof item.image === "undefined" || isWishlistImage(item.image))
  );
}

function toWishlist(items: StorefrontWishlistItem[]): StorefrontWishlist {
  return {
    items,
    itemCount: items.length,
    isEmpty: items.length === 0,
  };
}

async function readWishlistItems() {
  const cookieStore = await cookies();
  const rawValue = cookieStore.get(WISHLIST_COOKIE)?.value;

  if (!rawValue) {
    return [];
  }

  try {
    const parsed = JSON.parse(decodeURIComponent(rawValue)) as unknown;

    if (!Array.isArray(parsed)) {
      return [];
    }

    return parsed.filter(isWishlistItem);
  } catch {
    return [];
  }
}

export async function getWishlistFromCookies() {
  return toWishlist(await readWishlistItems());
}

export async function addWishlistItem(item: StorefrontWishlistItem) {
  const items = await readWishlistItems();
  const nextItems = [item, ...items.filter((entry) => entry.id !== item.id)];

  return toWishlist(nextItems);
}

export async function removeWishlistItem(id: number) {
  const items = await readWishlistItems();

  return toWishlist(items.filter((item) => item.id !== id));
}

export function applyWishlistCookie(
  response: NextResponse,
  wishlist: StorefrontWishlist,
) {
  response.cookies.set(WISHLIST_COOKIE, JSON.stringify(wishlist.items), {
    httpOnly: true,
    sameSite: "lax",
    secure: process.env.NODE_ENV === "production",
    path: "/",
    maxAge: 60 * 60 * 24 * 365,
  });
}
