'use client';

import { useState, useEffect, useCallback, useTransition } from 'react';
import { tagsClient, TagFilters, TagsClient } from '@/clients/tags-client';
import {
  createTag,
  updateTag,
  deleteTag as deleteTagAction,
} from '@/actions/tags';
import { Tag } from '@/lib/types';

interface UseTagsState {
  tags: Array<Tag & { usage: number }>;
  popularTags: Array<Tag & { usage: number }>;
  loading: boolean;
  isPending: boolean; // Loading state for server actions
  error: string | null;
}

interface UseTagsActions {
  refreshTags: () => Promise<void>;
  searchTags: (query: string, limit?: number) => Promise<Tag[]>;
  createTag: (name: string, color: string) => Promise<void>;
  updateTag: (
    tagId: string,
    data: { name?: string; color?: string; isPinned?: boolean }
  ) => Promise<void>;
  deleteTag: (tagId: string) => Promise<void>;
  getPopularTags: (limit?: number) => Promise<void>;
  setFilters: (filters: TagFilters) => void;
}

/**
 * Hook pour la gestion des tags
 */
export function useTags(
  initialData?: (Tag & { usage: number })[],
  initialFilters?: TagFilters
): UseTagsState & UseTagsActions {
  const [isPending, startTransition] = useTransition();
  const [state, setState] = useState<UseTagsState>({
    tags: initialData || [],
    popularTags: initialData || [],
    loading: !initialData,
    isPending: false,
    error: null,
  });

  const [filters, setFilters] = useState<TagFilters>(initialFilters || {});

  /**
   * Récupère les tags depuis l'API
   */
  const refreshTags = useCallback(async () => {
    setState((prev) => ({ ...prev, loading: true, error: null }));

    try {
      const response = await tagsClient.getTags(filters);

      setState((prev) => ({
        ...prev,
        tags: response.data,
        loading: false,
      }));
    } catch (error) {
      setState((prev) => ({
        ...prev,
        loading: false,
        error: error instanceof Error ? error.message : 'Erreur inconnue',
      }));
    }
  }, [filters]);

  /**
   * Recherche des tags par nom (pour autocomplete)
   */
  const searchTags = useCallback(
    async (query: string, limit: number = 10): Promise<Tag[]> => {
      try {
        const response = await tagsClient.searchTags(query, limit);
        return response.data;
      } catch (error) {
        console.error('Erreur lors de la recherche de tags:', error);
        return [];
      }
    },
    []
  );

  /**
   * Récupère les tags populaires
   */
  const getPopularTags = useCallback(async (limit: number = 10) => {
    setState((prev) => ({ ...prev, loading: true, error: null }));

    try {
      const response = await tagsClient.getPopularTags(limit);

      setState((prev) => ({
        ...prev,
        popularTags: response.data,
        loading: false,
      }));
    } catch (error) {
      setState((prev) => ({
        ...prev,
        loading: false,
        error: error instanceof Error ? error.message : 'Erreur inconnue',
      }));
    }
  }, []);

  /**
   * Crée un nouveau tag avec server action
   */
  const createTagAction = useCallback(
    async (name: string, color: string): Promise<void> => {
      // Validation côté client
      const errors = TagsClient.validateTagData({ name, color });
      if (errors.length > 0) {
        setState((prev) => ({ ...prev, error: errors[0] }));
        return;
      }

      startTransition(async () => {
        try {
          setState((prev) => ({ ...prev, error: null }));
          const result = await createTag(name, color);

          if (!result.success) {
            setState((prev) => ({
              ...prev,
              error: result.error || 'Erreur lors de la création',
            }));
          }
          // Note: revalidatePath in server action handles cache refresh automatically
        } catch (error) {
          setState((prev) => ({
            ...prev,
            error:
              error instanceof Error
                ? error.message
                : 'Erreur lors de la création',
          }));
        }
      });
    },
    []
  );

  /**
   * Met à jour un tag avec server action
   */
  const updateTagAction = useCallback(
    async (
      tagId: string,
      data: { name?: string; color?: string; isPinned?: boolean }
    ): Promise<void> => {
      startTransition(async () => {
        try {
          setState((prev) => ({ ...prev, error: null }));
          const result = await updateTag(tagId, data);

          if (!result.success) {
            setState((prev) => ({
              ...prev,
              error: result.error || 'Erreur lors de la mise à jour',
            }));
          }
          // Note: revalidatePath in server action handles cache refresh automatically
        } catch (error) {
          setState((prev) => ({
            ...prev,
            error:
              error instanceof Error
                ? error.message
                : 'Erreur lors de la mise à jour',
          }));
        }
      });
    },
    []
  );

  /**
   * Supprime un tag avec server action
   */
  const deleteTagActionHandler = useCallback(
    async (tagId: string): Promise<void> => {
      startTransition(async () => {
        try {
          setState((prev) => ({ ...prev, error: null }));
          const result = await deleteTagAction(tagId);

          if (!result.success) {
            setState((prev) => ({
              ...prev,
              error: result.error || 'Erreur lors de la suppression',
            }));
            throw new Error(result.error);
          }
          // Note: revalidatePath in server action handles cache refresh automatically
        } catch (error) {
          setState((prev) => ({
            ...prev,
            error:
              error instanceof Error
                ? error.message
                : 'Erreur lors de la suppression',
          }));
          throw error; // Re-throw pour que l'UI puisse gérer l'erreur
        }
      });
    },
    []
  );

  // Charger les tags au montage et quand les filtres changent (seulement si pas de données initiales)
  useEffect(() => {
    if (!initialData) {
      refreshTags();
    }
  }, [refreshTags, initialData]);

  return {
    ...state,
    isPending, // Expose loading state from useTransition
    refreshTags,
    searchTags,
    createTag: createTagAction,
    updateTag: updateTagAction,
    deleteTag: deleteTagActionHandler,
    getPopularTags,
    setFilters,
  };
}

/**
 * Hook simplifié pour l'autocomplete des tags
 */
export function useTagsAutocomplete() {
  const [suggestions, setSuggestions] = useState<Tag[]>([]);
  const [loading, setLoading] = useState(false);

  const searchTags = useCallback(async (query: string) => {
    if (!query.trim()) {
      setSuggestions([]);
      return;
    }

    setLoading(true);
    try {
      const response = await tagsClient.searchTags(query, 5);
      setSuggestions(response.data);
    } catch (error) {
      console.error('Erreur lors de la recherche de tags:', error);
      setSuggestions([]);
    } finally {
      setLoading(false);
    }
  }, []);

  const clearSuggestions = useCallback(() => {
    setSuggestions([]);
  }, []);

  const loadPopularTags = useCallback(async (limit: number = 20) => {
    setLoading(true);
    try {
      const response = await tagsClient.getPopularTags(limit);
      setSuggestions(response.data);
    } catch (error) {
      console.error('Erreur lors du chargement des tags populaires:', error);
      setSuggestions([]);
    } finally {
      setLoading(false);
    }
  }, []);

  return {
    suggestions,
    loading,
    searchTags,
    clearSuggestions,
    loadPopularTags,
  };
}
