'use client';

import { useState, useEffect, useRef } from 'react';
import { useUser } from '@/app/contexts/UserContext';
import { useSupabaseUser } from '@/app/contexts/SupabaseUserContext';
import { useTranslations } from 'next-intl';
import { supabase } from '@/lib/supabase';
import type { ChatConversation, SupabaseConversation } from '../types/supabase';
import { convertSupabaseConversationToChatConversation } from '../types/supabase';

export const useConversations = () => {
  const { user } = useUser();
  const { supabaseUser } = useSupabaseUser();
  const t = useTranslations('chat.errors');
  const tLoading = useTranslations('chat.loading');
  const [conversations, setConversations] = useState<ChatConversation[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const retryCountRef = useRef(0);
  const maxRetries = 3;

  const loadConversations = async (isRetry: boolean = false): Promise<void> => {
    if (!user?.id) {
      setConversations([]);
      setLoading(false);
      setError(t('userNotAuthenticated'));
      return;
    }

    try {
      if (!isRetry) {
        setLoading(true);
      }
      setError(null);

      // Utiliser l'utilisateur Supabase du context
      if (!supabaseUser) {
        throw new Error(t('userNotAvailable'));
      }

      // Charger les conversations de l'utilisateur
      const { data: participants, error: participantsError } = await supabase
        .from('conversation_participants')
        .select(`
          conversation_id,
          conversations (
            id,
            type,
            name,
            created_at,
            updated_at
          )
        `)
        .eq('user_id', supabaseUser.id);

      if (participantsError) {
        // Vérifier si c'est une erreur de connexion Supabase
        if (participantsError.message.includes('fetch') || participantsError.message.includes('network')) {
          throw new Error(t('supabaseUnavailable'));
        }
        throw participantsError;
      }

      // Si aucune conversation, retourner liste vide
      if (!participants || participants.length === 0) {
        setConversations([]);
        setLoading(false);
        return;
      }

      // Enrichir chaque conversation
      const enrichedConversations: ChatConversation[] = [];
      const missingDirectNamesOtherUserIds = new Set<string>();

      for (const participant of participants) {
        const conversation = participant.conversations as unknown as SupabaseConversation;

        // Obtenir les participants de la conversation
        const { data: convParticipants } = await supabase
          .from('conversation_participants')
          .select('user_id')
          .eq('conversation_id', conversation.id);

        const participantIds = convParticipants?.map(p => p.user_id) || [];

        // Obtenir le dernier message
        const { data: lastMessage } = await supabase
          .from('messages')
          .select('content, created_at')
          .eq('conversation_id', conversation.id)
          .order('created_at', { ascending: false })
          .limit(1)
          .single();

        // Calculer le nombre de messages non lus (fallback sans sous-requête PostgREST)
        // 1) Récupérer les IDs des messages entrants de la conversation
        const { data: incomingMsgs } = await supabase
          .from('messages')
          .select('id')
          .eq('conversation_id', conversation.id)
          .neq('sender_id', supabaseUser.id);

        const incomingIds = (incomingMsgs || []).map(m => m.id);
        let unreadCount = 0;
        if (incomingIds.length > 0) {
          // 2) Récupérer les lectures de l'utilisateur pour ces messages
          const { data: readsForUser } = await supabase
            .from('message_reads')
            .select('message_id')
            .eq('user_id', supabaseUser.id)
            .in('message_id', incomingIds);

          const readIds = new Set((readsForUser || []).map(r => r.message_id));
          unreadCount = incomingIds.filter(id => !readIds.has(id)).length;
        }

        const chatConversation = convertSupabaseConversationToChatConversation(
          conversation,
          participantIds,
          lastMessage?.content,
          lastMessage ? new Date(lastMessage.created_at).toLocaleTimeString() : undefined,
          lastMessage ? new Date(lastMessage.created_at).getTime() : undefined,
          unreadCount || 0
        );

        // Collecter l'autre participant si direct et sans nom
        if (conversation.type === 'direct' && (!conversation.name || conversation.name.trim() === '')) {
          const otherId = participantIds.find(id => id !== supabaseUser.id);
          if (otherId) missingDirectNamesOtherUserIds.add(otherId);
        }

        enrichedConversations.push(chatConversation);
      }

      // Récupérer en une seule requête les noms des autres participants manquants
      let otherUserIdToName: Record<string, string> = {};
      if (missingDirectNamesOtherUserIds.size > 0) {
        const ids = Array.from(missingDirectNamesOtherUserIds);
        const { data: usersForNames } = await supabase
          .from('users')
          .select('id, name')
          .in('id', ids);
        if (Array.isArray(usersForNames)) {
          otherUserIdToName = usersForNames.reduce<Record<string, string>>((acc, u) => {
            acc[u.id as string] = (u as any).name as string;
            return acc;
          }, {});
        }
      }

      // Appliquer les noms manquants pour les conversations directes
      for (const conv of enrichedConversations) {
        if (conv.type === 'direct' && (!conv.name || conv.name.trim() === '')) {
          const otherId = conv.participants.find(id => id !== supabaseUser.id);
          if (otherId && otherUserIdToName[otherId]) {
            (conv as any).name = otherUserIdToName[otherId];
          }
        }
      }

      // Trier par dernier message (plus récent en premier)
      const sortedConversations = enrichedConversations.sort((a, b) => 
        (b.lastMessageTimestamp || 0) - (a.lastMessageTimestamp || 0)
      );

      setConversations(sortedConversations);
      retryCountRef.current = 0; // Reset retry count on success
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : t('loadingConversations');
      
      // Retry automatique pour les erreurs réseau
      if (retryCountRef.current < maxRetries && 
          (errorMessage.includes('network') || errorMessage.includes('fetch') || errorMessage.includes(t('supabaseUnavailable')))) {
        retryCountRef.current++;
        await new Promise(resolve => setTimeout(resolve, 1000 * retryCountRef.current)); // Délai exponentiel
        return loadConversations(true); // Retry
      }
      
      setError(errorMessage);
      console.error('Error loading conversations:', err);
    } finally {
      if (!isRetry || retryCountRef.current >= maxRetries) {
        setLoading(false);
      }
    }
  };

  const searchConversation = async (query: string) => {
    if (!user?.id) {
      setError(t('userNotAuthenticated'));
      return;
    }

    try {
      setLoading(true);
      setError(null);

      // Charger toutes les conversations d'abord
      await loadConversations();

      // Filtrage côté client
      if (!query.trim()) {
        // Si query vide, on recharge toutes les conversations
        return;
      }

      const searchTerm = query.toLowerCase();
      setConversations(prev => 
        prev.filter(conv => 
          conv.name?.toLowerCase().includes(searchTerm) ||
          conv.lastMessage?.toLowerCase().includes(searchTerm)
        )
      );
    } catch (err) {
      setError(t('searchFailed'));
      console.error('Error searching conversations:', err);
    } finally {
      setLoading(false);
    }
  };

  const clearUnread = (conversationId: string) => {
    setConversations(prev => prev.map(c => (
      c.id === conversationId ? { ...c, unreadCount: 0 } : c
    )));
  };

  useEffect(() => {
    if (supabaseUser) {
      loadConversations();
    }
  }, [user?.id, supabaseUser?.id]);

  return {
    conversations,
    loading,
    error,
    reload: loadConversations,
    search: searchConversation,
    clearUnread
  };
};