/**
 * 流式事件处理器
 *
 * 统一处理工作流和 Agent 的流式事件
 */

import type { Ref } from 'vue';

import type {
  AiChatPanelEmits,
  AiChatPanelProps,
  ChatMessage,
  DesignPreviewData,
  ReasoningStep,
  StreamEvent,
} from '../types';

/** 事件处理器配置 */
interface EventHandlerConfig {
  props: AiChatPanelProps;
  emit: AiChatPanelEmits;
  messages: Ref<ChatMessage[]>;
  currentSteps: Ref<ReasoningStep[]>;
  currentRunId: Ref<string>;
  currentAssistantMsgId: Ref<null | string>;
  waitingForInput: Ref<boolean>;
  waitingConfig: Ref<any>;
  running: Ref<boolean>;
  conversationId: Ref<null | string>;
  // 设计预览回调
  onDesignPreview?: (data: DesignPreviewData) => void;
}

/** 生成消息 ID */
const generateId = () =>
  `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;

/**
 * 创建事件处理器
 */
export function useEventHandler(config: EventHandlerConfig) {
  const {
    props,
    emit,
    messages,
    currentSteps,
    currentRunId,
    // currentAssistantMsgId 保留用于未来扩展
    waitingForInput,
    waitingConfig,
    running,
    onDesignPreview,
  } = config;

  /** 更新助手消息 */
  const updateAssistantMessage = (
    msgId: string,
    updates: Partial<ChatMessage>,
  ) => {
    const index = messages.value.findIndex((m) => m.id === msgId);
    if (index !== -1) {
      const currentMsg = messages.value[index];
      if (currentMsg) {
        messages.value[index] = { ...currentMsg, ...updates } as ChatMessage;
      }
    }
  };

  /** 获取等待提示文本 */
  const getWaitingPrompt = (waitConfig: any): string => {
    if (!waitConfig) return '等待输入...';
    switch (waitConfig.type) {
      case 'choice': {
        return waitConfig.question || '请选择：';
      }
      case 'confirm': {
        return `**${waitConfig.title || '确认'}**\n\n${waitConfig.content || '请确认是否继续？'}`;
      }
      case 'question': {
        return waitConfig.question || '请输入：';
      }
      default: {
        return '等待输入...';
      }
    }
  };

  /** 处理设计预览事件 */
  const handleDesignPreview = (
    event: StreamEvent,
    msgId: string,
    configData: any,
  ) => {
    const previewType = configData.preview_type;
    const previewData: DesignPreviewData = {
      type: previewType,
      title: configData.title || '设计预览',
      data: configData.data || {},
      nodeId: event.node_id || '',
      data_sources: configData.data_sources || configData.table_configs,
      schema_fields: configData.schema_fields || configData.form_fields,
      layoutOptions: configData.layoutOptions,
      themeOptions: configData.themeOptions,
    };

    // 调用设计预览回调
    onDesignPreview?.(previewData);

    // 显示提示消息
    const waitingContent = `**${configData.title}**\n\n${configData.message || '请在右侧面板中确认或编辑设计'}`;
    const initialMsg = messages.value.find((m) => m.id === msgId);
    if (initialMsg && !initialMsg.content?.trim()) {
      updateAssistantMessage(msgId, {
        status: 'completed',
        content: waitingContent,
      });
    } else {
      const newMsg: ChatMessage = {
        id: generateId(),
        role: 'assistant',
        content: waitingContent,
        timestamp: new Date(),
        status: 'completed',
      };
      messages.value.push(newMsg);
    }
  };

  /** 处理普通对话流交互 */
  const handleDialogFlowInteraction = (msgId: string, configData: any) => {
    const waitingContent = getWaitingPrompt(configData);

    const initialMsg = messages.value.find((m) => m.id === msgId);
    if (initialMsg && !initialMsg.content?.trim()) {
      updateAssistantMessage(msgId, {
        status: 'completed',
        content: waitingContent,
        interaction: configData,
      });
    } else {
      const newMsg: ChatMessage = {
        id: generateId(),
        role: 'assistant',
        content: waitingContent,
        timestamp: new Date(),
        status: 'completed',
        interaction: configData,
      };
      messages.value.push(newMsg);
    }
  };

  /** 获取节点显示名称（优先从前端 nodes 中获取） */
  const getNodeLabel = (
    nodeId?: string,
    nodeType?: string,
    fallbackLabel?: string,
  ) => {
    if (!nodeId) return fallbackLabel || nodeType || '';
    if (props.nodes?.length) {
      const node = props.nodes.find((n) => n.id === nodeId);
      if (node?.data?.label) return node.data.label as string;
    }
    return fallbackLabel || nodeType || '';
  };

  /** 处理流式事件 */
  const handleStreamEvent = (event: StreamEvent, msgId: string) => {
    switch (event.type) {
      // ========== Agent 特有事件 ==========
      case 'action': {
        currentSteps.value.push({
          type: 'action',
          content: '',
          tool: event.tool,
          params: event.params,
          timestamp: new Date().toISOString(),
        });
        updateAssistantMessage(msgId, {
          reasoning_steps: [...currentSteps.value],
        });
        break;
      }

      case 'answer': {
        const initialMsg = messages.value.find((m) => m.id === msgId);
        if (initialMsg && !initialMsg.content?.trim()) {
          updateAssistantMessage(msgId, {
            status: 'completed',
            content: event.content || '',
          });
        } else {
          const answerMsg: ChatMessage = {
            id: generateId(),
            role: 'assistant',
            content: event.content || '',
            timestamp: new Date(),
            status: 'completed',
          };
          messages.value.push(answerMsg);
        }
        break;
      }

      case 'complete': {
        let endOutput = '';
        if (
          event.outputs &&
          typeof event.outputs.output === 'string' &&
          event.outputs.output.trim()
        ) {
          endOutput = event.outputs.output;
        }

        const initialMsg = messages.value.find((m) => m.id === msgId);
        const initialMsgHasContent = initialMsg?.content?.trim();

        if (endOutput) {
          if (initialMsg && !initialMsgHasContent) {
            updateAssistantMessage(msgId, {
              status: 'completed',
              content: endOutput,
              elapsed_time: event.elapsed_time,
              tokens_used: event.tokens_used || event.total_tokens,
            });
          } else {
            const endMsg: ChatMessage = {
              id: generateId(),
              role: 'assistant',
              content: endOutput,
              timestamp: new Date(),
              status: 'completed',
              elapsed_time: event.elapsed_time,
              tokens_used: event.tokens_used || event.total_tokens,
            };
            messages.value.push(endMsg);
          }
        } else if (!initialMsgHasContent) {
          const otherAssistantMessages = messages.value.filter(
            (m) =>
              m.role === 'assistant' && m.id !== msgId && m.content?.trim(),
          );
          if (otherAssistantMessages.length > 0) {
            const initialMsgIndex = messages.value.findIndex(
              (m) => m.id === msgId,
            );
            if (initialMsgIndex !== -1) {
              messages.value.splice(initialMsgIndex, 1);
            }
          } else {
            updateAssistantMessage(msgId, {
              status: 'completed',
              elapsed_time: event.elapsed_time,
              tokens_used: event.tokens_used || event.total_tokens,
              content: '工作流执行完成',
            });
          }
        } else if (initialMsg) {
          // 流式输出已有内容，只更新状态和统计信息
          updateAssistantMessage(msgId, {
            status: 'completed',
            elapsed_time: event.elapsed_time,
            tokens_used: event.tokens_used || event.total_tokens,
          });
        }

        running.value = false;

        // 触发消息完成事件，用于刷新对话列表（更新标题）
        emit('message-complete', config.conversationId.value);
        break;
      }

      case 'error': {
        updateAssistantMessage(msgId, {
          status: 'failed',
          error_message: event.message || event.content || '执行失败',
        });
        running.value = false;
        break;
      }

      case 'llm_chunk': {
        // 更新助手消息内容（流式输出）
        const initialMsg = messages.value.find((m) => m.id === msgId);
        if (initialMsg) {
          updateAssistantMessage(msgId, {
            content: event.accumulated_content || event.content || '',
            status: 'streaming',
          });
        } else {
          // 如果消息不存在，创建新消息
          const streamMsg: ChatMessage = {
            id: msgId,
            role: 'assistant',
            content: event.accumulated_content || event.content || '',
            timestamp: new Date(),
            status: 'streaming',
          };
          messages.value.push(streamMsg);
        }

        if (props.enableNodeEvents) {
          emit('node-streaming', {
            node_id: event.node_id,
            content: event.content,
            accumulated_content: event.accumulated_content,
          });
        }
        break;
      }

      // ========== 循环事件 ==========
      case 'loop_complete': {
        const loopEvent = event as any;
        const outputVar = loopEvent.output_variable || 'loop_results';
        const outputs: Record<string, any> = {
          total_iterations: loopEvent.total_iterations,
          results_count: loopEvent.results_count,
        };
        if (loopEvent.loop_results) {
          outputs[outputVar] = loopEvent.loop_results;
        }

        if (props.enableNodeEvents) {
          emit('node-complete', {
            node_id: loopEvent.node_id,
            node_type: 'loop',
            status: 'success',
            elapsed_time: 0,
            tokens_used: 0,
            outputs,
          });
        }
        break;
      }

      case 'loop_iteration_complete': {
        if (props.enableNodeEvents) {
          emit('loop-iteration', {
            node_id: event.node_id,
            type: 'complete',
            iteration: event.iteration,
            total: event.total,
            output: event.output,
          });
        }
        break;
      }

      case 'loop_iteration_error': {
        if (props.enableNodeEvents) {
          emit('loop-iteration', {
            node_id: event.node_id,
            type: 'error',
            iteration: event.iteration,
            total: event.total,
            error: event.error,
          });
        }
        break;
      }

      case 'loop_iteration_start': {
        if (props.enableNodeEvents) {
          emit('loop-iteration', {
            node_id: event.node_id,
            type: 'start',
            iteration: event.iteration,
            total: event.total,
            item: event.item,
          });
        }
        break;
      }

      case 'node_complete': {
        const existingIndex = currentSteps.value.findIndex(
          (s) => s.node_id === event.node_id && s.type === 'node_start',
        );
        const completeLabel = getNodeLabel(
          event.node_id,
          event.node_type,
          event.node_label,
        );
        if (existingIndex === -1) {
          currentSteps.value.push({
            type: 'node_complete',
            content: completeLabel,
            node_id: event.node_id,
            node_type: event.node_type,
            output: event.outputs,
            status: 'completed',
            timestamp: new Date().toISOString(),
          });
        } else {
          currentSteps.value[existingIndex] = {
            ...currentSteps.value[existingIndex]!,
            type: 'node_complete',
            content: completeLabel,
            output: event.outputs,
            status: 'completed',
          };
        }
        updateAssistantMessage(msgId, {
          reasoning_steps: [...currentSteps.value],
        });

        if (props.enableNodeEvents) {
          emit('node-complete', {
            node_id: event.node_id,
            node_type: event.node_type,
            status: event.status,
            elapsed_time: event.elapsed_time,
            tokens_used: event.tokens_used,
            error_message: event.error_message,
            outputs: event.outputs,
            inputs: event.inputs,
            loop_iteration: event.loop_iteration,
            warnings: event.warnings,
          });
        }
        break;
      }

      case 'node_event': {
        const nodeEvent = event.event;
        if (nodeEvent?.type === 'message') {
          const initialMsg = messages.value.find((m) => m.id === msgId);
          if (initialMsg && !initialMsg.content?.trim()) {
            updateAssistantMessage(msgId, {
              status: 'completed',
              content: nodeEvent.content || '',
            });
          } else {
            const newMsg: ChatMessage = {
              id: generateId(),
              role: 'assistant',
              content: nodeEvent.content || '',
              timestamp: new Date(),
              status: 'completed',
            };
            messages.value.push(newMsg);
          }
        }
        break;
      }

      // ========== 节点事件 ==========
      case 'node_start': {
        const existingIndex = currentSteps.value.findIndex(
          (s) => s.node_id === event.node_id,
        );
        if (existingIndex === -1) {
          currentSteps.value.push({
            type: 'node_start',
            content: getNodeLabel(
              event.node_id,
              event.node_type,
              event.node_label,
            ),
            node_id: event.node_id,
            node_type: event.node_type,
            status: 'running',
            timestamp: new Date().toISOString(),
          });
        }
        updateAssistantMessage(msgId, {
          reasoning_steps: [...currentSteps.value],
        });

        if (props.enableNodeEvents) {
          emit('node-start', {
            node_id: event.node_id,
            node_type: event.node_type,
            node_label: event.node_label,
            inputs: event.inputs,
            loop_iteration: event.loop_iteration,
          });
        }
        break;
      }

      // ========== 通用事件 ==========
      case 'start': {
        currentRunId.value = event.run_id || '';
        break;
      }

      // ========== 对话流交互事件 ==========
      case 'waiting_input': {
        waitingForInput.value = true;
        waitingConfig.value = event.waiting_config || event.config;

        const configData = event.waiting_config || (event as any).config;

        if (configData?.type === 'design_preview') {
          handleDesignPreview(event, msgId, configData);
        } else {
          handleDialogFlowInteraction(msgId, configData);
        }

        running.value = false;
        break;
      }
    }
  };

  return {
    handleStreamEvent,
    updateAssistantMessage,
    getWaitingPrompt,
    generateId,
  };
}
