"use client";

import { useCallback, useSyncExternalStore } from "react";

const STORAGE_KEY = "stylunique:wishlist";
const EMPTY_HANDLES: string[] = [];
const listeners = new Set<() => void>();

let cachedRaw: string | null = null;
let cachedHandles: string[] = EMPTY_HANDLES;

function parseHandles(raw: string): string[] {
  try {
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed.filter((value): value is string => typeof value === "string") : EMPTY_HANDLES;
  } catch {
    return EMPTY_HANDLES;
  }
}

// useSyncExternalStore requires the same reference back when nothing changed,
// so this only re-parses (and returns a new array) when the raw value differs.
function readHandles(): string[] {
  if (typeof window === "undefined") {
    return EMPTY_HANDLES;
  }

  const raw = window.localStorage.getItem(STORAGE_KEY);
  if (raw === cachedRaw) {
    return cachedHandles;
  }

  cachedRaw = raw;
  cachedHandles = raw ? parseHandles(raw) : EMPTY_HANDLES;
  return cachedHandles;
}

function writeHandles(handles: string[]) {
  const raw = JSON.stringify(handles);
  try {
    window.localStorage.setItem(STORAGE_KEY, raw);
  } catch {
    // Best-effort: private browsing or storage quota can throw.
  }
  cachedRaw = raw;
  cachedHandles = handles;
  listeners.forEach((listener) => listener());
}

function subscribe(listener: () => void) {
  listeners.add(listener);
  window.addEventListener("storage", listener);
  return () => {
    listeners.delete(listener);
    window.removeEventListener("storage", listener);
  };
}

function getServerSnapshot(): string[] {
  return EMPTY_HANDLES;
}

export function useWishlist() {
  const handles = useSyncExternalStore(subscribe, readHandles, getServerSnapshot);

  const isWishlisted = useCallback((handle: string) => handles.includes(handle), [handles]);

  const toggle = useCallback((handle: string) => {
    const current = readHandles();
    const next = current.includes(handle) ? current.filter((existing) => existing !== handle) : [...current, handle];
    writeHandles(next);
  }, []);

  const remove = useCallback((handle: string) => {
    writeHandles(readHandles().filter((existing) => existing !== handle));
  }, []);

  return { handles, isWishlisted, toggle, remove };
}
