/**
 * json-render 注册表
 *
 * 创建组件注册表，将 Schema 定义与 React 组件绑定
 * 用于 Renderer 的自动解析和渲染
 */

'use client';

import { useState } from 'react';

// ============ React 组件实现 ============

// Card 组件
const Card = ({ title, children, className, renderChildren, emit }: any) => (
  <div className={`bg-white dark:bg-gray-800 rounded-lg border dark:border-gray-700 shadow-sm p-4 ${className || ''}`}>
    {title && <h3 className="text-lg font-semibold mb-3 text-gray-900 dark:text-white">{title}</h3>}
    {renderChildren ? renderChildren(children, emit) : null}
  </div>
);

// Stack 组件
const Stack = ({ direction = 'column', spacing = 2, align = 'start', children, className, renderChildren, emit }: any) => {
  const directionClass = direction === 'row' ? 'flex-row' : 'flex-col';
  const spacingClass = spacing > 0 ? `gap-${spacing}` : '';
  const alignClass = align === 'center' ? 'items-center' : align === 'end' ? 'items-end' : align === 'stretch' ? 'items-stretch' : 'items-start';

  return (
    <div className={`flex ${directionClass} ${spacingClass} ${alignClass} ${className || ''}`}>
      {renderChildren ? renderChildren(children, emit) : null}
    </div>
  );
};

// Heading 组件
const Heading = ({ level = 'h2', text, className }: any) => {
  const Tag = level;
  const sizeClasses: Record<string, string> = {
    h1: 'text-3xl font-bold',
    h2: 'text-2xl font-semibold',
    h3: 'text-xl font-semibold',
    h4: 'text-lg font-medium',
    h5: 'text-base font-medium',
    h6: 'text-sm font-medium',
  };
  const sizeClass = sizeClasses[level] || sizeClasses.h2;

  return <Tag className={`${sizeClass} text-gray-900 dark:text-white ${className || ''}`}>{text}</Tag>;
};

// Text 组件
const Text = ({ content, variant = 'body', className }: any) => {
  const variantClasses: Record<string, string> = {
    body: 'text-gray-700 dark:text-gray-300',
    muted: 'text-gray-500 dark:text-gray-400',
    code: 'font-mono text-sm bg-gray-100 dark:bg-gray-900 px-1 py-0.5 rounded',
  };
  const variantClass = variantClasses[variant] || variantClasses.body;

  return <p className={`${variantClass} ${className || ''}`}>{content}</p>;
};

// Button 组件 - 支持交互事件
const Button = ({ label, variant = 'default', onClick, action, actionPayload, disabled = false, className, emit }: any) => {
  const variantClasses: Record<string, string> = {
    default: 'bg-gray-200 hover:bg-gray-300 text-gray-800 dark:bg-gray-700 dark:hover:bg-gray-600 dark:text-gray-200',
    primary: 'bg-blue-600 hover:bg-blue-700 text-white',
    secondary: 'bg-purple-600 hover:bg-purple-700 text-white',
    ghost: 'hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300',
    danger: 'bg-red-600 hover:bg-red-700 text-white',
  };
  const variantClass = variantClasses[variant] || variantClasses.default;

  const handleClick = () => {
    if (disabled) return;

    // 优先使用 action 事件（emit）
    if (action && emit) {
      emit(action, actionPayload);
      return;
    }

    // 回退到 onClick 代码执行
    if (onClick) {
      try {
        // 安全执行 onClick 代码
        const fn = new Function('event', onClick);
        fn(new Event('click'));
      } catch (e) {
        console.error('Error executing onClick:', e);
      }
    }
  };

  return (
    <button
      onClick={handleClick}
      disabled={disabled}
      className={`${variantClass} px-4 py-2 rounded-md font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${className || ''}`}
    >
      {label}
    </button>
  );
};

// Input 组件
const Input = ({ placeholder, value, onChange, disabled = false, className, type = 'text' }: any) => {
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (onChange) {
      try {
        const fn = new Function('event', onChange);
        fn(e);
      } catch (err) {
        console.error('Error executing onChange:', err);
      }
    }
  };

  return (
    <input
      type={type}
      placeholder={placeholder}
      defaultValue={value}
      onChange={handleChange}
      disabled={disabled}
      className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:opacity-50 ${className || ''}`}
    />
  );
};

// Badge 组件
const Badge = ({ text, variant = 'default', className }: any) => {
  const variantClasses: Record<string, string> = {
    default: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200',
    success: 'bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-200',
    warning: 'bg-yellow-100 dark:bg-yellow-900/30 text-yellow-800 dark:text-yellow-200',
    error: 'bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-200',
    info: 'bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-200',
  };
  const variantClass = variantClasses[variant] || variantClasses.default;

  return (
    <span className={`inline-flex items-center px-2 py-1 rounded-md text-xs font-medium ${variantClass} ${className || ''}`}>
      {text}
    </span>
  );
};

// Separator 组件
const Separator = ({ orientation = 'horizontal', className }: any) => {
  const orientationClass = orientation === 'horizontal' ? 'h-px w-full' : 'w-px h-full';
  return <div className={`bg-gray-200 dark:bg-gray-700 ${orientationClass} ${className || ''}`} />;
};

// ============ MCP 专用组件实现 ============

// TranslationResult 组件 - 翻译结果展示（支持 emit 事件）
const TranslationResult = ({ translated, termsUsed, className, emit }: any) => {
  const [copied, setCopied] = useState(false);

  const handleCopy = () => {
    // 使用 emit 触发复制事件（如果可用），否则直接调用 clipboard API
    if (emit) {
      emit('copy', { text: translated });
    } else {
      navigator.clipboard.writeText(translated);
    }
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div className={`translation-result bg-white dark:bg-gray-800 rounded-xl shadow-md border border-gray-200 dark:border-gray-700 overflow-hidden ${className || ''}`}>
      {/* 头部 */}
      <div className="bg-gradient-to-r from-blue-500 to-purple-500 px-4 py-3 flex items-center gap-2">
        <span className="text-xl">🌐</span>
        <h4 className="font-semibold text-white">翻译结果</h4>
      </div>

      {/* 内容区域 */}
      <div className="p-4">
        {/* 译文 */}
        <div className="bg-gradient-to-br from-blue-50 to-purple-50 dark:from-blue-900/20 dark:to-purple-900/20 rounded-lg p-3 border border-blue-100 dark:border-blue-800/50 mb-3">
          <div className="flex items-center gap-2 mb-2">
            <span className="text-xs font-medium text-blue-600 dark:text-blue-400 uppercase tracking-wide">译文</span>
          </div>
          <p className="text-gray-900 dark:text-gray-100 font-medium leading-relaxed">{translated}</p>
        </div>

        {/* 使用的术语 */}
        {termsUsed && termsUsed.length > 0 && (
          <div className="bg-gray-50 dark:bg-gray-900/50 rounded-lg p-3">
            <div className="flex items-center gap-2 mb-2">
              <span className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wide">使用术语</span>
            </div>
            <div className="flex flex-wrap gap-2">
              {termsUsed.map((term: string, idx: number) => (
                <span key={idx} className="inline-flex items-center px-2 py-1 rounded-md text-xs font-medium bg-purple-100 dark:bg-purple-900/30 text-purple-800 dark:text-purple-200">
                  {term}
                </span>
              ))}
            </div>
          </div>
        )}
      </div>

      {/* 底部操作栏 */}
      <div className="px-4 py-3 bg-gray-50 dark:bg-gray-900/30 border-t dark:border-gray-700 flex gap-2">
        <button
          onClick={handleCopy}
          className="flex-1 flex items-center justify-center gap-1 px-3 py-2 text-sm bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-lg text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
        >
          <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
          </svg>
          <span>{copied ? '已复制！' : '复制译文'}</span>
        </button>
      </div>
    </div>
  );
};

// NovelList 组件 - 支持点击交互
const NovelList = ({ novels, className, emit }: any) => (
  <div className={`novel-list space-y-3 ${className || ''}`}>
    {novels.map((novel: any) => (
      <div
        key={novel.id}
        onClick={() => emit && emit('selectNovel', { id: novel.id, title: novel.title, ...novel })}
        className="bg-white dark:bg-gray-800 rounded-lg border dark:border-gray-700 p-4 hover:shadow-md hover:border-blue-300 dark:hover:border-blue-600 transition-all cursor-pointer"
      >
        <h4 className="font-semibold text-lg text-gray-900 dark:text-white mb-1">{novel.title}</h4>
        {novel.author && <p className="text-sm text-gray-500 dark:text-gray-400 mb-2">By {novel.author}</p>}
        {novel.description && <p className="text-sm text-gray-600 dark:text-gray-300 mb-2 line-clamp-2">{novel.description}</p>}
        <div className="flex items-center gap-2">
          {novel.chapterCount && <Badge text={`${novel.chapterCount} chapters`} variant="info" />}
          {novel.tags?.map((tag: string) => (
            <Badge key={tag} text={tag} variant="default" />
          ))}
        </div>
      </div>
    ))}
  </div>
);

// ChapterReader 组件
const ChapterReader = ({ novelTitle, chapterTitle, content, chapterNumber, totalChapters, className }: any) => (
  <div className={`chapter-reader bg-white dark:bg-gray-800 rounded-lg border dark:border-gray-700 p-6 ${className || ''}`}>
    <div className="border-b dark:border-gray-700 pb-4 mb-4">
      <p className="text-sm text-gray-500 dark:text-gray-400 mb-1">{novelTitle}</p>
      <h2 className="text-2xl font-bold text-gray-900 dark:text-white">{chapterTitle}</h2>
      {chapterNumber && totalChapters && (
        <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
          Chapter {chapterNumber} of {totalChapters}
        </p>
      )}
    </div>
    <div className="prose dark:prose-invert max-w-none">
      <p className="text-gray-700 dark:text-gray-300 whitespace-pre-wrap leading-relaxed">{content}</p>
    </div>
  </div>
);

// McpToolCall 组件
const McpToolCall = ({ tool, status, args, result, error, className }: any) => {
  const statusConfig: Record<string, { icon: string; color: string; bg: string }> = {
    pending: { icon: '⏳', color: 'text-yellow-600', bg: 'bg-yellow-50 dark:bg-yellow-900/20 border-yellow-300 dark:border-yellow-700' },
    running: { icon: '🔄', color: 'text-blue-600', bg: 'bg-blue-50 dark:bg-blue-900/20 border-blue-300 dark:border-blue-700' },
    success: { icon: '✅', color: 'text-green-600', bg: 'bg-green-50 dark:bg-green-900/20 border-green-300 dark:border-green-700' },
    error: { icon: '❌', color: 'text-red-600', bg: 'bg-red-50 dark:bg-red-900/20 border-red-300 dark:border-red-700' },
  };
  const config = statusConfig[status] || statusConfig.success;

  return (
    <div className={`mcp-tool-call border-l-4 p-3 rounded-r ${config.bg} ${className || ''}`}>
      <div className="flex items-center gap-2 mb-2">
        <span className="text-lg">{config.icon}</span>
        <span className={`font-mono text-sm font-medium ${config.color}`}>{tool}</span>
      </div>
      {args && (
        <div className="mt-2">
          <p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Arguments:</p>
          <pre className="text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded overflow-x-auto">
            {JSON.stringify(args, null, 2)}
          </pre>
        </div>
      )}
      {result && status === 'success' && (
        <div className="mt-2">
          <p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Result:</p>
          <pre className="text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded overflow-x-auto">
            {JSON.stringify(result, null, 2)}
          </pre>
        </div>
      )}
      {error && status === 'error' && (
        <div className="mt-2">
          <p className="text-xs text-red-600 dark:text-red-400 mb-1">Error:</p>
          <p className="text-sm text-red-700 dark:text-red-300">{error}</p>
        </div>
      )}
    </div>
  );
};

// LoginPanel 组件
const LoginPanel = ({ server, email, className }: any) => (
  <div className={`login-panel bg-white dark:bg-gray-800 rounded-lg border dark:border-gray-700 p-6 ${className || ''}`}>
    <div className="text-center mb-6">
      <div className="text-4xl mb-2">🔐</div>
      <h3 className="text-xl font-semibold text-gray-900 dark:text-white">{server}</h3>
      <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">Sign in to continue</p>
    </div>
    <form className="space-y-4">
      <div>
        <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Email</label>
        <Input type="email" placeholder="your@email.com" defaultValue={email} />
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Password</label>
        <Input type="password" placeholder="••••••••" />
      </div>
      <Button label="Sign In" variant="primary" className="w-full" />
    </form>
  </div>
);

// CodeBlock 组件
const CodeBlock = ({ code, language = 'text', inline = false, className }: any) => {
  if (inline) {
    return (
      <code className={`bg-gray-100 dark:bg-gray-900 px-1.5 py-0.5 rounded text-sm font-mono text-gray-800 dark:text-gray-200 ${className || ''}`}>
        {code}
      </code>
    );
  }

  return (
    <div className={`code-block bg-gray-900 dark:bg-gray-950 rounded-lg p-4 overflow-x-auto ${className || ''}`}>
      <div className="flex items-center justify-between mb-2">
        <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 transition-colors"
        >
          Copy
        </button>
      </div>
      <pre className="text-sm text-gray-100 font-mono">
        <code>{code}</code>
      </pre>
    </div>
  );
};

// DataTable 组件
const DataTable = ({ columns, rows, className }: any) => (
  <div className={`data-table overflow-x-auto ${className || ''}`}>
    <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
      <thead className="bg-gray-50 dark:bg-gray-800">
        <tr>
          {columns.map((col: any) => (
            <th key={col.key} className="px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
              {col.label}
            </th>
          ))}
        </tr>
      </thead>
      <tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
        {rows.map((row: any, idx: number) => (
          <tr key={idx} className="hover:bg-gray-50 dark:hover:bg-gray-800">
            {columns.map((col: any) => (
              <td key={col.key} className="px-4 py-3 text-sm text-gray-700 dark:text-gray-300">
                {String(row[col.key] ?? '')}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  </div>
);

// NovelDetail 组件 - 小说详情卡片
const NovelDetail = ({ novel, className, emit }: any) => {
  if (!novel) return null;

  return (
    <div className={`novel-detail bg-white dark:bg-gray-800 rounded-xl shadow-md border border-gray-200 dark:border-gray-700 overflow-hidden ${className || ''}`}>
      {/* 头部 - 渐变背景 */}
      <div className="bg-gradient-to-r from-purple-500 to-pink-500 px-4 py-4">
        <h3 className="font-bold text-white text-xl">{novel.title || '未知标题'}</h3>
        {novel.isVip && (
          <span className="inline-block mt-1 px-2 py-0.5 bg-yellow-400 text-yellow-900 text-xs rounded-full font-medium">
            👑 VIP
          </span>
        )}
      </div>

      {/* 内容区域 */}
      <div className="p-4 space-y-4">
        {/* 基本信息 */}
        <div>
          <h4 className="font-semibold text-gray-900 dark:text-gray-100 mb-2 flex items-center gap-1">
            <span>📖</span> 基本信息
          </h4>
          <div className="space-y-1 text-sm text-gray-700 dark:text-gray-300">
            <p><span className="text-gray-500">作者：</span>{novel.author || '-'}</p>
            <p><span className="text-gray-500">类型：</span>{novel.category || '-'}</p>
            <p><span className="text-gray-500">简介：</span>{novel.description || '暂无简介'}</p>
          </div>
        </div>

        {/* 统计数据 */}
        <div>
          <h4 className="font-semibold text-gray-900 dark:text-gray-100 mb-2 flex items-center gap-1">
            <span>📊</span> 统计数据
          </h4>
          <div className="grid grid-cols-2 gap-2">
            <div className="bg-gray-50 dark:bg-gray-900/50 p-2 rounded-lg">
              <span className="text-xs text-gray-500">状态</span>
              <p className="font-medium text-sm">{novel.status || '-'}</p>
            </div>
            <div className="bg-gray-50 dark:bg-gray-900/50 p-2 rounded-lg">
              <span className="text-xs text-gray-500">章节数</span>
              <p className="font-medium text-sm">{novel.chapterCount ?? '-'}章</p>
            </div>
            <div className="bg-gray-50 dark:bg-gray-900/50 p-2 rounded-lg">
              <span className="text-xs text-gray-500">总字数</span>
              <p className="font-medium text-sm">{novel.wordCount ?? '-'}字</p>
            </div>
            <div className="bg-gray-50 dark:bg-gray-900/50 p-2 rounded-lg">
              <span className="text-xs text-gray-500">阅读量</span>
              <p className="font-medium text-sm">{novel.viewCount ?? '-'}次</p>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

// SuggestionButtons 组件 - 建议操作按钮组
const SuggestionButtons = ({ suggestions, className, emit }: any) => {
  if (!suggestions || !Array.isArray(suggestions) || suggestions.length === 0) return null;

  return (
    <div className={`suggestion-buttons flex flex-wrap gap-2 ${className || ''}`}>
      {suggestions.map((suggestion: any, index: number) => {
        const handleClick = () => {
          if (emit && suggestion.message) {
            emit('sendMessage', { message: suggestion.message });
          }
        };

        return (
          <button
            key={index}
            onClick={handleClick}
            className="px-4 py-2 bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-lg hover:bg-blue-200 dark:hover:bg-blue-900/50 transition-colors text-sm font-medium cursor-pointer"
          >
            {suggestion.icon && <span className="mr-1">{suggestion.icon}</span>}
            {suggestion.label || suggestion.message}
          </button>
        );
      })}
    </div>
  );
};

// ============ 创建注册表 ============

// 简化的组件注册表 - 直接映射组件名称到 React 组件
export const jsonRenderRegistry: Record<string, React.ComponentType<any>> = {
  // 基础组件
  card: Card,
  stack: Stack,
  heading: Heading,
  text: Text,
  button: Button,
  input: Input,
  badge: Badge,
  separator: Separator,

  // MCP 专用组件
  'translation-result': TranslationResult,
  'novel-list': NovelList,
  'novel-detail': NovelDetail,
  'chapter-reader': ChapterReader,
  'mcp-tool-call': McpToolCall,
  'login-panel': LoginPanel,
  'code-block': CodeBlock,
  'data-table': DataTable,
  'suggestion-buttons': SuggestionButtons,
};

// ============ 辅助函数 ============

/**
 * 递归渲染子组件
 * 用于 Card 和 Stack 组件中渲染 children 数组
 * @param children - 子组件数组
 * @param emit - ActionContext emit 函数（用于组件交互）
 */
export function renderChildren(children: any, emit?: (eventName: string, payload?: any) => void): React.ReactNode {
  if (!children) return null;
  if (!Array.isArray(children)) return null;

  return children.map((child: any, idx: number) => {
    if (!child || typeof child !== 'object') return null;
    if (!child.type) return <span key={idx}>{String(child)}</span>;

    const componentType = child.type;
    const Component = (jsonRenderRegistry as any)[componentType];

    if (Component) {
      // 合并 props：原始 child props + emit 函数
      const props: any = { ...child };
      if (emit) {
        props.emit = emit;
      }

      // 如果组件需要渲染子组件，传入 renderChildren 函数（并传递 emit）
      if (componentType === 'card' || componentType === 'stack') {
        props.renderChildren = (grandchildren: any) => renderChildren(grandchildren, emit);
      }

      return <Component key={idx} {...props} />;
    }

    return (
      <div key={idx} className="p-2 bg-yellow-50 dark:bg-yellow-900/20 rounded border border-yellow-200 dark:border-yellow-800">
        <p className="text-sm text-yellow-700 dark:text-yellow-300">Unknown component: {componentType}</p>
      </div>
    );
  });
}

// 导出类型
export type { ComponentSpec } from './json-render-catalog';
