"use client";

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
  type ReactNode,
} from "react";
import type { Product } from "@/data/products";
import { useAuth } from "@/context/AuthContext";
import { syncCustomerFavorites } from "@/lib/auth";

export type FavoriteItem = {
  id: string;
  slug: string;
  name: string;
  price: number;
  image: string;
  collection: string;
};

type FavoritesContextValue = {
  items: FavoriteItem[];
  count: number;
  ready: boolean;
  isFavorite: (productIdOrSlug: string) => boolean;
  toggle: (product: Product) => void;
  remove: (productIdOrSlug: string) => void;
  clear: () => void;
};

const FavoritesContext = createContext<FavoritesContextValue | null>(null);

const GUEST_KEY = "ot_favorites_guest";

function storageKey(email: string | null | undefined) {
  if (!email) return GUEST_KEY;
  return `ot_favorites_${email.trim().toLowerCase()}`;
}

function readList(key: string): FavoriteItem[] {
  if (typeof window === "undefined") return [];
  try {
    const raw = localStorage.getItem(key);
    if (!raw) return [];
    const parsed = JSON.parse(raw) as FavoriteItem[];
    if (!Array.isArray(parsed)) return [];
    return parsed.filter((i) => i?.id && i?.slug);
  } catch {
    return [];
  }
}

function writeList(key: string, items: FavoriteItem[]) {
  try {
    localStorage.setItem(key, JSON.stringify(items));
  } catch {
    /* ignore quota */
  }
}

function toFavorite(product: Product): FavoriteItem {
  return {
    id: product.id,
    slug: product.slug,
    name: product.name,
    price: product.price,
    image: product.images[0] || "/brand/senora-clasica.jpg",
    collection: product.collection || "OLD TENNIS",
  };
}

function mergeLists(a: FavoriteItem[], b: FavoriteItem[]) {
  const map = new Map<string, FavoriteItem>();
  for (const item of [...a, ...b]) {
    map.set(item.id || item.slug, item);
  }
  return Array.from(map.values());
}

function favoritesFromMetadata(
  metadata: Record<string, unknown> | null | undefined
): FavoriteItem[] {
  const raw = metadata?.ot_favorites;
  if (!Array.isArray(raw)) return [];
  return (raw as FavoriteItem[]).filter((i) => i?.id && i?.slug);
}

export function FavoritesProvider({ children }: { children: ReactNode }) {
  const { customer, loading: authLoading } = useAuth();
  const [items, setItems] = useState<FavoriteItem[]>([]);
  const [ready, setReady] = useState(false);
  const syncTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const pushToServer = useCallback(
    (list: FavoriteItem[]) => {
      if (!customer?.email) return;
      if (syncTimer.current) clearTimeout(syncTimer.current);
      syncTimer.current = setTimeout(() => {
        void syncCustomerFavorites(list);
      }, 400);
    },
    [customer?.email]
  );

  useEffect(() => {
    if (authLoading) return;
    const key = storageKey(customer?.email);
    let list = readList(key);

    if (customer?.email) {
      const guest = readList(GUEST_KEY);
      const remote = favoritesFromMetadata(customer.metadata);
      list = mergeLists(mergeLists(list, guest), remote);
      writeList(key, list);
      writeList(GUEST_KEY, []);
      pushToServer(list);
    }

    setItems(list);
    setReady(true);
    // Solo rehidratar al cambiar sesión (email), no en cada metadata refresh
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [authLoading, customer?.email]);

  const persist = useCallback(
    (next: FavoriteItem[]) => {
      setItems(next);
      writeList(storageKey(customer?.email), next);
      pushToServer(next);
    },
    [customer?.email, pushToServer]
  );

  const isFavorite = useCallback(
    (productIdOrSlug: string) =>
      items.some((i) => i.id === productIdOrSlug || i.slug === productIdOrSlug),
    [items]
  );

  const toggle = useCallback(
    (product: Product) => {
      const exists = items.some(
        (i) => i.id === product.id || i.slug === product.slug
      );
      if (exists) {
        persist(
          items.filter((i) => i.id !== product.id && i.slug !== product.slug)
        );
      } else {
        persist([toFavorite(product), ...items]);
      }
    },
    [items, persist]
  );

  const remove = useCallback(
    (productIdOrSlug: string) => {
      persist(
        items.filter(
          (i) => i.id !== productIdOrSlug && i.slug !== productIdOrSlug
        )
      );
    },
    [items, persist]
  );

  const clear = useCallback(() => persist([]), [persist]);

  const value = useMemo(
    () => ({
      items,
      count: items.length,
      ready,
      isFavorite,
      toggle,
      remove,
      clear,
    }),
    [items, ready, isFavorite, toggle, remove, clear]
  );

  return (
    <FavoritesContext.Provider value={value}>
      {children}
    </FavoritesContext.Provider>
  );
}

export function useFavorites() {
  const ctx = useContext(FavoritesContext);
  if (!ctx) {
    throw new Error("useFavorites debe usarse dentro de FavoritesProvider");
  }
  return ctx;
}
