/**
 * Chat Message Component
 */

import {
  User,
  Bot,
  Copy,
  Check,
  Wrench,
  ChevronDown,
  ChevronRight,
  Clock,
  AlertCircle,
  CheckCircle2,
  Loader2,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { useState, forwardRef } from 'react';
import { cn } from '../utils/cn';
import { fadeInUp, smoothTransition } from '../utils/animations';
import { getAgentDisplayName } from '../utils/agent';
import { Markdown } from './Markdown';
import { FileMentionText } from './FileMentionTag';
import type { Message, ToolCallInfo, ToolCallStatus, ToolMessagePart } from '../api/types.js';

interface ChatMessageProps {
  message: Message;
  /** 是否为流式输出中（显示打字光标） */
  isStreaming?: boolean;
}

export const ChatMessage = forwardRef<HTMLDivElement, ChatMessageProps>(
  ({ message, isStreaming = false }, ref) => {
    const isUser = message.role === 'user';
    const [copied, setCopied] = useState(false);

    const handleCopy = async () => {
      await navigator.clipboard.writeText(message.content ?? '');
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    };

    // 渲染消息内容 - 使用 parts 保持原始顺序
    const renderContent = () => {
      // 优先使用 parts 数组（保持原始顺序）
      if (message.parts && message.parts.length > 0) {
        // 查找最后一个文本 part 的索引（用于显示打字光标）
        let lastTextPartIndex = -1;
        if (isStreaming) {
          for (let i = message.parts.length - 1; i >= 0; i--) {
            if (message.parts[i].type === 'text') {
              lastTextPartIndex = i;
              break;
            }
          }
        }

        return (
          <div className="message-content text-fg-secondary space-y-3">
            {message.parts.map((part, index) => {
              switch (part.type) {
                case 'text':
                  if (!part.text && index !== lastTextPartIndex) return null;
                  return isUser ? (
                    <div key={part.id}>
                      <FileMentionText text={part.text} />
                    </div>
                  ) : (
                    <div key={part.id}>
                      <Markdown content={part.text} />
                      {/* 流式输出时在最后一个文本末尾显示打字光标 */}
                      {isStreaming && index === lastTextPartIndex && (
                        <motion.span
                          animate={{ opacity: [1, 0] }}
                          transition={{ duration: 0.8, repeat: Infinity, repeatType: 'reverse' }}
                          className="inline-block w-2 h-4 bg-primary-400 ml-1 rounded-sm align-middle"
                        />
                      )}
                    </div>
                  );
                case 'tool':
                  return <ToolPartItem key={part.id} part={part} />;
                case 'reasoning':
                  return (
                    <div key={part.id} className="text-fg-muted italic border-l-2 border-line pl-3">
                      {part.text}
                    </div>
                  );
                default:
                  return null;
              }
            })}
          </div>
        );
      }

      // 回退：使用旧的 content + toolCalls 字段
      return (
        <>
          {!isUser && message.toolCalls && message.toolCalls.length > 0 && (
            <ToolCallsDisplay toolCalls={message.toolCalls} />
          )}
          <div className="message-content text-fg-secondary">
            {isUser ? (
              <div>
                <FileMentionText text={message.content ?? ''} />
              </div>
            ) : (
              <Markdown content={message.content ?? ''} />
            )}
          </div>
        </>
      );
    };

    return (
      <motion.div
        ref={ref}
        variants={fadeInUp}
        initial="initial"
        animate="animate"
        exit="exit"
        transition={smoothTransition}
        className={cn(
          'group flex gap-4 p-4 rounded-lg',
          isUser ? 'bg-surface-subtle' : 'bg-surface-subtle/50'
        )}
      >
        <div
          className={cn(
            'w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 text-white',
            isUser ? 'bg-primary-600' : 'bg-green-600'
          )}
        >
          {isUser ? <User size={18} /> : <Bot size={18} />}
        </div>
        <div className="flex-1 min-w-0 overflow-hidden">
          <div className="flex items-center justify-between mb-1">
            <span className="text-sm text-fg-muted">
              {isUser ? 'You' : getAgentDisplayName(message.metadata?.agentName)}
            </span>
            <button
              onClick={handleCopy}
              className="opacity-0 group-hover:opacity-100 p-1 rounded text-fg-subtle hover:text-fg-muted hover:bg-surface-muted transition-all"
              title="Copy message"
            >
              {copied ? <Check size={14} className="text-green-500" /> : <Copy size={14} />}
            </button>
          </div>
          {renderContent()}
        </div>
      </motion.div>
    );
  }
);

interface StreamingMessageProps {
  content: string;
  /** 当前 Agent 名称 */
  agentName?: string;
}

export function StreamingMessage({ content, agentName }: StreamingMessageProps) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      transition={smoothTransition}
      className="flex gap-4 p-4 rounded-lg bg-surface-subtle/50"
    >
      <div className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 bg-green-600 text-white">
        <Bot size={18} />
      </div>
      <div className="flex-1 min-w-0 overflow-hidden">
        <div className="text-sm text-fg-muted mb-1">{getAgentDisplayName(agentName)}</div>
        <div className="message-content text-fg-secondary">
          <Markdown content={content} />
          <motion.span
            animate={{ opacity: [1, 0] }}
            transition={{ duration: 0.8, repeat: Infinity, repeatType: 'reverse' }}
            className="inline-block w-2 h-4 bg-primary-400 ml-1 rounded-sm align-middle"
          />
        </div>
      </div>
    </motion.div>
  );
}

interface TypingIndicatorProps {
  /** 当前 Agent 名称 */
  agentName?: string;
}

export function TypingIndicator({ agentName }: TypingIndicatorProps) {
  return (
    <motion.div
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      transition={smoothTransition}
      className="flex gap-4 p-4 rounded-lg bg-surface-subtle/50"
    >
      <div className="w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 bg-green-600 text-white">
        <Bot size={18} />
      </div>
      <div className="flex-1">
        <div className="text-sm text-fg-muted mb-1">{getAgentDisplayName(agentName)}</div>
        <div className="flex items-center gap-1 h-6">
          {[0, 1, 2].map((i) => (
            <motion.span
              key={i}
              animate={{ y: [0, -4, 0] }}
              transition={{
                duration: 0.6,
                repeat: Infinity,
                delay: i * 0.15,
              }}
              className="w-2 h-2 rounded-full bg-fg-muted"
            />
          ))}
        </div>
      </div>
    </motion.div>
  );
}

// ============ 工具调用显示组件 ============

/**
 * 单个工具 Part 项（用于 parts 数组渲染）
 */
interface ToolPartItemProps {
  part: ToolMessagePart;
}

function ToolPartItem({ part }: ToolPartItemProps) {
  const [expanded, setExpanded] = useState(false);
  const hasDetails =
    Object.keys(part.arguments).length > 0 ||
    part.result !== undefined ||
    part.error !== undefined;

  return (
    <div className="border border-line rounded-lg overflow-hidden bg-surface-subtle/30">
      {/* 头部：工具名称、状态、时长 */}
      <button
        onClick={() => hasDetails && setExpanded(!expanded)}
        className={cn(
          'w-full flex items-center gap-2 px-3 py-2 text-sm',
          hasDetails && 'hover:bg-surface-muted/50 cursor-pointer',
          !hasDetails && 'cursor-default'
        )}
      >
        <Wrench size={14} className="text-fg-muted flex-shrink-0" />
        <span className="font-mono text-fg-secondary flex-1 text-left truncate">
          {part.toolName}
        </span>
        {getStatusIcon(part.status)}
        {part.duration && (
          <span className="text-xs text-fg-subtle">{formatDuration(part.duration)}</span>
        )}
        {hasDetails && (
          <span className="text-fg-subtle">
            {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
          </span>
        )}
      </button>

      {/* 展开的详情 */}
      <AnimatePresence>
        {expanded && hasDetails && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="border-t border-line overflow-hidden"
          >
            <div className="px-3 py-2 space-y-2 text-xs">
              {/* 参数 */}
              {Object.keys(part.arguments).length > 0 && (
                <div>
                  <div className="text-fg-subtle mb-1">Arguments:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-fg-muted max-h-48 overflow-y-auto">
                    {JSON.stringify(part.arguments, null, 2)}
                  </pre>
                </div>
              )}

              {/* 结果 */}
              {part.result !== undefined && (
                <div>
                  <div className="text-fg-subtle mb-1">Result:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-green-400 max-h-48 overflow-y-auto">
                    {typeof part.result === 'string'
                      ? part.result
                      : JSON.stringify(part.result, null, 2)}
                  </pre>
                </div>
              )}

              {/* 错误 */}
              {part.error && (
                <div>
                  <div className="text-red-400 mb-1">Error:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-red-300 max-h-48 overflow-y-auto">
                    {part.error}
                  </pre>
                </div>
              )}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}

/**
 * 获取工具状态图标
 */
function getStatusIcon(status: ToolCallStatus) {
  switch (status) {
    case 'pending':
      return <Clock size={14} className="text-yellow-500" />;
    case 'running':
      return <Loader2 size={14} className="text-blue-500 animate-spin" />;
    case 'completed':
      return <CheckCircle2 size={14} className="text-green-500" />;
    case 'error':
      return <AlertCircle size={14} className="text-red-500" />;
  }
}

/**
 * 格式化执行时长
 */
function formatDuration(ms?: number): string {
  if (!ms) return '';
  if (ms < 1000) return `${ms}ms`;
  return `${(ms / 1000).toFixed(1)}s`;
}

/**
 * 工具调用列表容器
 */
interface ToolCallsDisplayProps {
  toolCalls: ToolCallInfo[];
}

function ToolCallsDisplay({ toolCalls }: ToolCallsDisplayProps) {
  return (
    <div className="mb-3 space-y-2">
      {toolCalls.map((toolCall) => (
        <ToolCallItem key={toolCall.id} toolCall={toolCall} />
      ))}
    </div>
  );
}

/**
 * 单个工具调用项
 */
interface ToolCallItemProps {
  toolCall: ToolCallInfo;
}

function ToolCallItem({ toolCall }: ToolCallItemProps) {
  const [expanded, setExpanded] = useState(false);
  const hasDetails =
    Object.keys(toolCall.arguments).length > 0 ||
    toolCall.result !== undefined ||
    toolCall.error !== undefined;

  return (
    <div className="border border-line rounded-lg overflow-hidden bg-surface-subtle/30">
      {/* 头部：工具名称、状态、时长 */}
      <button
        onClick={() => hasDetails && setExpanded(!expanded)}
        className={cn(
          'w-full flex items-center gap-2 px-3 py-2 text-sm',
          hasDetails && 'hover:bg-surface-muted/50 cursor-pointer',
          !hasDetails && 'cursor-default'
        )}
      >
        <Wrench size={14} className="text-fg-muted flex-shrink-0" />
        <span className="font-mono text-fg-secondary flex-1 text-left truncate">
          {toolCall.name}
        </span>
        {getStatusIcon(toolCall.status)}
        {toolCall.duration && (
          <span className="text-xs text-fg-subtle">{formatDuration(toolCall.duration)}</span>
        )}
        {hasDetails && (
          <span className="text-fg-subtle">
            {expanded ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
          </span>
        )}
      </button>

      {/* 展开的详情 */}
      <AnimatePresence>
        {expanded && hasDetails && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="border-t border-line overflow-hidden"
          >
            <div className="px-3 py-2 space-y-2 text-xs">
              {/* 参数 */}
              {Object.keys(toolCall.arguments).length > 0 && (
                <div>
                  <div className="text-fg-subtle mb-1">Arguments:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-fg-muted max-h-48 overflow-y-auto">
                    {JSON.stringify(toolCall.arguments, null, 2)}
                  </pre>
                </div>
              )}

              {/* 结果 */}
              {toolCall.result !== undefined && (
                <div>
                  <div className="text-fg-subtle mb-1">Result:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-green-400 max-h-48 overflow-y-auto">
                    {typeof toolCall.result === 'string'
                      ? toolCall.result
                      : JSON.stringify(toolCall.result, null, 2)}
                  </pre>
                </div>
              )}

              {/* 错误 */}
              {toolCall.error && (
                <div>
                  <div className="text-red-400 mb-1">Error:</div>
                  <pre className="bg-surface-base rounded p-2 overflow-x-auto text-red-300 max-h-48 overflow-y-auto">
                    {toolCall.error}
                  </pre>
                </div>
              )}
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
}
