import { useCallback, useEffect, useRef, useState } from 'react';
import { io, Socket } from 'socket.io-client';
import { useChatStore, Message, FileAttachment } from '../stores/chatStore';
import { uploadFile, getFileType, validateFile } from '@/shared/services/fileService';
import type { FileInfo } from '@/shared/services/fileService';

// Singleton socket instance to prevent multiple connections
let globalSocket: Socket | null = null;
let currentUserId: string | null = null;

interface PendingFile {
  id: string;
  file: File;
  preview?: string;
  type: 'image' | 'document' | 'other';
}

export function useChat() {
  const socketRef = useRef<Socket | null>(null);
  const {
    userId,
    currentConversationId,
    setStreaming,
    appendStreamContent,
    clearStreamContent,
    addMessage,
    addConversation,
    setCurrentConversation,
    setConnected,
    addActiveAgent,
    completeAgent,
    setCoordinatorPhase,
    clearAgentState,
  } = useChatStore();

  // 文件上传状态
  const [pendingFiles, setPendingFiles] = useState<PendingFile[]>([]);
  const [uploadProgress, setUploadProgress] = useState<Record<string, { progress: number; status: string }>>({});
  const [isUploading, setIsUploading] = useState(false);

  // Initialize WebSocket connection (singleton pattern)
  useEffect(() => {
    if (!userId) return;

    // If socket exists for same user, reuse it
    if (globalSocket && currentUserId === userId && globalSocket.connected) {
      socketRef.current = globalSocket;
      setConnected(true);
      return;
    }

    // If socket exists for different user or disconnected, clean up
    if (globalSocket) {
      globalSocket.disconnect();
      globalSocket = null;
    }

    currentUserId = userId;

    const socket = io('/ws/conversation', {
      path: '/ws/conversation/socket.io',
      query: { userId },
      transports: ['websocket'],
      reconnection: true,
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
    });

    socket.on('connect', () => {
      console.log('WebSocket connected, socket id:', socket.id);
      setConnected(true);
    });

    socket.on('disconnect', (reason) => {
      console.log('WebSocket disconnected, reason:', reason);
      setConnected(false);
    });

    socket.on('connect_error', (error) => {
      console.error('WebSocket connect_error:', error.message);
    });

    socket.on('connected', (data) => {
      console.log('Connection confirmed:', data);
    });

    socket.on('stream_start', (data) => {
      console.log('Stream started:', data);
      setStreaming(true);
      clearStreamContent();
      clearAgentState();
      useChatStore.getState().clearToolResults();
    });

    socket.on('stream_chunk', (data) => {
      appendStreamContent(data.content);
    });

    socket.on('stream_end', (data) => {
      const { conversationId } = data;
      const state = useChatStore.getState();
      const streamContent = state.streamContent;
      const toolResults = state.pendingToolResults;

      // Add the complete message with tool results if any
      const message: Message = {
        id: `msg_${Date.now()}`,
        role: 'assistant',
        content: streamContent,
        createdAt: new Date().toISOString(),
        metadata: toolResults.length > 0
          ? { toolCalls: toolResults }
          : undefined,
      };

      addMessage(conversationId, message);
      setStreaming(false);
      clearStreamContent();
      clearAgentState();
      state.clearToolResults();
    });

    // Multi-agent events
    socket.on('agent_start', (data) => {
      console.log('Agent started:', data);
      addActiveAgent({
        messageId: data.messageId,
        conversationId: data.conversationId,
        agentType: data.agentType,
        agentName: data.agentName,
        description: data.description,
        startedAt: Date.now(),
      });
    });

    socket.on('agent_complete', (data) => {
      console.log('Agent completed:', data);
      completeAgent(data.messageId, data.agentType, data.durationMs, data.success);
    });

    socket.on('coordinator_thinking', (data) => {
      console.log('Coordinator thinking:', data);
      setCoordinatorPhase(data.phase, data.message);
    });

    socket.on('tool_call', (data) => {
      console.log('Tool call:', data);
    });

    socket.on('tool_result', (data) => {
      console.log('Tool result:', data);
      // Collect tool results; they'll be attached to the message on stream_end
      try {
        const parsed = typeof data.result === 'string' ? JSON.parse(data.result) : data.result;
        useChatStore.getState().addToolResult(data.tool, parsed);
      } catch {
        useChatStore.getState().addToolResult(data.tool, data.result);
      }
    });

    socket.on('error', (error) => {
      console.error('WebSocket error:', error);
      setStreaming(false);
    });

    globalSocket = socket;
    socketRef.current = socket;

    // Don't disconnect on cleanup - keep singleton alive
  }, [userId]);

  // 添加待上传文件
  const addFiles = useCallback((files: File[]) => {
    const newFiles: PendingFile[] = [];

    files.forEach((file) => {
      const validation = validateFile(file);
      if (!validation.valid) {
        console.error(validation.error);
        return;
      }

      const id = `pending_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      const type = getFileType(file.type);

      const pendingFile: PendingFile = {
        id,
        file,
        type,
      };

      // 为图片生成预览
      if (type === 'image') {
        pendingFile.preview = URL.createObjectURL(file);
      }

      newFiles.push(pendingFile);
    });

    setPendingFiles((prev) => [...prev, ...newFiles]);
  }, []);

  // 移除待上传文件
  const removeFile = useCallback((id: string) => {
    setPendingFiles((prev) => {
      const file = prev.find((f) => f.id === id);
      if (file?.preview) {
        URL.revokeObjectURL(file.preview);
      }
      return prev.filter((f) => f.id !== id);
    });
    setUploadProgress((prev) => {
      const newProgress = { ...prev };
      delete newProgress[id];
      return newProgress;
    });
  }, []);

  // 上传文件并获取附件信息
  const uploadFiles = useCallback(async (conversationId: string): Promise<FileAttachment[]> => {
    if (!userId || pendingFiles.length === 0) return [];

    setIsUploading(true);
    const attachments: FileAttachment[] = [];

    for (const pf of pendingFiles) {
      setUploadProgress((prev) => ({
        ...prev,
        [pf.id]: { progress: 0, status: 'uploading' },
      }));

      try {
        const fileInfo: FileInfo = await uploadFile(
          pf.file,
          userId,
          conversationId,
          (progress) => {
            setUploadProgress((prev) => ({
              ...prev,
              [pf.id]: { progress, status: 'uploading' },
            }));
          },
        );

        setUploadProgress((prev) => ({
          ...prev,
          [pf.id]: { progress: 100, status: 'success' },
        }));

        attachments.push({
          id: fileInfo.id,
          originalName: fileInfo.originalName,
          mimeType: fileInfo.mimeType,
          type: fileInfo.type,
          size: fileInfo.size,
          downloadUrl: fileInfo.downloadUrl,
          thumbnailUrl: fileInfo.thumbnailUrl,
        });

        // 清理预览
        if (pf.preview) {
          URL.revokeObjectURL(pf.preview);
        }
      } catch (error) {
        console.error('File upload failed:', error);
        setUploadProgress((prev) => ({
          ...prev,
          [pf.id]: { progress: 0, status: 'error' },
        }));
      }
    }

    // 清空待上传列表
    setPendingFiles([]);
    setUploadProgress({});
    setIsUploading(false);

    return attachments;
  }, [userId, pendingFiles]);

  // Create new conversation
  const createNewConversation = async (): Promise<string | null> => {
    if (!userId) return null;

    try {
      const response = await fetch('/api/v1/conversations', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'x-user-id': userId,
        },
        body: JSON.stringify({}),
      });

      const data = await response.json();
      if (data.success) {
        const conversation = data.data;
        addConversation({
          id: conversation.id,
          title: conversation.title || '新对话',
          status: conversation.status,
          updatedAt: conversation.updatedAt,
          messageCount: 0,
        });
        setCurrentConversation(conversation.id);
        return conversation.id;
      }
    } catch (error) {
      console.error('Failed to create conversation:', error);
    }
    return null;
  };

  // Send message (with optional attachments)
  const sendMessage = useCallback(
    async (content: string) => {
      if (!userId) return;
      if (!content.trim() && pendingFiles.length === 0) return;

      let conversationId = currentConversationId;

      // Create new conversation if needed
      if (!conversationId) {
        conversationId = await createNewConversation();
        if (!conversationId) return;
      }

      // 先上传文件
      let attachments: FileAttachment[] = [];
      if (pendingFiles.length > 0) {
        attachments = await uploadFiles(conversationId);
      }

      // Add user message immediately
      const userMessage: Message = {
        id: `msg_${Date.now()}`,
        role: 'user',
        content: content.trim(),
        createdAt: new Date().toISOString(),
        attachments: attachments.length > 0 ? attachments : undefined,
      };
      addMessage(conversationId, userMessage);

      // Send via WebSocket (use globalSocket for reliability)
      const socket = globalSocket || socketRef.current;
      if (socket?.connected) {
        console.log('Sending message via WebSocket:', { conversationId, content: content.trim(), attachments });
        socket.emit('message', {
          conversationId,
          content: content.trim(),
          attachments: attachments.length > 0 ? attachments : undefined,
        });
      } else {
        console.error('WebSocket not connected, cannot send message. Socket state:', socket?.connected);
      }
    },
    [userId, currentConversationId, addMessage, pendingFiles, uploadFiles],
  );

  const createConversation = useCallback(async () => {
    return createNewConversation();
  }, [userId]);

  return {
    sendMessage,
    createConversation,
    // 文件上传相关
    pendingFiles,
    uploadProgress,
    isUploading,
    addFiles,
    removeFile,
    hasPendingFiles: pendingFiles.length > 0,
  };
}
