/**
 * 消息转换器
 * 将内部存储格式转换为 AI SDK ModelMessage 格式
 */

import type { ModelMessage } from 'ai';
import type { Message } from './message.js';
import type { Part, ToolPart, TextPart } from './parts.js';

/**
 * 将单条内部消息转换为 AI SDK ModelMessage 数组
 *
 * 对于 assistant 消息，可能产生 1-2 条 ModelMessage：
 * 1. assistant 消息（文本 + 工具调用）
 * 2. tool 消息（如果有已完成的工具调用）
 */
function messageToModelMessages(msg: Message): ModelMessage[] {
  const result: ModelMessage[] = [];

  if (msg.role === 'user') {
    // User 消息：提取所有文本
    const textContent = extractTextContent(msg.parts);
    if (textContent) {
      result.push({
        role: 'user',
        content: textContent,
      });
    }
    return result;
  }

  // Assistant 消息
  const textParts = msg.parts.filter((p): p is TextPart => p.type === 'text');
  const toolParts = msg.parts.filter((p): p is ToolPart => p.type === 'tool');

  // 构建 assistant 消息内容
  const assistantContent: unknown[] = [];

  // 添加文本部分
  for (const textPart of textParts) {
    assistantContent.push({
      type: 'text',
      text: textPart.text,
    });
  }

  // 添加工具调用部分（只有 running 或已完成的工具）
  // AI SDK v5 使用 input 字段（不是 args）
  for (const toolPart of toolParts) {
    if (toolPart.state.status !== 'pending') {
      assistantContent.push({
        type: 'tool-call',
        toolCallId: toolPart.toolCallId,
        toolName: toolPart.toolName,
        input: toolPart.state.input,
      });
    }
  }

  // 添加 assistant 消息
  if (assistantContent.length > 0) {
    // 简化：如果只有一个文本内容，直接使用字符串
    if (
      assistantContent.length === 1 &&
      (assistantContent[0] as { type: string }).type === 'text'
    ) {
      result.push({
        role: 'assistant',
        content: (assistantContent[0] as { text: string }).text,
      });
    } else {
      result.push({
        role: 'assistant',
        content: assistantContent,
      } as ModelMessage);
    }
  }

  // 如果有已完成/出错的工具调用，添加 tool 消息
  const completedToolParts = toolParts.filter(
    (p) => p.state.status === 'completed' || p.state.status === 'error'
  );

  if (completedToolParts.length > 0) {
    const toolContent = completedToolParts.map((toolPart) => {
      const state = toolPart.state;
      // 使用类型断言获取正确的值
      const output = state.status === 'completed'
        ? (state as { output: unknown }).output
        : (state as { error: string }).error;
      // 获取 input（AI SDK v5 要求 tool-result 必须包含 input）
      const input = state.status !== 'pending'
        ? (state as { input: Record<string, unknown> }).input
        : {};

      return {
        type: 'tool-result' as const,
        toolCallId: toolPart.toolCallId,
        toolName: toolPart.toolName,
        input,
        output,
      };
    });

    result.push({
      role: 'tool',
      content: toolContent,
    } as unknown as ModelMessage);
  }

  return result;
}

/**
 * 从 Parts 中提取纯文本内容
 */
function extractTextContent(parts: Part[]): string {
  return parts
    .filter((p): p is TextPart => p.type === 'text')
    .map((p) => p.text)
    .join('');
}

/**
 * 将内部消息列表转换为 AI SDK ModelMessage 数组
 *
 * 输入：内部存储的 Message[] (只有 user 和 assistant)
 * 输出：AI SDK 格式的 ModelMessage[] (包括 user, assistant, tool)
 */
export function toModelMessages(messages: Message[]): ModelMessage[] {
  const result: ModelMessage[] = [];

  for (const msg of messages) {
    const modelMessages = messageToModelMessages(msg);
    result.push(...modelMessages);
  }

  return result;
}

/**
 * 获取工具调用的输入参数（兼容不同状态）
 * 注意：AI SDK 的 input 是 unknown 类型，这里做安全转换
 */
export function getToolInput(toolPart: ToolPart): Record<string, unknown> {
  if (toolPart.state.status === 'pending') {
    return {};
  }
  const input = toolPart.state.input;
  // 安全转换：如果是对象返回对象，否则返回空对象
  if (input && typeof input === 'object' && !Array.isArray(input)) {
    return input as Record<string, unknown>;
  }
  return {};
}

/**
 * 获取工具调用的执行时长（毫秒）
 */
export function getToolDuration(toolPart: ToolPart): number | undefined {
  const state = toolPart.state;
  if (state.status === 'completed' || state.status === 'error') {
    return state.time.end - state.time.start;
  }
  if (state.status === 'running') {
    return Date.now() - state.time.start;
  }
  return undefined;
}
