/**
 * BlockCanvas.tsx - 块画布组件
 * 
 * 渲染所有的文档块,管理块的排序和交互
 * 支持在标题上方显示TOC占位符
 * 
 * @module components/Editor
 */

import React from 'react';
import type { DocumentBlock } from '../../types/editor';
import { BlockRenderer } from './BlockRenderer';
import { TOCPlaceholder } from './blocks/TOCPlaceholder';
import { getHeadingNumberMap } from '../../utils/headingNumbering';
import { formatOrderedListMarker, getOrderedListNumberMap } from '../../utils/listNumbering';
import './BlockCanvas.css';

// ══════════════════════════════════════════════════════════════════════════════
// Component Props
// ══════════════════════════════════════════════════════════════════════════════

export interface BlockCanvasProps {
  /** 文档块数组 */
  blocks: DocumentBlock[];
  /** 是否只读 */
  readOnly?: boolean;
}

// ══════════════════════════════════════════════════════════════════════════════
// Component
// ══════════════════════════════════════════════════════════════════════════════

/**
 * BlockCanvas - 块画布
 * 
 * 在第一个标题块上方显示TOC占位符(如果当前没有TOC块)
 * 在每个标题块上方显示TOC占位符(如果当前没有TOC块)
 */
export const BlockCanvas = React.memo(function BlockCanvas({
  blocks,
  readOnly = false,
}: BlockCanvasProps) {
  const [collapsedHeadingIds, setCollapsedHeadingIds] = React.useState<Set<string>>(new Set());
  const { sortedBlocks, hasTOC, firstHeadingIndex, headingNumbers, orderedListNumbers, collapsibleHeadingIds } = React.useMemo(() => {
    const sorted = [...blocks].sort((a, b) => a.block_order - b.block_order);
    let tocFound = false;
    let headingIndex = -1;

    sorted.forEach((block, index) => {
      if (block.type === 'toc') tocFound = true;
      if (headingIndex === -1 && block.type === 'heading') {
        headingIndex = index;
      }
    });

    const collapsible = new Set<string>();
    sorted.forEach((block, index) => {
      if (block.type !== 'heading') return;

      const nextBlock = sorted[index + 1];
      if (
        nextBlock &&
        (nextBlock.type !== 'heading' || nextBlock.level > block.level)
      ) {
        collapsible.add(block.id);
      }
    });

    return {
      sortedBlocks: sorted,
      hasTOC: tocFound,
      headingNumbers: getHeadingNumberMap(sorted),
      firstHeadingIndex: headingIndex,
      orderedListNumbers: getOrderedListNumberMap(sorted),
      collapsibleHeadingIds: collapsible,
    };
  }, [blocks]);

  const visibleBlocks = React.useMemo(() => {
    const hiddenByLevel: number[] = [];
    return sortedBlocks.filter((block) => {
      if (block.type === 'heading') {
        while (hiddenByLevel.length > 0 && hiddenByLevel[hiddenByLevel.length - 1] >= block.level) {
          hiddenByLevel.pop();
        }
        const isHidden = hiddenByLevel.length > 0;
        if (collapsedHeadingIds.has(block.id)) hiddenByLevel.push(block.level);
        return !isHidden;
      }
      return hiddenByLevel.length === 0;
    });
  }, [sortedBlocks, collapsedHeadingIds]);

  const toggleHeadingCollapse = React.useCallback((headingId: string) => {
    setCollapsedHeadingIds((current) => {
      const next = new Set(current);
      if (next.has(headingId)) next.delete(headingId);
      else next.add(headingId);
      return next;
    });
  }, []);

  // 空状态
  if (visibleBlocks.length === 0) {
    return (
      <div className="block-canvas-empty">
        <p>文档为空,点击工具栏添加内容</p>
      </div>
    );
  }

  return (
    <div className="block-canvas" data-testid="block-canvas">
      {visibleBlocks.map((block, index) => {
        const prevBlock = index > 0 ? visibleBlocks[index - 1] : null;
        
        // 在标题上方显示TOC占位符的条件:
        // 1. 当前文档没有TOC块
        // 2. 当前块是标题块
        // 3. 不是只读模式
        const showPlaceholderBefore =
          !hasTOC && index === firstHeadingIndex && !readOnly;
        
        return (
          <React.Fragment key={block.id}>
            {/* 在标题上方显示TOC占位符 */}
            {showPlaceholderBefore && (
              <TOCPlaceholder 
                afterBlockId={prevBlock?.id}
                readOnly={readOnly}
              />
            )}
            
            {/* 渲染当前块 */}
            <BlockRenderer
              block={block}
              index={index}
              blockCount={visibleBlocks.length}
              listMarker={block.type === 'heading'
                ? block.metadata.list_type === 'ordered'
                  ? `${headingNumbers.get(block.id) ?? '1'}.`
                  : block.metadata.list_type === 'unordered'
                    ? '•'
                    : undefined
                : block.type === 'paragraph'
                  ? block.metadata.list_type === 'ordered'
                  ? formatOrderedListMarker(
                    orderedListNumbers.get(block.id) ?? 1,
                    block.metadata.list_level ?? 0,
                  )
                  : block.metadata.list_type === 'unordered'
                    ? '•'
                    : undefined
                  : undefined
                }
              collapsible={block.type === 'heading' && collapsibleHeadingIds.has(block.id)}
              collapsed={block.type === 'heading' && collapsedHeadingIds.has(block.id)}
              onToggleCollapse={block.type === 'heading'
                ? toggleHeadingCollapse
                : undefined}
              readOnly={readOnly}
            />
          </React.Fragment>
        );
      })}
    </div>
  );
});

export default BlockCanvas;
