import { create } from 'zustand';
import { wsService } from '@/services/websocket';
import type { ChatMessage, Conversation, ChatWebSocketEvent } from '@/types';

interface ChatState {
  conversations: Conversation[];
  currentConversation: Conversation | null;
  messages: Record<string, ChatMessage[]>;
  typingUsers: Record<string, number[]>;
  isConnected: boolean;
  isLoading: boolean;
  error: string | null;
}

interface ChatActions {
  setConversations: (conversations: Conversation[]) => void;
  setCurrentConversation: (conversation: Conversation | null) => void;
  addMessage: (conversationId: string, message: ChatMessage) => void;
  updateMessage: (
    conversationId: string,
    messageId: string,
    updates: Partial<ChatMessage>
  ) => void;
  removeMessage: (conversationId: string, messageId: string) => void;
  setMessages: (conversationId: string, messages: ChatMessage[]) => void;
  setTypingUsers: (conversationId: string, userIds: number[]) => void;
  addTypingUser: (conversationId: string, userId: number) => void;
  removeTypingUser: (conversationId: string, userId: number) => void;
  setConnected: (connected: boolean) => void;
  setLoading: (loading: boolean) => void;
  setError: (error: string | null) => void;
  connect: () => Promise<void>;
  disconnect: () => void;
  joinConversation: (conversationId: string) => void;
  leaveConversation: (conversationId: string) => void;
  sendMessage: (
    conversationId: string,
    content: string,
    parentMessageId?: string
  ) => void;
  startTyping: (conversationId: string) => void;
  stopTyping: (conversationId: string) => void;
  addReaction: (messageId: string, emoji: string) => void;
  removeReaction: (messageId: string, emoji: string) => void;
  fetchConversations: () => Promise<void>;
  createConversation: (params: {
    name: string;
    description?: string;
    type?: 'public' | 'private' | 'direct';
    is_private?: boolean;
  }) => Promise<Conversation>;
}

export const useChatStore = create<ChatState & ChatActions>((set, get) => ({
  // État initial
  conversations: [],
  currentConversation: null,
  messages: {},
  typingUsers: {},
  isConnected: false,
  isLoading: false,
  error: null,

  // Actions
  setConversations: conversations => set({ conversations }),

  setCurrentConversation: conversation => {
    set({ currentConversation: conversation });
    if (conversation) {
      get().joinConversation(conversation.id);
    }
  },

  addMessage: (conversationId, message) => {
    set(state => ({
      messages: {
        ...state.messages,
        [conversationId]: [...(state.messages[conversationId] || []), message],
      },
    }));
  },

  updateMessage: (conversationId, messageId, updates) => {
    set(state => ({
      messages: {
        ...state.messages,
        [conversationId]:
          state.messages[conversationId]?.map(msg =>
            msg.id === messageId ? { ...msg, ...updates } : msg
          ) || [],
      },
    }));
  },

  removeMessage: (conversationId, messageId) => {
    set(state => ({
      messages: {
        ...state.messages,
        [conversationId]:
          state.messages[conversationId]?.filter(msg => msg.id !== messageId) ||
          [],
      },
    }));
  },

  setMessages: (conversationId, messages) => {
    set(state => ({
      messages: {
        ...state.messages,
        [conversationId]: messages,
      },
    }));
  },

  setTypingUsers: (conversationId, userIds) => {
    set(state => ({
      typingUsers: {
        ...state.typingUsers,
        [conversationId]: userIds,
      },
    }));
  },

  addTypingUser: (conversationId, userId) => {
    set(state => ({
      typingUsers: {
        ...state.typingUsers,
        [conversationId]: [
          ...(state.typingUsers[conversationId] || []),
          userId,
        ],
      },
    }));
  },

  removeTypingUser: (conversationId, userId) => {
    set(state => ({
      typingUsers: {
        ...state.typingUsers,
        [conversationId]: (state.typingUsers[conversationId] || []).filter(
          id => id !== userId
        ),
      },
    }));
  },

  setConnected: isConnected => set({ isConnected }),

  setLoading: isLoading => set({ isLoading }),

  setError: error => set({ error }),

  connect: async () => {
    set({ isLoading: true, error: null });
    try {
      await wsService.connect();
      set({ isConnected: true, isLoading: false });

      // Écouter les événements WebSocket
      wsService.on('message', (event: ChatWebSocketEvent) => {
        const { conversation_id, user_id, content, emoji, timestamp } =
          event.data;

        switch (event.type) {
          case 'message':
            if (content) {
              get().addMessage(conversation_id, {
                id: crypto.randomUUID(),
                conversation_id,
                sender_id: user_id,
                content,
                created_at: timestamp,
              });
            }
            break;
          case 'typing':
            get().addTypingUser(conversation_id, user_id);
            // Retirer l'utilisateur de la liste après 3 secondes
            setTimeout(() => {
              get().removeTypingUser(conversation_id, user_id);
            }, 3000);
            break;
          case 'reaction':
            if (emoji) {
              // Mettre à jour les réactions du message
              // Cette logique dépend de la structure des données
            }
            break;
        }
      });

      wsService.on('connected', () => {
        set({ isConnected: true, isLoading: false });
      });

      wsService.on('disconnected', () => {
        set({ isConnected: false });
      });

      wsService.on('error', (error: any) => {
        set({ error: error.message, isLoading: false });
      });
    } catch (error: any) {
      set({ error: error.message, isLoading: false });
    }
  },

  disconnect: () => {
    wsService.disconnect();
    set({ isConnected: false });
  },

  joinConversation: conversationId => {
    wsService.joinConversation(conversationId);
  },

  leaveConversation: conversationId => {
    wsService.leaveConversation(conversationId);
  },

  sendMessage: (conversationId, content, parentMessageId) => {
    wsService.sendMessage(conversationId, content, parentMessageId);
  },

  startTyping: conversationId => {
    wsService.startTyping(conversationId);
  },

  stopTyping: conversationId => {
    wsService.stopTyping(conversationId);
  },

  addReaction: (messageId, emoji) => {
    wsService.addReaction(messageId, emoji);
  },

  removeReaction: (messageId, emoji) => {
    wsService.removeReaction(messageId, emoji);
  },

  fetchConversations: async () => {
    try {
      const { apiService } = await import('@/services/api');
      const conversations = await apiService.getConversations();
      set({ conversations });
    } catch (error) {
      console.error('Error fetching conversations:', error);
      set({ error: 'Failed to fetch conversations' });
    }
  },

  createConversation: async (params) => {
    try {
      const { apiService } = await import('@/services/api');
      const conversation = await apiService.createConversation(params);
      
      // Ajouter la nouvelle conversation à la liste
      set(state => ({
        conversations: [...state.conversations, conversation],
        currentConversation: conversation,
      }));
      
      // Rejoindre la conversation via WebSocket
      get().joinConversation(conversation.id);
      
      return conversation;
    } catch (error: any) {
      console.error('Error creating conversation:', error);
      set({ error: error.message || 'Failed to create conversation' });
      throw error;
    }
  },
}));
