/**
 * useChatAssistant Hook
 * Centralized chat logic for the LLM assistant
 */

import { useState, useCallback, useEffect, useRef } from 'react';
import { useChatStore } from '../../../stores/chatStore';
import type { Message } from '../components/ChatMessage';
import type { ToolCall } from '../components/ToolCallCard';
import { extractTradingSignals, extractMentionedTools } from '../utils/messageFormatters';

export interface ChatAssistantOptions {
  sessionId?: string;
  autoScroll?: boolean;
  maxRetries?: number;
  retryDelay?: number;
}

export interface SendMessageOptions {
  attachments?: File[];
  context?: Record<string, unknown>;
  tools?: string[];
}

export interface ChatAssistantState {
  messages: Message[];
  isLoading: boolean;
  isStreaming: boolean;
  error: string | null;
  currentSessionId: string | null;
  pendingToolCalls: ToolCall[];
}

export interface ChatAssistantActions {
  sendMessage: (content: string, options?: SendMessageOptions) => Promise<void>;
  regenerateLastResponse: () => Promise<void>;
  cancelGeneration: () => void;
  clearError: () => void;
  createNewSession: () => Promise<string>;
  loadSession: (sessionId: string) => Promise<void>;
  deleteMessage: (messageId: string) => void;
  editMessage: (messageId: string, newContent: string) => Promise<void>;
}

export function useChatAssistant(options: ChatAssistantOptions = {}): ChatAssistantState & ChatAssistantActions {
  const {
    sessionId: initialSessionId,
    autoScroll = true,
    maxRetries = 3,
    retryDelay = 1000,
  } = options;

  // Store state
  const {
    sessions,
    currentSessionId,
    messages: storeMessages,
    loading,
    error: storeError,
    createNewSession: storeCreateSession,
    loadSession: storeLoadSession,
    sendMessage: storeSendMessage,
    deleteSession,
  } = useChatStore();

  // Local state
  const [isStreaming, setIsStreaming] = useState(false);
  const [localError, setLocalError] = useState<string | null>(null);
  const [pendingToolCalls, setPendingToolCalls] = useState<ToolCall[]>([]);

  // Refs
  const abortControllerRef = useRef<AbortController | null>(null);
  const messagesEndRef = useRef<HTMLDivElement | null>(null);
  const retryCountRef = useRef(0);

  // Initialize session
  useEffect(() => {
    if (initialSessionId && initialSessionId !== currentSessionId) {
      storeLoadSession(initialSessionId);
    }
  }, [initialSessionId, currentSessionId, storeLoadSession]);

  // Auto-scroll on new messages
  useEffect(() => {
    if (autoScroll && messagesEndRef.current) {
      messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [storeMessages, autoScroll]);

  // Transform store messages to include parsed data
  const messages: Message[] = storeMessages.map((msg) => ({
    ...msg,
    // Convert timestamp to Date if it's a string (from JSON serialization)
    timestamp: typeof msg.timestamp === 'string' ? new Date(msg.timestamp) : msg.timestamp,
    tools_used: (msg as { toolsUsed?: string[] }).toolsUsed || extractMentionedTools(msg.content),
  }));

  // Send message with retry logic
  const sendMessage = useCallback(async (
    content: string,
    sendOptions: SendMessageOptions = {}
  ) => {
    if (!content.trim()) return;

    setLocalError(null);
    abortControllerRef.current = new AbortController();

    try {
      // Add user message optimistically
      const userMessage: Message = {
        id: `temp-${Date.now()}`,
        role: 'user',
        content,
        timestamp: new Date(),
      };

      // If tools are requested, set up pending tool calls
      if (sendOptions.tools?.length) {
        setPendingToolCalls(
          sendOptions.tools.map((tool) => ({
            id: `pending-${tool}`,
            name: tool,
            arguments: {},
            status: 'pending',
          }))
        );
      }

      setIsStreaming(true);

      // Send to store/API
      await storeSendMessage(content);

      // Clear pending tool calls on success
      setPendingToolCalls([]);
      retryCountRef.current = 0;

    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to send message';

      // Retry logic
      if (retryCountRef.current < maxRetries && !abortControllerRef.current?.signal.aborted) {
        retryCountRef.current++;
        await new Promise((resolve) => setTimeout(resolve, retryDelay * retryCountRef.current));
        return sendMessage(content, sendOptions);
      }

      setLocalError(errorMessage);
      setPendingToolCalls([]);
    } finally {
      setIsStreaming(false);
      abortControllerRef.current = null;
    }
  }, [storeSendMessage, maxRetries, retryDelay]);

  // Regenerate last assistant response
  const regenerateLastResponse = useCallback(async () => {
    const lastUserMessage = [...messages].reverse().find((m) => m.role === 'user');
    if (!lastUserMessage) return;

    // Remove the last assistant message from local state
    // Using reverse().findIndex() as a polyfill for findLastIndex
    const reversedMessages = [...messages].reverse();
    const reverseIdx = reversedMessages.findIndex((m) => m.role === 'assistant');
    const lastAssistantIdx = reverseIdx >= 0 ? messages.length - 1 - reverseIdx : -1;
    if (lastAssistantIdx >= 0) {
      // In a real implementation, we'd call an API to regenerate
      await sendMessage(lastUserMessage.content);
    }
  }, [messages, sendMessage]);

  // Cancel ongoing generation
  const cancelGeneration = useCallback(() => {
    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
      setIsStreaming(false);
      setPendingToolCalls([]);
    }
  }, []);

  // Clear error
  const clearError = useCallback(() => {
    setLocalError(null);
  }, []);

  // Create new session
  const createNewSession = useCallback(async (): Promise<string> => {
    await storeCreateSession();
    // After creating, the store updates currentSessionId, so we get it from there
    // We need to get the updated value from the store
    const { currentSessionId: newSessionId } = useChatStore.getState();
    return newSessionId ?? '';
  }, [storeCreateSession]);

  // Load existing session
  const loadSession = useCallback(async (sessionId: string) => {
    await storeLoadSession(sessionId);
  }, [storeLoadSession]);

  // Delete a message (local only, would need API support)
  const deleteMessage = useCallback((messageId: string) => {
    // This would require store support
    console.warn('deleteMessage not implemented in store');
  }, []);

  // Edit a message and regenerate
  const editMessage = useCallback(async (messageId: string, newContent: string) => {
    // Find the message and regenerate from that point
    const messageIdx = messages.findIndex((m) => m.id === messageId);
    if (messageIdx === -1) return;

    // In a real implementation, we'd truncate history and regenerate
    await sendMessage(newContent);
  }, [messages, sendMessage]);

  return {
    // State
    messages,
    isLoading: loading,
    isStreaming,
    error: localError || storeError,
    currentSessionId,
    pendingToolCalls,

    // Actions
    sendMessage,
    regenerateLastResponse,
    cancelGeneration,
    clearError,
    createNewSession,
    loadSession,
    deleteMessage,
    editMessage,
  };
}

// Export types
export type UseChatAssistantReturn = ReturnType<typeof useChatAssistant>;

export default useChatAssistant;
