/**
 * JsonRenderer - 使用官方 @json-render/react API 的渲染器
 *
 * 功能：
 * - 使用官方 Renderer 组件渲染 json-render spec
 * - 支持单个 spec 和 specs 数组
 * - 支持流式渲染（SSE）
 * - 兼容旧格式的 ComponentSpec
 *
 * 使用方式：
 * ```tsx
 * // 渲染单个 spec（旧格式）
 * <JsonRenderer spec={{ type: 'card', title: 'Hello' }} />
 *
 * // 渲染多个 specs（旧格式）
 * <JsonRenderer specs={[spec1, spec2]} />
 *
 * // 渲染官方格式 spec
 * <JsonRenderer spec={officialSpec} />
 * ```
 */

'use client';

import { useMemo } from 'react';
import {
  Renderer,
  JSONUIProvider,
  type Spec,
} from '@json-render/react';
import type { UIElement } from '@json-render/core';
import { registry } from '@/lib/registry';

// ============ Types ============

/**
 * 旧格式组件 spec 类型
 * 旧格式: { type: 'card', title: '...', children: [...] }
 */
export interface LegacyComponentSpec {
  type: string;
  children?: LegacyComponentSpec[];
  [key: string]: unknown;
}

/**
 * JsonRenderer Props
 */
export interface JsonRendererProps {
  /** 单个组件 spec（支持旧格式和官方格式） */
  spec?: LegacyComponentSpec | Spec | null;
  /** 多个组件 spec 数组 */
  specs?: LegacyComponentSpec[] | Spec[];
  /** 可选样式类 */
  className?: string;
  /** 事件处理函数 */
  onAction?: (actionName: string, params?: Record<string, unknown>) => void;
  /** 是否正在加载 */
  loading?: boolean;
}

/**
 * StreamingJsonRenderer Props - 用于 SSE 流式渲染
 */
export interface StreamingJsonRendererProps extends JsonRendererProps {
  /** 流式数据 */
  specs?: LegacyComponentSpec[];
}

// ============ Helper Functions ============

/**
 * 生成唯一 key
 */
let keyCounter = 0;
function generateKey(): string {
  return `el_${++keyCounter}`;
}

/**
 * 将旧的嵌套格式 ComponentSpec 转换为扁平化的官方 Spec 格式
 *
 * 旧格式: { type: 'card', title: '...', children: [...] }
 * 新格式: { root: 'card1', elements: { 'card1': { type: 'card', props: { title: '...' }, children: ['text1'] } } }
 */
function convertLegacyToSpec(
  legacySpec: LegacyComponentSpec,
  elements: Record<string, UIElement> = {},
  parentKey?: string
): string {
  const { type, children, ...restProps } = legacySpec;
  const key = generateKey();

  // 转换 children（递归）
  let childKeys: string[] | undefined;
  if (children && Array.isArray(children) && children.length > 0) {
    childKeys = children.map((child) =>
      convertLegacyToSpec(child, elements, key)
    );
  }

  // 创建 UIElement
  const element: UIElement = {
    type,
    props: restProps,
  };

  if (childKeys && childKeys.length > 0) {
    element.children = childKeys;
  }

  elements[key] = element;
  return key;
}

/**
 * 检查是否是官方 Spec 格式
 */
function isOfficialSpec(spec: unknown): spec is Spec {
  if (!spec || typeof spec !== 'object') return false;
  const s = spec as Record<string, unknown>;
  return typeof s.root === 'string' && typeof s.elements === 'object';
}

/**
 * 检查是否是旧格式 ComponentSpec
 */
function isLegacySpec(spec: unknown): spec is LegacyComponentSpec {
  if (!spec || typeof spec !== 'object') return false;
  const s = spec as Record<string, unknown>;
  return typeof s.type === 'string' && !('root' in s) && !('elements' in s);
}

/**
 * 将任何格式的 spec 转换为官方 Spec 格式
 */
function normalizeSpec(spec: LegacyComponentSpec | Spec | null | undefined): Spec | null {
  if (!spec) return null;

  // 已经是官方格式
  if (isOfficialSpec(spec)) {
    return spec;
  }

  // 旧格式，需要转换
  if (isLegacySpec(spec)) {
    const elements: Record<string, UIElement> = {};
    const root = convertLegacyToSpec(spec, elements);

    if (Object.keys(elements).length === 0) {
      return null;
    }

    return { root, elements };
  }

  return null;
}

/**
 * 将多个 spec 转换为容器 spec
 */
function wrapSpecsInContainer(specs: (LegacyComponentSpec | Spec)[]): Spec | null {
  if (!specs || specs.length === 0) return null;

  // 过滤有效的 specs
  const validSpecs = specs.filter(Boolean);
  if (validSpecs.length === 0) return null;

  // 如果只有一个 spec，直接转换
  if (validSpecs.length === 1) {
    return normalizeSpec(validSpecs[0]);
  }

  // 多个 specs，包装在 stack 容器中
  const elements: Record<string, UIElement> = {};
  keyCounter = 0; // 重置计数器

  const childKeys = validSpecs.map((spec) => {
    if (isOfficialSpec(spec)) {
      // 官方格式，合并 elements
      Object.assign(elements, spec.elements);
      return spec.root;
    }
    // 旧格式，转换
    return convertLegacyToSpec(spec as LegacyComponentSpec, elements);
  });

  // 创建 stack 容器
  const stackKey = generateKey();
  elements[stackKey] = {
    type: 'stack',
    props: {
      direction: 'column',
      spacing: 2,
    },
    children: childKeys,
  };

  return { root: stackKey, elements };
}

// ============ Components ============

/**
 * 基础 JsonRenderer 组件
 *
 * 使用官方 @json-render/react Renderer 渲染组件
 */
export function JsonRenderer({
  spec,
  specs,
  className,
  onAction,
  loading,
}: JsonRendererProps) {
  // 转换 spec 格式
  const finalSpec = useMemo(() => {
    if (specs && specs.length > 0) {
      return wrapSpecsInContainer(specs);
    }
    if (spec) {
      return normalizeSpec(spec);
    }
    return null;
  }, [spec, specs]);

  // 创建 action handlers
  const handlers = useMemo(() => {
    const baseHandlers: Record<string, (params?: Record<string, unknown>) => Promise<void> | void> = {
      sendMessage: async (params?: Record<string, unknown>) => {
        onAction?.('sendMessage', params);
      },
      selectNovel: async (params?: Record<string, unknown>) => {
        onAction?.('selectNovel', params);
      },
      copy: async (params?: Record<string, unknown>) => {
        onAction?.('copy', params);
        // 如果有 text 参数，直接复制到剪贴板
        if (params?.text && typeof params.text === 'string') {
          try {
            await navigator.clipboard.writeText(params.text);
          } catch (e) {
            console.error('Failed to copy to clipboard:', e);
          }
        }
      },
    };
    return baseHandlers;
  }, [onAction]);

  if (!finalSpec) {
    return null;
  }

  return (
    <div className={className}>
      <JSONUIProvider
        registry={registry}
        handlers={handlers}
      >
        <Renderer
          spec={finalSpec}
          registry={registry}
          loading={loading}
        />
      </JSONUIProvider>
    </div>
  );
}

/**
 * 流式 JsonRenderer 组件
 *
 * 用于 SSE 流式渲染，支持动态更新 specs
 */
export function StreamingJsonRenderer({
  specs,
  className,
  onAction,
  loading,
}: StreamingJsonRendererProps) {
  // 转换 specs 格式
  const finalSpec = useMemo(() => {
    if (!specs || specs.length === 0) return null;
    return wrapSpecsInContainer(specs);
  }, [specs]);

  // 创建 action handlers
  const handlers = useMemo(() => {
    const baseHandlers: Record<string, (params?: Record<string, unknown>) => Promise<void> | void> = {
      sendMessage: async (params?: Record<string, unknown>) => {
        onAction?.('sendMessage', params);
      },
      selectNovel: async (params?: Record<string, unknown>) => {
        onAction?.('selectNovel', params);
      },
      copy: async (params?: Record<string, unknown>) => {
        onAction?.('copy', params);
        if (params?.text && typeof params.text === 'string') {
          try {
            await navigator.clipboard.writeText(params.text);
          } catch (e) {
            console.error('Failed to copy to clipboard:', e);
          }
        }
      },
    };
    return baseHandlers;
  }, [onAction]);

  if (!finalSpec) {
    return null;
  }

  return (
    <div className={className}>
      <JSONUIProvider
        registry={registry}
        handlers={handlers}
      >
        <Renderer
          spec={finalSpec}
          registry={registry}
          loading={loading}
        />
      </JSONUIProvider>
    </div>
  );
}

// ============ Default Export ============

/**
 * 默认导出 - 基础 JsonRenderer
 *
 * 支持单个 spec 或 specs 数组
 */
export default JsonRenderer;

// ============ Additional Exports ============

// 导出类型
export type { Spec, StateModel } from '@json-render/react';
export type { UIElement } from '@json-render/core';
// 兼容旧类型
export type ComponentSpec = LegacyComponentSpec;
