import { create } from "zustand";
import {
  ChatSession,
  ChatMessage,
  ConnectionStatus,
  SessionCreatedResponse,
  ChatJoinedResponse,
  MessageReceivedResponse,
  BotResponse,
  BotResponseStart,
  BotResponseChunk,
  BotResponseEnd,
  ErrorResponse,
} from "../types/Types";

interface ChatbotState {
  // Connection
  connectionStatus: ConnectionStatus;
  setConnectionStatus: (status: ConnectionStatus) => void;

  // Current session
  currentSession: ChatSession | null;
  setCurrentSession: (session: ChatSession | null) => void;

  // Messages
  messages: ChatMessage[];
  addMessage: (message: ChatMessage) => void;
  updateMessage: (messageId: string, updates: Partial<ChatMessage>) => void;
  setMessages: (messages: ChatMessage[]) => void;
  clearMessages: () => void;

  // Streaming message
  streamingMessage: {
    userMessageId: string | null;
    content: string;
    isStreaming: boolean;
  };
  startStreaming: (userMessageId: string) => void;
  appendStreamChunk: (chunk: string) => void;
  endStreaming: (fullResponse: string) => void;
  clearStreaming: () => void;

  // Sessions list
  sessions: ChatSession[];
  setSessions: (sessions: ChatSession[]) => void;
  addSession: (session: ChatSession) => void;
  updateSession: (sessionId: string, updates: Partial<ChatSession>) => void;

  // Typing indicators
  typingUsers: Set<string>;
  setTyping: (sessionId: string, isTyping: boolean) => void;
  clearTyping: () => void;

  // Errors
  error: string | null;
  setError: (error: string | null) => void;
}

export const useChatbotStore = create<ChatbotState>((set, get) => ({
  // Connection
  connectionStatus: "disconnected",
  setConnectionStatus: (status) => set({ connectionStatus: status }),

  // Current session
  currentSession: null,
  setCurrentSession: (session) => set({ currentSession: session }),

  // Messages
  messages: [],
  addMessage: (message) =>
    set((state) => ({
      messages: [...state.messages, message],
    })),
  updateMessage: (messageId, updates) =>
    set((state) => ({
      messages: state.messages.map((msg) =>
        msg.id === messageId ? { ...msg, ...updates } : msg
      ),
    })),
  setMessages: (messages) => set({ messages }),
  clearMessages: () => set({ messages: [] }),

  // Streaming message
  streamingMessage: {
    userMessageId: null,
    content: "",
    isStreaming: false,
  },
  startStreaming: (userMessageId) =>
    set({
      streamingMessage: {
        userMessageId,
        content: "",
        isStreaming: true,
      },
    }),
  appendStreamChunk: (chunk) =>
    set((state) => ({
      streamingMessage: {
        ...state.streamingMessage,
        content: state.streamingMessage.content + chunk,
      },
    })),
  endStreaming: (fullResponse) => {
    const state = get();
    // تبدیل streaming message به message معمولی
    if (state.streamingMessage.userMessageId) {
      const botMessage: ChatMessage = {
        id: `temp-${Date.now()}`,
        content: fullResponse,
        type: "bot",
        status: "sent",
        createdAt: new Date().toISOString(),
        responseToId: state.streamingMessage.userMessageId,
      };
      set((s) => ({
        messages: [...s.messages, botMessage],
        streamingMessage: {
          userMessageId: null,
          content: "",
          isStreaming: false,
        },
      }));
    }
  },
  clearStreaming: () =>
    set({
      streamingMessage: {
        userMessageId: null,
        content: "",
        isStreaming: false,
      },
    }),

  // Sessions list
  sessions: [],
  setSessions: (sessions) => set({ sessions }),
  addSession: (session) =>
    set((state) => ({
      sessions: [session, ...state.sessions],
    })),
  updateSession: (sessionId, updates) =>
    set((state) => ({
      sessions: state.sessions.map((session) =>
        session.id === sessionId ? { ...session, ...updates } : session
      ),
    })),

  // Typing indicators
  typingUsers: new Set(),
  setTyping: (sessionId, isTyping) =>
    set((state) => {
      const newSet = new Set(state.typingUsers);
      if (isTyping) {
        newSet.add(sessionId);
      } else {
        newSet.delete(sessionId);
      }
      return { typingUsers: newSet };
    }),
  clearTyping: () => set({ typingUsers: new Set() }),

  // Errors
  error: null,
  setError: (error) => set({ error }),
}));
