import { useState, useEffect, useRef, useCallback } from 'react';
import { CyreneAvatar } from '@/components/persona/CyreneAvatar';
import { useAuthStore } from '@/store/authStore';
import { useChatStore } from '@/store/chatStore';
import { useSpeechSynthesis } from '@/hooks/useSpeechSynthesis';
import type { MessageAttachment, MultiMessageItem, StreamSegment, MessageDisplayType } from '@/types/chat';
import { ImageLightbox } from './ImageLightbox';

interface MessageBubbleProps {
  id: string;
  role: 'user' | 'assistant' | 'system' | 'action';
  content: string;
  timestamp: number;
  isStreaming?: boolean;
  attachments?: MessageAttachment[];
  multiMessages?: MultiMessageItem[];
  streamSegments?: StreamSegment[];
  msgType?: MessageDisplayType;
}

/**
 * 打字机逐字显示 Hook
 * 当 isStreaming 为 true 时，逐字显示 content；当流式结束时一次性显示全部
 */
function useTypewriter(content: string, isStreaming: boolean): string {
  const [displayed, setDisplayed] = useState('');
  const prevContentRef = useRef('');
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);

  useEffect(() => {
    if (!isStreaming) {
      // 流式结束，直接显示全部内容
      setDisplayed(content);
      prevContentRef.current = content;
      if (timerRef.current) {
        clearInterval(timerRef.current);
        timerRef.current = null;
      }
      return;
    }

    // 如果 content 重置了（新消息），从头开始
    if (content.length < prevContentRef.current.length && content.length < displayed.length) {
      setDisplayed('');
      prevContentRef.current = '';
    }

    // 启动逐字显示定时器
    const tick = () => {
      setDisplayed((prev) => {
        if (prev.length >= content.length) {
          if (timerRef.current) {
            clearInterval(timerRef.current);
            timerRef.current = null;
          }
          return prev;
        }
        // 每次显示一个字符，遇到中文字符时多等一帧
        return content.slice(0, prev.length + 1);
      });
    };

    if (timerRef.current) {
      clearInterval(timerRef.current);
    }

    // 根据内容长度动态调整速度：短内容快，长内容稍慢
    const speed = content.length > 200 ? 15 : content.length > 100 ? 20 : 30;
    timerRef.current = setInterval(tick, speed);

    prevContentRef.current = content;

    return () => {
      if (timerRef.current) {
        clearInterval(timerRef.current);
        timerRef.current = null;
      }
    };
  }, [content, isStreaming]);

  return displayed;
}

/**
 * AI 消息的操作栏 — 包含 TTS 朗读按钮
 */
function AIMessageActions({ content }: { content: string }) {
  const { isSpeaking, isSupported, speak, stop } = useSpeechSynthesis();
  const [isThisSpeaking, setIsThisSpeaking] = useState(false);
  const contentRef = useRef(content);

  // 当全局 TTS 正在朗读且对应的是本条消息时，设置 isThisSpeaking
  useEffect(() => {
    if (!isSpeaking) {
      setIsThisSpeaking(false);
    }
  }, [isSpeaking]);

  const handleToggleTTS = useCallback(() => {
    if (isThisSpeaking) {
      stop();
      setIsThisSpeaking(false);
    } else {
      setIsThisSpeaking(true);
      speak(content, { lang: 'zh-CN' });
      // 朗读结束后重置
      const checkEnd = setInterval(() => {
        if (!window.speechSynthesis.speaking) {
          setIsThisSpeaking(false);
          clearInterval(checkEnd);
        }
      }, 200);
    }
  }, [content, isThisSpeaking, speak, stop]);

  if (!isSupported) return null;

  return (
    <div className="flex items-center gap-1 mt-1.5">
      <button
        onClick={handleToggleTTS}
        className={`inline-flex items-center gap-1 text-xs px-2 py-1 rounded-full transition-all duration-200 ${
          isThisSpeaking
            ? 'bg-pink-100 text-pink-600 tts-playing'
            : 'text-gray-400 hover:text-pink-500 hover:bg-pink-50'
        }`}
        title={isThisSpeaking ? '停止朗读' : '朗读此消息'}
      >
        {isThisSpeaking ? (
          <>
            <span className="text-sm">⏹</span>
            <span>停止</span>
          </>
        ) : (
          <>
            <span className="text-sm">🔊</span>
            <span>朗读</span>
          </>
        )}
      </button>
    </div>
  );
}

export function MessageBubble({
  id,
  role,
  content,
  timestamp,
  isStreaming,
  attachments,
  multiMessages,
  streamSegments,
  msgType,
}: MessageBubbleProps) {
  const isUser = role === 'user';
  const isAction = role === 'action' || msgType === 'action';
  const isThinking = msgType === 'thinking';
  const isToolProgress = msgType === 'tool_progress';
  const isSystemInfo = msgType === 'system_info';

  // 动作消息使用独立的渲染方式
  if (isAction) {
    return <ActionMessageBubble content={content} timestamp={timestamp} />;
  }

  // 思考内容 — 可折叠面板
  if (isThinking) {
    return (
      <details className="mx-4 my-1 px-3 py-2 bg-gray-50 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 text-xs text-gray-500 dark:text-gray-400 italic">
        <summary className="cursor-pointer select-none">昔涟正在思考...</summary>
        <p className="mt-1 whitespace-pre-wrap">{content}</p>
      </details>
    );
  }

  // 工具进度 — 紧凑进度行
  if (isToolProgress) {
    return (
      <div className="flex items-center gap-2 mx-4 my-1 px-3 py-1 text-xs text-gray-400 dark:text-gray-500">
        <span className="inline-block w-2 h-2 rounded-full bg-blue-400 animate-pulse" />
        <span>{content}</span>
      </div>
    );
  }

  // 系统信息 — 居中 Toast 风格
  if (isSystemInfo) {
    return (
      <div className="flex justify-center my-1">
        <span className="text-xs text-gray-400 dark:text-gray-500 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded-full">
          {content}
        </span>
      </div>
    );
  }

  const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
  const time = new Date(timestamp).toLocaleTimeString('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
  });

  // 流式消息使用打字机逐字显示
  const displayedContent = useTypewriter(content, !!isStreaming);
  // 判断是否还有未显示完的字符
  const hasMoreChars = isStreaming && displayedContent.length < content.length;

  // When typewriter animation finishes, notify store to process next queued message.
  const typewriterComplete = isStreaming && content.length > 0 && displayedContent.length >= content.length;
  const doneNotifiedRef = useRef(false);
  useEffect(() => {
    if (typewriterComplete && !doneNotifiedRef.current) {
      doneNotifiedRef.current = true;
      const timer = setTimeout(() => {
        useChatStore.getState().onTypewriterDone(id);
      }, 200);
      return () => clearTimeout(timer);
    }
  }, [typewriterComplete, id]);

  // 图片附件
  const imageAttachments = attachments?.filter((a) => a.type === 'image') ?? [];

  return (
    <div className={`flex px-4 py-2 gap-2 items-end group ${isUser ? 'justify-end' : ''}`}>
      {/* 用户消息：时间在左侧（气泡外侧） */}
      {isUser && !isStreaming && (
        <p className="text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0 mb-1 hidden md:block md:opacity-0 group-hover:opacity-100 transition-opacity duration-200">
          {time}
        </p>
      )}

      {/* 头像 */}
      {!isUser && (
        <CyreneAvatar size="sm" className="flex-shrink-0 mb-0.5" />
      )}

      {/* 消息气泡 */}
      <div
        className={`
          max-w-[75%] px-4 py-2.5 rounded-2xl text-sm leading-relaxed shadow-sm
          ${
            isUser
              ? 'bg-pink-400 text-white rounded-br-md'
              : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 rounded-bl-md border border-pink-100 dark:border-pink-900'
          }
          ${isStreaming ? 'message-streaming' : ''}
        `}
      >

        {/* 多段消息渲染 (multi_message 类型) */}
        {multiMessages && multiMessages.length > 0 && !isStreaming && (
          <div className="space-y-2">
            {multiMessages
              .sort((a, b) => a.index - b.index)
              .map((item) => (
                <p key={item.index} className="whitespace-pre-wrap break-words">
                  {item.content}
                </p>
              ))}
          </div>
        )}

        {/* 流式片段渲染 (stream_segments 类型) */}
        {streamSegments && streamSegments.length > 0 && !isStreaming && (
          <div className="space-y-1.5">
            {streamSegments
              .sort((a, b) => a.index - b.index)
              .map((seg) => (
                <p key={seg.index} className="whitespace-pre-wrap break-words text-gray-600 dark:text-gray-400">
                  {seg.text}
                </p>
              ))}
          </div>
        )}

        {/* 普通文本 / 流式文本 */}
        {(!multiMessages || multiMessages.length === 0) && (!streamSegments || streamSegments.length === 0) && (
          <p className="whitespace-pre-wrap break-words">
            {isStreaming ? displayedContent : content}
            {/* 流式消息末尾闪烁光标 — 用独立 span 避免 ::after 在隐藏字符后错位 */}
            {hasMoreChars && (
              <span className="animate-streaming-cursor" />
            )}
          </p>
        )}

        {/* 图片附件网格 */}
        {!isStreaming && imageAttachments.length > 0 && (
          <div
            className={`grid gap-1.5 mt-2 ${
              imageAttachments.length === 1
                ? 'grid-cols-1'
                : imageAttachments.length === 2
                ? 'grid-cols-2'
                : 'grid-cols-3'
            }`}
          >
            {imageAttachments.map((att, idx) => (
              <ImageThumbnail
                key={idx}
                attachment={att}
                onClick={() => setLightboxIndex(idx)}
              />
            ))}
          </div>
        )}
      </div>

      {/* 昔涟消息：时间在右侧（气泡外侧） */}
      {!isUser && !isStreaming && (
        <p className="text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0 mb-1 hidden md:block md:opacity-0 group-hover:opacity-100 transition-opacity duration-200">
          {time}
        </p>
      )}

      {/* 用户头像 */}
      {isUser && <UserAvatar />}

      {/* Lightbox */}
      {lightboxIndex !== null && (
        <ImageLightbox
          attachments={imageAttachments}
          currentIndex={lightboxIndex}
          onClose={() => setLightboxIndex(null)}
        />
      )}
    </div>
  );
}

/** 动作消息气泡 — 居左，与昔涟头像对齐，灰色/斜体与聊天消息区分 */
function ActionMessageBubble({ content, timestamp }: { content: string; timestamp: number }) {
  const time = new Date(timestamp).toLocaleTimeString('zh-CN', {
    hour: '2-digit',
    minute: '2-digit',
  });

  return (
    <div className="flex px-4 py-0.5 gap-1.5 items-end group animate-fadeIn">
      <div className="w-8 flex-shrink-0" />
      <div className="max-w-[70%]">
        <p className="text-xs text-gray-400 dark:text-gray-500 italic leading-snug whitespace-pre-wrap break-words">
          {content}
        </p>
      </div>
      <p className="text-[10px] text-gray-400 dark:text-gray-500 flex-shrink-0 mb-0.5 hidden md:block md:opacity-0 group-hover:opacity-100 transition-opacity duration-200">
        {time}
      </p>
    </div>
  );
}

/** 图片缩略图组件 */
function ImageThumbnail({
  attachment,
  onClick,
}: {
  attachment: MessageAttachment;
  onClick: () => void;
}) {
  const [loaded, setLoaded] = useState(false);
  const [error, setError] = useState(false);
  const url = attachment.thumbnail_url || attachment.url;

  return (
    <button
      onClick={onClick}
      className="relative w-full aspect-square rounded-lg overflow-hidden border border-pink-100 dark:border-pink-800 bg-gray-100 dark:bg-gray-700 hover:ring-2 hover:ring-pink-400 transition-all cursor-pointer group"
      aria-label={`查看图片: ${attachment.filename || '未命名图片'}`}
    >
      {/* 加载中 */}
      {!loaded && !error && (
        <div className="absolute inset-0 flex items-center justify-center text-gray-400">
          <svg className="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
          </svg>
        </div>
      )}

      {/* 加载失败 */}
      {error && (
        <div className="absolute inset-0 flex items-center justify-center text-gray-400">
          <span className="text-2xl">🖼️</span>
        </div>
      )}

      {/* 图片 */}
      <img
        src={url}
        alt={attachment.filename || '图片'}
        className={`w-full h-full object-cover transition-transform group-hover:scale-105 ${loaded ? 'block' : 'hidden'}`}
        onLoad={() => setLoaded(true)}
        onError={() => setError(true)}
      />

      {/* 悬停遮罩 */}
      {loaded && (
        <div className="absolute inset-0 bg-black/0 group-hover:bg-black/20 transition-colors flex items-center justify-center">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="w-6 h-6 text-white opacity-0 group-hover:opacity-100 transition-opacity">
            <path fillRule="evenodd" d="M15 3.75a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0V5.56l-3.97 3.97a.75.75 0 11-1.06-1.06l3.97-3.97h-3.69a.75.75 0 010-1.5h4.5zM5.25 6.75a3 3 0 00-3 3v7.5a3 3 0 003 3h13.5a3 3 0 003-3v-7.5a3 3 0 00-3-3H15a.75.75 0 000 1.5h3.75a1.5 1.5 0 011.5 1.5v7.5a1.5 1.5 0 01-1.5 1.5H5.25a1.5 1.5 0 01-1.5-1.5v-7.5a1.5 1.5 0 011.5-1.5H9a.75.75 0 000-1.5H5.25z" clipRule="evenodd" />
          </svg>
        </div>
      )}
    </button>
  );
}

/** 用户头像组件：管理员使用 Admin_Avatar.jpg，普通用户使用 Default_Avatar.png */
function UserAvatar() {
  const [imgError, setImgError] = useState(false);
  const userId = useAuthStore((s) => s.userId);
  const isAdmin = userId === 'admin';
  const avatarSrc = isAdmin
    ? '/images/User_Avatar/Admin_Avatar.jpg'
    : '/images/User_Avatar/Default_Avatar.png';

  if (imgError) {
    return (
      <div className="w-8 h-8 rounded-full bg-gradient-to-br from-pink-300 to-pink-500 flex items-center justify-center flex-shrink-0 mt-1 shadow-sm">
        <span className="text-white text-sm">开拓者</span>
      </div>
    );
  }

  return (
    <img
      src={avatarSrc}
      alt={isAdmin ? '管理员' : '用户'}
      className="w-8 h-8 rounded-full object-cover flex-shrink-0 mt-1 shadow-sm"
      onError={() => setImgError(true)}
    />
  );
}
