'use client';

import { useCallback, useEffect, useMemo, useState } from 'react';

import {
  FAVORITES_CHANGED_EVENT,
  FAVORITES_STORAGE_KEY,
  getFavoriteKey,
  readFavoriteItems,
  writeFavoriteItems,
} from '@/utils/favorites';
import type {
  FavoriteCreationItem,
  FavoriteCreatorItem,
  FavoriteItem,
  FavoriteKind,
} from '@/utils/favorites';

export function useFavorites() {
  const [items, setItems] = useState<FavoriteItem[]>([]);
  const [isReady, setIsReady] = useState(false);

  const refresh = useCallback(() => {
    setItems(readFavoriteItems());
  }, []);

  useEffect(() => {
    refresh();
    setIsReady(true);

    const handleFavoritesChanged = () => refresh();
    const handleStorageChanged = (event: StorageEvent) => {
      if (event.key === FAVORITES_STORAGE_KEY) refresh();
    };

    window.addEventListener(FAVORITES_CHANGED_EVENT, handleFavoritesChanged);
    window.addEventListener('storage', handleStorageChanged);

    return () => {
      window.removeEventListener(FAVORITES_CHANGED_EVENT, handleFavoritesChanged);
      window.removeEventListener('storage', handleStorageChanged);
    };
  }, [refresh]);

  const isFavorite = useCallback(
    (kind: FavoriteKind, id: string) =>
      items.some((item) => getFavoriteKey(item.kind, item.id) === getFavoriteKey(kind, id)),
    [items]
  );

  const addFavorite = useCallback((favorite: FavoriteItem) => {
    const current = readFavoriteItems();
    const favoriteKey = getFavoriteKey(favorite.kind, favorite.id);
    const next = [
      { ...favorite, savedAt: favorite.savedAt || new Date().toISOString() },
      ...current.filter((item) => getFavoriteKey(item.kind, item.id) !== favoriteKey),
    ];

    if (!writeFavoriteItems(next)) return false;

    setItems(next);
    return true;
  }, []);

  const removeFavorite = useCallback((kind: FavoriteKind, id: string) => {
    const favoriteKey = getFavoriteKey(kind, id);
    const next = readFavoriteItems().filter(
      (item) => getFavoriteKey(item.kind, item.id) !== favoriteKey
    );

    if (!writeFavoriteItems(next)) return false;

    setItems(next);
    return true;
  }, []);

  const toggleFavorite = useCallback((favorite: FavoriteItem) => {
    const current = readFavoriteItems();
    const favoriteKey = getFavoriteKey(favorite.kind, favorite.id);
    const exists = current.some((item) => getFavoriteKey(item.kind, item.id) === favoriteKey);
    const next = exists
      ? current.filter((item) => getFavoriteKey(item.kind, item.id) !== favoriteKey)
      : [
          { ...favorite, savedAt: new Date().toISOString() },
          ...current.filter((item) => getFavoriteKey(item.kind, item.id) !== favoriteKey),
        ];

    if (!writeFavoriteItems(next)) return false;

    setItems(next);
    return !exists;
  }, []);

  return useMemo(
    () => ({
      items,
      isReady,
      count: items.length,
      creations: items.filter((item): item is FavoriteCreationItem => item.kind === 'creation'),
      creators: items.filter((item): item is FavoriteCreatorItem => item.kind === 'creator'),
      isFavorite,
      addFavorite,
      removeFavorite,
      toggleFavorite,
    }),
    [addFavorite, isFavorite, isReady, items, removeFavorite, toggleFavorite]
  );
}
