/**
 * 聊天消息组件 - 支持 Markdown 渲染和 JSON 组件混排
 *
 * 更新：使用官方 @json-render/core API
 * - 支持从 props 直接接收编译后的 specs
 * - 使用官方 Renderer 渲染组件
 */
'use client';

import { useEffect, useMemo } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Renderer, JSONUIProvider } from '@json-render/react';
import { compileSpecStream, parseSpecStreamLine } from '@json-render/core';
import { registry } from '@/lib/registry';
import { useActionEmit } from '@/lib/action-context';
import type { Spec } from '@json-render/core';

interface ChatMessageProps {
  role: 'user' | 'assistant';
  content: string;
  isLoading?: boolean;
  specs?: Spec[];  // 新增：接收编译后的 specs
}

/**
 * 检查文本是否为 JSON Patch 格式 (SpecStream)
 */
function isSpecStreamFormat(text: string): boolean {
  const lines = text.split('\n').filter(l => l.trim());
  if (lines.length === 0) return false;

  let patchCount = 0;
  for (const line of lines.slice(0, 5)) {
    const patch = parseSpecStreamLine(line);
    if (patch) patchCount++;
  }

  return patchCount >= 2;
}

/**
 * 从 SpecStream 格式中编译出完整的 spec
 */
function compileSpecFromStream(text: string): Spec | null {
  try {
    const spec = compileSpecStream(text as any);
    console.log('[compileSpecFromStream] Compiled spec:', spec);
    return spec;
  } catch (e) {
    console.error('[compileSpecFromStream] Failed to compile:', e);
    return null;
  }
}

/**
 * 从编译后的 spec 中提取可渲染的元素
 * 对于 flat 格式 {root, elements}，返回 root 指向的元素
 */
function extractRenderableElements(spec: Spec): Spec[] {
  const elements: Spec[] = [];

  if (!spec || typeof spec !== 'object') return elements;

  // 如果 spec 有 root 和 elements 字段（flat 格式）
  // 需要渲染整个 spec 对象，让 Renderer 根据 root 找到对应元素
  if (spec.root && spec.elements && typeof spec.elements === 'object') {
    // 返回完整的 flat spec，Renderer 会处理
    elements.push(spec);
    return elements;
  }

  // 如果 spec 有 elements 字段但没有 root
  if (spec.elements && typeof spec.elements === 'object') {
    for (const [key, element] of Object.entries(spec.elements)) {
      if (element && typeof element === 'object' && 'type' in element) {
        elements.push(element as Spec);
      }
    }
  }

  // 如果 spec 本身就是一个组件
  if ('type' in spec && spec.type) {
    elements.push(spec);
  }

  return elements;
}

function CodeBlock({ inline, className, children, ...props }: any) {
  const code = String(children).replace(/\n$/, '');
  if (inline) {
    return <code className="bg-gray-100 dark:bg-gray-900 px-1.5 py-0.5 rounded text-sm font-mono" {...props}>{children}</code>;
  }
  const match = /language-(\w+)/.exec(className || '');
  const language = match ? match[1] : 'text';
  return (
    <div className="code-block bg-gray-900 rounded-lg overflow-x-auto my-2">
      <div className="flex items-center justify-between px-4 py-2 bg-gray-800 border-b border-gray-700">
        <span className="text-xs text-gray-400 uppercase">{language}</span>
        <button onClick={() => navigator.clipboard.writeText(code)} className="text-xs text-gray-400 hover:text-white">复制</button>
      </div>
      <pre className="p-4 text-sm text-gray-100 font-mono overflow-x-auto"><code {...props}>{children}</code></pre>
    </div>
  );
}

function Paragraph({ children }: any) {
  return <p className="my-2 leading-relaxed">{children}</p>;
}

export default function ChatMessage({ role, content, isLoading, specs: propSpecs }: ChatMessageProps) {
  const isUser = role === 'user';
  const { emit } = useActionEmit();

  // 优先使用传入的 specs，否则从 content 编译
  const compiledSpecs = useMemo(() => {
    // 如果 props 传入了 specs，直接使用
    if (propSpecs && propSpecs.length > 0) {
      console.log('[ChatMessage] Using propSpecs:', propSpecs);
      return propSpecs;
    }

    if (isUser || !content) return [];

    // 回退：从 content 编译
    if (isSpecStreamFormat(content)) {
      console.log('[ChatMessage] Detected SpecStream format, compiling...');
      const spec = compileSpecFromStream(content);
      if (spec) {
        const elements = extractRenderableElements(spec);
        console.log('[ChatMessage] Extracted', elements.length, 'elements from content');
        return elements;
      }
    }

    return [];
  }, [content, isUser, propSpecs]);

  useEffect(() => {
    if (!isUser) {
      console.log('[ChatMessage] Rendering:', {
        hasPropSpecs: !!(propSpecs && propSpecs.length > 0),
        isSpecStream: isSpecStreamFormat(content || ''),
        compiledSpecsCount: compiledSpecs.length,
        contentPreview: content?.substring(0, 100),
      });
    }
  }, [content, isUser, compiledSpecs, propSpecs]);

  // 如果有编译出的 specs，渲染组件
  if (compiledSpecs.length > 0) {
    return (
      <div className="flex justify-start">
        <div className="message-bubble assistant-message max-w-full">
          <div className="text-xs text-gray-500 dark:text-gray-400 mb-2">AI 助手</div>
          <div className="space-y-4">
            <JSONUIProvider registry={registry}>
              {compiledSpecs.map((spec, i) => {
                try {
                  console.log('[ChatMessage] Rendering spec:', spec);
                  return <Renderer key={i} registry={registry} spec={spec} state={spec.state} />;
                } catch (e) {
                  console.error('[ChatMessage] Render error:', e);
                  return <div key={i} className="p-2 bg-red-50 rounded text-sm text-red-600">渲染错误: {String(e)}</div>;
                }
              })}
            </JSONUIProvider>
            {isLoading && <span className="inline-block ml-1 animate-pulse">▊</span>}
          </div>
        </div>
      </div>
    );
  }

  // 普通 Markdown 渲染
  return (
    <div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
      <div className={`message-bubble ${isUser ? 'user-message' : 'assistant-message'}`}>
        {!isUser && <div className="text-xs text-gray-500 dark:text-gray-400 mb-1">AI 助手</div>}
        {!isUser ? (
          <div className="prose prose-sm dark:prose-invert max-w-none">
            <ReactMarkdown remarkPlugins={[remarkGfm]} components={{ code: CodeBlock, p: Paragraph }}>
              {content || ''}
            </ReactMarkdown>
            {isLoading && <span className="inline-block ml-1 animate-pulse">▊</span>}
          </div>
        ) : (
          <div className="whitespace-pre-wrap break-words">
            {content || <span className="text-gray-400 italic">暂无内容</span>}
          </div>
        )}
      </div>
    </div>
  );
}
