import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import '../widgets/layout/app_layout.dart';
import '../widgets/common/app_button.dart';
import '../widgets/common/app_card.dart';
import '../providers/document_provider.dart';
import '../providers/element_provider.dart';
import '../models/element.dart';
import '../models/graph.dart';
import '../services/mock_data_service.dart';
import '../utils/constants.dart';
import '../theme/app_colors.dart';

/// 人工牵引页
class TractionPage extends StatefulWidget {
  final String documentId;

  const TractionPage({Key? key, required this.documentId}) : super(key: key);

  @override
  State<TractionPage> createState() => _TractionPageState();
}

class _TractionPageState extends State<TractionPage> {
  ElementType? _filterType;
  List<GraphNode> _graphNodes = [];
  List<GraphEdge> _graphEdges = [];
  bool _showSelectedOnly = false;

  @override
  void initState() {
    super.initState();
    _graphNodes = MockDataService.getMockGraphNodes();
    _graphEdges = MockDataService.getMockGraphEdges();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer2<DocumentProvider, ElementProvider>(
      builder: (context, docProvider, elementProvider, child) {
        final document = docProvider.getDocumentById(widget.documentId);
        final parsedText = document?.parsedText ?? _getMockText();
        final elements = elementProvider.filteredElements;

        return AppLayout(
          maxContentWidth: 1920,
          contentPadding: const EdgeInsets.symmetric(horizontal: 32, vertical: 32),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const SizedBox(height: 24),
              // 标题栏
              _buildHeader(context, document),
              const SizedBox(height: 32),
              // 三栏布局
              _buildThreeColumnLayout(context, parsedText, elements),
            ],
          ),
        );
      },
    );
  }

  Widget _buildHeader(BuildContext context, document) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: AppColors.border),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.04),
            blurRadius: 12,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Row(
        children: [
          IconButton(
            icon: const Icon(Icons.arrow_back),
            onPressed: () => context.pop(),
            style: IconButton.styleFrom(
              backgroundColor: AppColors.backgroundLight,
              padding: const EdgeInsets.all(12),
            ),
          ),
          const SizedBox(width: 16),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Container(
                      padding: const EdgeInsets.all(8),
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          colors: [AppColors.primary, AppColors.primaryLight],
                        ),
                        borderRadius: BorderRadius.circular(8),
                      ),
                      child: const Icon(
                        LucideIcons.git_branch,
                        color: Colors.white,
                        size: 18,
                      ),
                    ),
                    const SizedBox(width: 12),
                    const Text(
                      '人工牵引',
                      style: TextStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.bold,
                        color: AppColors.textPrimary,
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                Text(
                  '从文档标记 → 标签池 → 拖拽构建逻辑',
                  style: TextStyle(
                    fontSize: 14,
                    color: AppColors.textSecondary,
                  ),
                ),
              ],
            ),
          ),
          AppButton(
            text: '保存',
            type: ButtonType.secondary,
            size: ButtonSize.small,
            icon: LucideIcons.save,
            onPressed: () {},
          ),
        ],
      ),
    );
  }

  Widget _buildThreeColumnLayout(
    BuildContext context,
    String text,
    List<DocumentElement> elements,
  ) {
    final screenWidth = MediaQuery.of(context).size.width;
    final isWide = screenWidth > AppConstants.desktopBreakpoint;
    final veryWide = screenWidth > 1920;

    final elementPanelWidth = veryWide ? 540.0 : 310.0;
    final relationPanelWidth = veryWide ? 560.0 : 400.0;

    final content = isWide
        ? Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // 左侧：要素池
              SizedBox(
                width: elementPanelWidth,
                child: _buildElementPool(context, elements),
              ),
              SizedBox(width: veryWide ? 28 : 24),
              // 中间：主文档区
              Expanded(
                flex: 3,
                child: _buildDocumentView(context, text, elements),
              ),
              SizedBox(width: veryWide ? 28 : 24),
              // 右侧：关系构建区
              SizedBox(
                width: relationPanelWidth,
                child: _buildRelationshipBuilder(context),
              ),
            ],
          )
        : Column(
            children: [
              _buildDocumentView(context, text, elements),
              const SizedBox(height: 20),
              _buildRelationshipBuilder(context),
            ],
          );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // _buildActionBar(context),
        // const SizedBox(height: 20),
        content,
      ],
    );
  }

  Widget _buildActionBar(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(18),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: AppColors.border),
        boxShadow: [
          BoxShadow(
            color: Colors.black.withOpacity(0.02),
            blurRadius: 12,
            offset: const Offset(0, 4),
          ),
        ],
      ),
      child: Wrap(
        spacing: 16,
        runSpacing: 12,
        crossAxisAlignment: WrapCrossAlignment.center,
        children: [
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                padding: const EdgeInsets.all(10),
                decoration: BoxDecoration(
                  color: AppColors.primary.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(10),
                ),
                child: const Icon(
                  LucideIcons.sparkles,
                  color: AppColors.primary,
                  size: 18,
                ),
              ),
              const SizedBox(width: 12),
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '人工牵引操作台',
                    style: Theme.of(context).textTheme.titleMedium?.copyWith(
                          fontWeight: FontWeight.w600,
                          color: AppColors.textPrimary,
                        ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    '拖拽左侧要素到右侧画布，构建规则逻辑网络',
                    style: Theme.of(context).textTheme.bodySmall?.copyWith(
                          color: AppColors.textSecondary,
                        ),
                  ),
                ],
              ),
            ],
          ),
          const SizedBox(width: 12),
          AppButton(
            text: '自动布局',
            type: ButtonType.secondary,
            size: ButtonSize.small,
            icon: LucideIcons.layout_panel_left,
            onPressed: _autoLayoutGraph,
          ),
          AppButton(
            text: '对齐网格',
            type: ButtonType.secondary,
            size: ButtonSize.small,
            icon: LucideIcons.grid_3x3,
            onPressed: _alignNodesToGrid,
          ),
          AppButton(
            text: '导出节点',
            type: ButtonType.secondary,
            size: ButtonSize.small,
            icon: LucideIcons.download,
            onPressed: () {},
          ),
        ],
      ),
    );
  }

  void _autoLayoutGraph() {
    if (_graphNodes.isEmpty) return;
    const double horizontalGap = 240;
    const double verticalGap = 160;
    const double startX = 80;
    const double startY = 80;
    const int columns = 2;

    setState(() {
      for (int index = 0; index < _graphNodes.length; index++) {
        final node = _graphNodes[index];
        final col = index % columns;
        final row = index ~/ columns;
        final newPosition = Offset(
          startX + col * horizontalGap,
          startY + row * verticalGap,
        );
        _graphNodes[index] = node.copyWith(position: newPosition);
      }
    });
  }

  void _alignNodesToGrid() {
    if (_graphNodes.isEmpty) return;
    const double gridSize = 40;

    setState(() {
      for (int index = 0; index < _graphNodes.length; index++) {
        final node = _graphNodes[index];
        final alignedX = (node.position.dx / gridSize).roundToDouble() * gridSize;
        final alignedY = (node.position.dy / gridSize).roundToDouble() * gridSize;
        _graphNodes[index] = node.copyWith(position: Offset(alignedX, alignedY));
      }
    });
  }

  Widget _buildElementPool(BuildContext context, List<DocumentElement> elements) {
    final theme = Theme.of(context);
    final elementProvider = Provider.of<ElementProvider>(context);
    final allElements = elementProvider.elements;
    final selectedElements = elementProvider.selectedElements;

    final displayElements = _showSelectedOnly ? elements.where((e) => selectedElements.contains(e)).toList() : elements;

    final typeCounts = <ElementType, int>{
      for (final type in ElementType.values) type: allElements.where((e) => e.type == type).length,
    };

    final groupedElements = <ElementType, List<DocumentElement>>{};
    for (final type in ElementType.values) {
      final group = displayElements.where((element) => element.type == type).toList();
      if (group.isNotEmpty) {
        groupedElements[type] = group;
      }
    }

    return AppCard(
      title: Row(
        children: [
          const Icon(LucideIcons.tags, size: 18),
          const SizedBox(width: 8),
          const Text('要素池'),
          const Spacer(),
          Container(
            padding: const EdgeInsets.all(4),
            decoration: BoxDecoration(
              color: AppColors.primary.withOpacity(0.1),
              borderRadius: BorderRadius.circular(6),
            ),
            child: Text(
              '${elements.length}',
              style: TextStyle(
                fontSize: 11,
                fontWeight: FontWeight.bold,
                color: AppColors.primary,
              ),
            ),
          ),
        ],
      ),
      child: Container(
        padding: const EdgeInsets.all(15),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min,
          children: [
            // 搜索与筛选
            Row(
              children: [
                Expanded(
                  child: TextField(
                    decoration: InputDecoration(
                      hintText: '搜索要素或关键词...',
                      prefixIcon: const Icon(LucideIcons.search, size: 18),
                      isDense: true,
                      contentPadding: const EdgeInsets.symmetric(
                        horizontal: 14,
                        vertical: 12,
                      ),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(10),
                        borderSide: const BorderSide(color: AppColors.border),
                      ),
                      enabledBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(10),
                        borderSide: const BorderSide(color: AppColors.border),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(10),
                        borderSide: const BorderSide(
                          color: AppColors.primary,
                          width: 2,
                        ),
                      ),
                    ),
                    onChanged: (value) {
                      Provider.of<ElementProvider>(context, listen: false).setSearchQuery(value);
                    },
                  ),
                ),
                const SizedBox(width: 12),
                Tooltip(
                  message: '只查看已选择的要素',
                  child: InkWell(
                    onTap: () {
                      setState(() {
                        _showSelectedOnly = !_showSelectedOnly;
                      });
                    },
                    borderRadius: BorderRadius.circular(12),
                    child: Container(
                      padding: const EdgeInsets.symmetric(
                        horizontal: 12,
                        vertical: 10,
                      ),
                      decoration: BoxDecoration(
                        color: _showSelectedOnly ? AppColors.primary.withOpacity(0.15) : AppColors.borderLight,
                        borderRadius: BorderRadius.circular(12),
                        border: Border.all(
                          color: _showSelectedOnly ? AppColors.primary : AppColors.borderLight,
                        ),
                      ),
                      child: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          Icon(
                            LucideIcons.circle_check,
                            size: 16,
                            color: _showSelectedOnly ? AppColors.primary : AppColors.textSecondary,
                          ),
                          const SizedBox(width: 6),
                          Text(
                            '仅已选',
                            style: theme.textTheme.bodySmall?.copyWith(
                              color: _showSelectedOnly ? AppColors.primary : AppColors.textSecondary,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 16),
            // 类型筛选
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                _buildFilterChip('全部', null, count: allElements.length),
                _buildFilterChip('金额', ElementType.amount, count: typeCounts[ElementType.amount] ?? 0),
                _buildFilterChip('公司', ElementType.company, count: typeCounts[ElementType.company] ?? 0),
                _buildFilterChip('人名', ElementType.person, count: typeCounts[ElementType.person] ?? 0),
                _buildFilterChip('地名', ElementType.location, count: typeCounts[ElementType.location] ?? 0),
                _buildFilterChip('日期', ElementType.date, count: typeCounts[ElementType.date] ?? 0),
                _buildFilterChip('其他', ElementType.other, count: typeCounts[ElementType.other] ?? 0),
              ],
            ),
            const SizedBox(height: 20),
            // 要素列表
            SizedBox(
              height: 340,
              child: displayElements.isEmpty
                  ? _buildEmptyElementState()
                  : ListView(
                      padding: EdgeInsets.zero,
                      children: groupedElements.entries
                          .map(
                            (entry) => _buildElementGroupSection(
                              entry.key,
                              entry.value,
                              selectedElements,
                            ),
                          )
                          .toList(),
                    ),
            ),
            const SizedBox(height: 16),
            AppButton(
              text: '添加要素',
              type: ButtonType.primary,
              size: ButtonSize.small,
              icon: LucideIcons.plus,
              fullWidth: true,
              onPressed: () {},
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFilterChip(String label, ElementType? type, {int? count}) {
    final isSelected = _filterType == type;
    final displayLabel = count != null ? '$label · $count' : label;
    return FilterChip(
      label: Text(displayLabel),
      selected: isSelected,
      onSelected: (selected) {
        setState(() {
          _filterType = selected ? type : null;
        });
        Provider.of<ElementProvider>(context, listen: false).setFilterType(_filterType);
      },
      selectedColor: AppColors.primary.withOpacity(0.2),
      checkmarkColor: AppColors.primary,
      labelStyle: TextStyle(
        fontSize: 10,
        fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
        color: isSelected ? AppColors.primary : AppColors.textSecondary,
      ),
    );
  }

  Widget _buildDraggableElement(DocumentElement element, List<DocumentElement> selectedElements) {
    final elementProvider = Provider.of<ElementProvider>(context, listen: false);
    final isSelected = selectedElements.contains(element);
    final color = _getElementColor(element.type);

    return LongPressDraggable<DocumentElement>(
      data: element,
      onDragStarted: () {
        if (!isSelected) {
          elementProvider.selectElement(element);
        }
      },
      feedback: Material(
        color: Colors.transparent,
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 260),
          child: _buildElementTile(
            context,
            element,
            color,
            true,
            isFeedback: true,
          ),
        ),
      ),
      childWhenDragging: Opacity(
        opacity: 0.4,
        child: _buildElementTile(context, element, color, isSelected),
      ),
      child: GestureDetector(
        onTap: () {
          if (isSelected) {
            elementProvider.deselectElement(element);
          } else {
            elementProvider.selectElement(element);
          }
        },
        child: _buildElementTile(context, element, color, isSelected),
      ),
    );
  }

  Widget _buildElementTile(
    BuildContext context,
    DocumentElement element,
    Color color,
    bool isSelected, {
    bool isFeedback = false,
  }) {
    final theme = Theme.of(context);

    return Container(
      margin: const EdgeInsets.only(bottom: 10),
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        color: isSelected ? color.withOpacity(0.12) : AppColors.backgroundLight,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(
          color: isSelected ? color : AppColors.borderLight,
          width: isSelected ? 1.5 : 1,
        ),
        boxShadow: [
          if (isSelected)
            BoxShadow(
              color: color.withOpacity(0.2),
              blurRadius: 12,
              offset: const Offset(0, 4),
            ),
          if (isFeedback)
            BoxShadow(
              color: Colors.black.withOpacity(0.15),
              blurRadius: 16,
              offset: const Offset(0, 6),
            ),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
                decoration: BoxDecoration(
                  color: color.withOpacity(0.16),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Text(
                  element.type.label,
                  style: theme.textTheme.bodySmall?.copyWith(
                    color: color,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: Text(
                  element.label,
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: theme.textTheme.titleSmall?.copyWith(
                    fontWeight: FontWeight.w600,
                    color: AppColors.textPrimary,
                  ),
                ),
              ),
              const SizedBox(width: 6),
              Icon(
                LucideIcons.grip_vertical,
                size: 16,
                color: AppColors.textSecondary,
              ),
            ],
          ),
          const SizedBox(height: 10),
          Text(
            element.value,
            maxLines: 3,
            overflow: TextOverflow.ellipsis,
            style: theme.textTheme.bodyMedium?.copyWith(
              color: AppColors.textPrimary,
              height: 1.5,
            ),
          ),
          const SizedBox(height: 12),
          Row(
            children: [
              Icon(
                _getElementIcon(element.type),
                size: 16,
                color: color,
              ),
              const SizedBox(width: 6),
              Text(
                element.documentId ?? '未关联文档',
                style: theme.textTheme.bodySmall?.copyWith(
                  color: AppColors.textSecondary,
                ),
              ),
              const Spacer(),
              if (isSelected)
                Container(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 8,
                    vertical: 4,
                  ),
                  decoration: BoxDecoration(
                    color: color.withOpacity(0.18),
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(
                        LucideIcons.check,
                        size: 14,
                        color: color,
                      ),
                      const SizedBox(width: 4),
                      Text(
                        '已选中',
                        style: theme.textTheme.bodySmall?.copyWith(
                          color: color,
                          fontWeight: FontWeight.w600,
                        ),
                      ),
                    ],
                  ),
                ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildElementGroupSection(
    ElementType type,
    List<DocumentElement> items,
    List<DocumentElement> selectedElements,
  ) {
    final color = _getElementColor(type);
    return Padding(
      padding: const EdgeInsets.only(bottom: 20),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
            decoration: BoxDecoration(
              color: color.withOpacity(0.1),
              borderRadius: BorderRadius.circular(10),
            ),
            child: Row(
              children: [
                Icon(_getElementIcon(type), size: 16, color: color),
                const SizedBox(width: 8),
                Text(
                  '${type.label} · ${items.length}',
                  style: TextStyle(
                    fontSize: 13,
                    fontWeight: FontWeight.w600,
                    color: color,
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 12),
          for (final item in items) _buildDraggableElement(item, selectedElements),
        ],
      ),
    );
  }

  Widget _buildStatBadge({
    required IconData icon,
    required String label,
    required String value,
    required Color color,
  }) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
      decoration: BoxDecoration(
        color: color.withOpacity(0.12),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: color.withOpacity(0.2)),
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(icon, size: 16, color: color),
          const SizedBox(width: 8),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                label,
                style: const TextStyle(
                  fontSize: 11,
                  color: AppColors.textSecondary,
                ),
              ),
              Text(
                value,
                style: TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.w700,
                  color: color,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  Widget _buildEmptyElementState() {
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: AppColors.backgroundLight,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: AppColors.borderLight),
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            LucideIcons.inbox,
            size: 48,
            color: AppColors.textSecondary.withOpacity(0.4),
          ),
          const SizedBox(height: 12),
          const Text(
            '暂无匹配的要素',
            style: TextStyle(
              fontSize: 14,
              fontWeight: FontWeight.w600,
              color: AppColors.textPrimary,
            ),
          ),
          const SizedBox(height: 6),
          Text(
            _showSelectedOnly ? '切换回全部或调整筛选条件试试' : '尝试更换搜索关键字或筛选条件',
            style: const TextStyle(
              fontSize: 12,
              color: AppColors.textSecondary,
            ),
          ),
        ],
      ),
    );
  }

  IconData _getElementIcon(ElementType type) {
    switch (type) {
      case ElementType.amount:
        return LucideIcons.dollar_sign;
      case ElementType.company:
        return LucideIcons.building;
      case ElementType.person:
        return LucideIcons.user;
      case ElementType.location:
        return LucideIcons.map_pin;
      default:
        return LucideIcons.tag;
    }
  }

  Widget _buildDocumentView(
    BuildContext context,
    String text,
    List<DocumentElement> elements,
  ) {
    return AppCard(
      title: Row(
        children: [
          const Icon(LucideIcons.file_text, size: 18),
          const SizedBox(width: 8),
          const Text('主文档'),
          const Spacer(),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
            decoration: BoxDecoration(
              color: AppColors.primary.withOpacity(0.1),
              borderRadius: BorderRadius.circular(6),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  LucideIcons.mouse_pointer_click,
                  size: 12,
                  color: AppColors.primary,
                ),
                const SizedBox(width: 4),
                Text(
                  '点击高亮区域选择',
                  style: TextStyle(
                    fontSize: 11,
                    fontWeight: FontWeight.w600,
                    color: AppColors.primary,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      child: Container(
        constraints: const BoxConstraints(minHeight: 600),
        padding: const EdgeInsets.all(24),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(12),
          border: Border.all(color: AppColors.border),
        ),
        child: SelectableText.rich(
          TextSpan(
            children: _buildTextSpans(text, elements),
            style: const TextStyle(
              fontSize: 15,
              height: 1.8,
              color: AppColors.textPrimary,
            ),
          ),
        ),
      ),
    );
  }

  List<TextSpan> _buildTextSpans(
    String text,
    List<DocumentElement> elements,
  ) {
    final spans = <TextSpan>[];
    int lastIndex = 0;

    for (final element in elements) {
      final index = text.indexOf(element.value, lastIndex);
      if (index != -1) {
        if (index > lastIndex) {
          spans.add(TextSpan(text: text.substring(lastIndex, index)));
        }
        spans.add(
          TextSpan(
            text: element.value,
            style: TextStyle(
              backgroundColor: _getElementColor(element.type).withOpacity(0.25),
              color: _getElementColor(element.type),
              fontWeight: FontWeight.w600,
              decoration: TextDecoration.underline,
              decorationColor: _getElementColor(element.type),
            ),
            mouseCursor: SystemMouseCursors.click,
          ),
        );
        lastIndex = index + element.value.length;
      }
    }

    if (lastIndex < text.length) {
      spans.add(TextSpan(text: text.substring(lastIndex)));
    }

    return spans.isEmpty ? [TextSpan(text: text)] : spans;
  }

  Color _getElementColor(ElementType type) {
    switch (type) {
      case ElementType.amount:
        return AppColors.amount;
      case ElementType.company:
        return AppColors.company;
      case ElementType.person:
        return AppColors.person;
      case ElementType.location:
        return AppColors.location;
      default:
        return AppColors.textSecondary;
    }
  }

  Widget _buildRelationshipBuilder(BuildContext context) {
    return Column(
      children: [
        AppCard(
            title: Row(
              children: [
                const Icon(LucideIcons.git_branch, size: 18),
                const SizedBox(width: 8),
                const Text('关系构建'),
                const Spacer(),
                Container(
                  padding: const EdgeInsets.all(4),
                  decoration: BoxDecoration(
                    color: AppColors.warning.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(6),
                  ),
                  child: Text(
                    '${_graphNodes.length} 节点',
                    style: TextStyle(
                      fontSize: 11,
                      fontWeight: FontWeight.bold,
                      color: AppColors.warning,
                    ),
                  ),
                ),
              ],
            ),
            child: Container(
              padding: const EdgeInsets.all(15),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '拖拽要素到此处构建关系网络',
                    style: TextStyle(
                      fontSize: 12,
                      color: AppColors.textSecondary,
                    ),
                  ),
                  const SizedBox(height: 16),
                  // 关系网络图
                  DragTarget<DocumentElement>(
                    onAccept: (element) {
                      setState(() {
                        _graphNodes.add(
                          GraphNode(
                            id: 'n${_graphNodes.length + 1}',
                            label: element.displayText,
                            type: NodeType.element,
                            position: Offset(
                              100 + (_graphNodes.length * 80).toDouble(),
                              120 + (_graphNodes.length * 60).toDouble(),
                            ),
                          ),
                        );
                      });
                    },
                    builder: (context, candidateData, rejectedData) {
                      final isHovering = candidateData.isNotEmpty;
                      return AnimatedContainer(
                        duration: const Duration(milliseconds: 180),
                        height: 400,
                        decoration: BoxDecoration(
                          gradient: LinearGradient(
                            begin: Alignment.topLeft,
                            end: Alignment.bottomRight,
                            colors: [
                              AppColors.background,
                              Colors.white,
                            ],
                          ),
                          borderRadius: BorderRadius.circular(12),
                          border: Border.all(
                            color: isHovering ? AppColors.primary : AppColors.border,
                            width: isHovering ? 2 : 1,
                          ),
                        ),
                        clipBehavior: Clip.hardEdge,
                        child: LayoutBuilder(
                          builder: (context, constraints) {
                            final canvasWidth = math.max(constraints.maxWidth, 600.0);
                            final canvasHeight = math.max(constraints.maxHeight, 420.0);
                            return InteractiveViewer(
                              constrained: false,
                              minScale: 0.5,
                              maxScale: 2.5,
                              boundaryMargin: const EdgeInsets.all(200),
                              child: SizedBox(
                                width: canvasWidth,
                                height: canvasHeight,
                                child: _buildGraphCanvas(
                                  Size(canvasWidth, canvasHeight),
                                ),
                              ),
                            );
                          },
                        ),
                      );
                    },
                  ),
                  const SizedBox(height: 16),
                  // 关系类型选择
                  Wrap(
                    spacing: 8,
                    runSpacing: 8,
                    children: [
                      _buildRelationChip('计算', EdgeType.calculate),
                      _buildRelationChip('引用', EdgeType.reference),
                      _buildRelationChip('包含', EdgeType.contain),
                    ],
                  ),
                ],
              ),
            )),
        const SizedBox(height: 16),
        AppCard(
          child: Column(
            children: [
              AppButton(
                text: '生成Prompt',
                type: ButtonType.primary,
                icon: LucideIcons.sparkles,
                fullWidth: true,
                onPressed: () {
                  context.push('${AppRoutes.result}/${widget.documentId}');
                },
              ),
              const SizedBox(height: 12),
              AppButton(
                text: '清空关系',
                type: ButtonType.secondary,
                icon: LucideIcons.trash_2,
                fullWidth: true,
                onPressed: () {
                  setState(() {
                    _graphNodes.clear();
                    _graphEdges.clear();
                  });
                },
              ),
            ],
          ),
        ),
      ],
    );
  }

  Widget _buildGraphCanvas(Size canvasSize) {
    if (_graphNodes.isEmpty) {
      return SizedBox.expand(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                LucideIcons.git_branch,
                size: 64,
                color: AppColors.textSecondary.withOpacity(0.5),
              ),
              const SizedBox(height: 16),
              Text(
                '拖拽要素到此处',
                style: TextStyle(
                  fontSize: 14,
                  color: AppColors.textSecondary,
                ),
              ),
              const SizedBox(height: 8),
              Text(
                '开始构建关系网络',
                style: TextStyle(
                  fontSize: 12,
                  color: AppColors.textSecondary.withOpacity(0.7),
                ),
              ),
            ],
          ),
        ),
      );
    }

    final positions = <String, Offset>{};
    for (final node in _graphNodes) {
      positions[node.id] = _clampOffset(node.position, canvasSize);
    }

    return CustomPaint(
      size: canvasSize,
      painter: GraphPainter(_graphNodes, _graphEdges, positions),
      child: Stack(
        clipBehavior: Clip.none,
        children: _graphNodes.map((node) {
          final position = positions[node.id] ?? node.position;
          return Positioned(
            left: position.dx,
            top: position.dy,
            child: _buildGraphNode(node),
          );
        }).toList(),
      ),
    );
  }

  Offset _clampOffset(Offset position, Size canvasSize) {
    const double padding = 24;
    const double nodeWidth = 160;
    const double nodeHeight = 64;
    final double maxX = math.max(padding, canvasSize.width - nodeWidth - padding);
    final double maxY = math.max(padding, canvasSize.height - nodeHeight - padding);
    return Offset(
      position.dx.clamp(padding, maxX),
      position.dy.clamp(padding, maxY),
    );
  }

  Widget _buildGraphNode(GraphNode node) {
    Color getNodeColor() {
      switch (node.type) {
        case NodeType.element:
          return AppColors.primary;
        case NodeType.operator:
          return AppColors.warning;
        case NodeType.result:
          return AppColors.success;
      }
    }

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
      decoration: BoxDecoration(
        color: getNodeColor(),
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: getNodeColor().withOpacity(0.3),
            blurRadius: 8,
            offset: const Offset(0, 2),
          ),
        ],
      ),
      child: Text(
        node.label,
        style: const TextStyle(
          color: Colors.white,
          fontSize: 12,
          fontWeight: FontWeight.w600,
        ),
      ),
    );
  }

  Widget _buildRelationChip(String label, EdgeType type) {
    return ChoiceChip(
      label: Text(label),
      selected: false,
      onSelected: (selected) {},
      labelStyle: const TextStyle(fontSize: 12),
    );
  }

  String _getMockText() {
    return '''一、项目概述
本项目由腾讯科技有限公司（以下简称"腾讯"）投资建设，旨在打造一套面向大型企业财务共享中心的"智能票据处理系统"。系统通过OCR识别、版面理解、要素抽取与人机协同核验，提升发票、合同、报销单据等票据类文档的处理效率与准确率。

二、投资与资金安排
项目总投资金额为人民币3,700万元，其中已支付1,000万元用于样机研制、数据治理与前期试点。剩余资金将依据阶段性里程碑进行分批拨付，涵盖核心算法优化、系统平台化改造、以及与客户生态的对接集成。

三、技术与产品路线
系统采用多模态文档理解技术，将版面结构、语义上下文与业务词典结合，实现对复杂票据的鲁棒解析。产品形态包含：上传解析端、人工牵引标注端、规则与关系构建端，以及结果交付端。

四、收益预期
预计上线后，票据处理效率提升60%以上，人工核验工作量下降40%，并显著降低AI"幻觉"导致的错判风险，从而提升财务数据的可靠性与可审计性。''';
  }
}

/// 关系网络绘制器
class GraphPainter extends CustomPainter {
  final List<GraphNode> nodes;
  final List<GraphEdge> edges;
  final Map<String, Offset> positions;

  GraphPainter(this.nodes, this.edges, this.positions);

  @override
  void paint(Canvas canvas, Size size) {
    if (nodes.isEmpty) return;

    const double nodeWidth = 160;
    const double nodeHeight = 64;

    final connectionPaint = Paint()
      ..color = AppColors.border
      ..strokeWidth = 1.5
      ..style = PaintingStyle.stroke;

    final arrowPaint = Paint()
      ..color = AppColors.primary
      ..style = PaintingStyle.fill;

    for (final edge in edges) {
      final source = positions[edge.source] ?? nodes.firstWhere((n) => n.id == edge.source).position;
      final target = positions[edge.target] ?? nodes.firstWhere((n) => n.id == edge.target).position;

      final sourceCenter = Offset(
        source.dx + nodeWidth / 2,
        source.dy + nodeHeight / 2,
      );
      final targetCenter = Offset(
        target.dx + nodeWidth / 2,
        target.dy + nodeHeight / 2,
      );

      canvas.drawLine(sourceCenter, targetCenter, connectionPaint);

      final dx = targetCenter.dx - sourceCenter.dx;
      final dy = targetCenter.dy - sourceCenter.dy;
      final distance = math.sqrt(dx * dx + dy * dy);
      if (distance < 0.001) continue;
      final directionX = dx / distance;
      final directionY = dy / distance;

      const arrowLength = 12.0;
      const arrowWidth = 6.0;
      final arrowPoint = Offset(
        targetCenter.dx - directionX * (nodeWidth / 2 - 4),
        targetCenter.dy - directionY * (nodeHeight / 2 - 4),
      );

      final orthogonalX = -directionY;
      final orthogonalY = directionX;

      final path = Path()
        ..moveTo(arrowPoint.dx, arrowPoint.dy)
        ..lineTo(
          arrowPoint.dx - directionX * arrowLength + orthogonalX * arrowWidth,
          arrowPoint.dy - directionY * arrowLength + orthogonalY * arrowWidth,
        )
        ..lineTo(
          arrowPoint.dx - directionX * arrowLength - orthogonalX * arrowWidth,
          arrowPoint.dy - directionY * arrowLength - orthogonalY * arrowWidth,
        )
        ..close();
      canvas.drawPath(path, arrowPaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
