import 'dart:io';
import 'dart:ui' as ui;

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:k_chart_plus/chart_translations.dart';
import 'package:k_chart_plus/k_chart_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

import '../../../core/l10n/app_localizations.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/utils/number_format.dart';
import '../../../core/utils/symbol_display.dart';
import '../../../core/utils/spot_order_book_convert.dart';
import '../../../core/utils/top_toast.dart';
import '../../../data/models/market/funding_rate.dart';
import '../../../data/models/market/order_book_entry.dart';
import '../../../providers/funding_rate_provider.dart';
import '../../../providers/futures_provider.dart';
import '../../../providers/market_detail_provider.dart';
import '../../../providers/spot_provider.dart';
import '../../widgets/common/app_shimmer.dart';
import '../../widgets/common/coin_icon.dart';
import '../../widgets/common/symbol_picker_sheet.dart';

/// K 线详情页骨架（现货 / 永续分别用 [SpotMarketDetailScreen]、[FuturesMarketDetailScreen] 入口）。
class MarketDetailScaffold extends ConsumerStatefulWidget {
  const MarketDetailScaffold({super.key, required this.marketKey});

  final MarketDetailKey marketKey;

  @override
  ConsumerState<MarketDetailScaffold> createState() =>
      _MarketDetailScaffoldState();
}

class _MarketDetailScaffoldState extends ConsumerState<MarketDetailScaffold> {
  final _shareKey = GlobalKey();
  bool _sharing = false;

  @override
  void initState() {
    super.initState();
    // provider 无 autoDispose，state 跨页面保留；进入页面时强制重置到"行情"tab
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted) return;
      ref.read(marketDetailProvider(widget.marketKey).notifier).setTopTab(0);
    });
  }

  Future<void> _handleShare() async {
    if (_sharing) return;
    if (!mounted) return;
    setState(() => _sharing = true);
    try {
      final boundary = _shareKey.currentContext?.findRenderObject()
          as RenderRepaintBoundary?;
      if (boundary == null) return;
      final image = await boundary.toImage(pixelRatio: 2.5);
      final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      final bytes = byteData!.buffer.asUint8List();
      final tempDir = await getTemporaryDirectory();
      final file = File(
          '${tempDir.path}/market_${DateTime.now().millisecondsSinceEpoch}.png');
      await file.writeAsBytes(bytes);
      // 先重置状态，再调用分享（避免用户取消时系统面板不 resolve 导致按钮卡转圈）
      if (mounted) setState(() => _sharing = false);
      Share.shareXFiles([XFile(file.path)], text: widget.marketKey.symbol);
    } catch (_) {
      if (mounted) {
        showTopToast(context,
            message: AppLocalizations.of(context)!.shareFailed,
            backgroundColor: AppColors.fall);
      }
    } finally {
      if (mounted) setState(() => _sharing = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final key = widget.marketKey;
    final isLoading = ref.watch(
      marketDetailProvider(key).select((s) => s.isLoading),
    );

    return Scaffold(
      appBar: _SymbolAppBar(
        marketKey: key,
        onShare: _handleShare,
        sharing: _sharing,
      ),
      body: RepaintBoundary(
        key: _shareKey,
        child: isLoading
            ? const _MarketDetailShimmer()
            : _DetailBody(marketKey: key),
      ),
      bottomNavigationBar: _BottomActions(marketKey: key),
    );
  }
}

// ── 顶部 AppBar（含币对切换）─────────────────────────────────

class _SymbolAppBar extends ConsumerWidget implements PreferredSizeWidget {
  const _SymbolAppBar({
    required this.marketKey,
    required this.onShare,
    this.sharing = false,
  });
  final MarketDetailKey marketKey;
  final VoidCallback onShare;
  final bool sharing;

  String get symbol => marketKey.symbol;
  bool get isFutures => marketKey.isFutures;

  @override
  Size get preferredSize => const Size.fromHeight(kToolbarHeight);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return AppBar(
      // 默认 titleSpacing 约 16，会在 leading 与 title 之间留出一块空白
      titleSpacing: 0,
      leadingWidth: 30,
      leading: IconButton(
        icon: const Icon(Icons.arrow_back_ios, size: 18),
        onPressed: () {
          if (context.canPop()) {
            context.pop();
          } else {
            context.go('/market');
          }
        },
        padding: EdgeInsets.zero,
        visualDensity: VisualDensity.compact,
        constraints: const BoxConstraints(minWidth: 40, minHeight: 40),
      ),
      title: Semantics(
        label: 'market_detail_symbol_picker',
        button: true,
        onTap: () => _showSymbolPicker(context, ref),
        child: GestureDetector(
          onTap: () => _showSymbolPicker(context, ref),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(formatUsdtPairDisplay(symbol),
                  style: const TextStyle(
                      fontSize: 17, fontWeight: FontWeight.w600)),
              const SizedBox(width: 4),
              const Icon(Icons.keyboard_arrow_down, size: 18),
            ],
          ),
        ),
      ),
      actions: [
        Semantics(
          label: 'market_detail_btn_share',
          button: true,
          enabled: !sharing,
          onTap: onShare,
          child: IconButton(
            icon: sharing
                ? const SizedBox(
                    width: 18,
                    height: 18,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                : const Icon(Icons.share_outlined, size: 20),
            onPressed: sharing ? null : onShare,
          ),
        ),
      ],
    );
  }

  void _showSymbolPicker(BuildContext context, WidgetRef ref) {
    showModalBottomSheet(
      context: context,
      useRootNavigator: true,
      isScrollControlled: true,
      backgroundColor: Theme.of(context).colorScheme.surface,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (sheetCtx) => SymbolPickerSheet(
        currentSymbol: symbol,
        initialTab: isFutures ? SymbolPickerTab.futures : SymbolPickerTab.spot,
        visibleTabs: [
          if (isFutures) SymbolPickerTab.futures else SymbolPickerTab.spot,
        ],
        onSelected: (newSymbol) {
          Navigator.pop(sheetCtx);
          if (newSymbol != symbol) {
            context.replace(isFutures
                ? '/market/futures/$newSymbol'
                : '/market/spot/$newSymbol');
          }
        },
        onSpotSelected: (newSymbol) {
          Navigator.pop(sheetCtx);
          if (newSymbol != symbol) {
            context.replace(isFutures
                ? '/market/futures/$newSymbol'
                : '/market/spot/$newSymbol');
          }
        },
      ),
    );
  }
}

// ── 详情主体 ──────────────────────────────────────────────

// 页面主体：只传 symbol，各子组件自行 select 需要的数据。
// 按 topTab 切换行情/概览内容，未激活的 tab 不构建。
class _DetailBody extends ConsumerWidget {
  const _DetailBody({required this.marketKey});

  final MarketDetailKey marketKey;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbol = marketKey.symbol;
    final topTab = ref.watch(
      marketDetailProvider(marketKey).select((s) => s.topTab),
    );

    Widget content;
    if (topTab == 0) {
      content = _MarketContent(marketKey: marketKey);
    } else if (topTab == 1) {
      content = _InfoTab(marketKey: marketKey);
    } else {
      content = _DataTab(symbol: symbol);
    }

    return Column(
      children: [
        _TopTabs(marketKey: marketKey),
        Expanded(child: content),
      ],
    );
  }
}

// 整个页面可上下滚动。K 线图用固定高度 450。
// KChartWidget 内部用 onHorizontalDrag 处理水平拖拽，
// Flutter 手势竞技场自动区分水平/垂直 — 垂直滑动归 SingleChildScrollView。
// 不需要动态切换 physics。
class _MarketContent extends StatefulWidget {
  const _MarketContent({required this.marketKey});
  final MarketDetailKey marketKey;

  @override
  State<_MarketContent> createState() => _MarketContentState();
}

class _MarketContentState extends State<_MarketContent> {
  final _dismissNotifier = ValueNotifier<bool>(false);
  // 用于判断点击位置是否在 K 线图区域内
  final _chartKey = GlobalKey();

  @override
  void dispose() {
    _dismissNotifier.dispose();
    super.dispose();
  }

  /// 点击 K 线图区域外部才触发 dismiss；
  /// 图表内部的 tap 由 KChartWidget 自身处理（展示/切换蜡烛详情）。
  void _onTapDown(TapDownDetails details) {
    final ro = _chartKey.currentContext?.findRenderObject() as RenderBox?;
    if (ro != null) {
      final local = ro.globalToLocal(details.globalPosition);
      if (local.dx >= 0 &&
          local.dx <= ro.size.width &&
          local.dy >= 0 &&
          local.dy <= ro.size.height) {
        return; // 点击在图表内部，交给 KChartWidget 处理
      }
    }
    _dismissNotifier.value = !_dismissNotifier.value;
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTapDown: _onTapDown,
      child: SingleChildScrollView(
        physics: const ClampingScrollPhysics(),
        child: Column(
          children: [
            _PriceHeader(marketKey: widget.marketKey),
            _PeriodTabBar(marketKey: widget.marketKey),
            SizedBox(
                key: _chartKey,
                child: _KlineChartArea(
                    marketKey: widget.marketKey,
                    dismissNotifier: _dismissNotifier)),
            _OrderBookSection(marketKey: widget.marketKey),
            const SizedBox(height: 16),
          ],
        ),
      ),
    );
  }
}

// ── 顶部 Tab（价格/信息）────────────────────────────────────

// 只 select topTab，行情/概览切换不触发其他区域重建
class _TopTabs extends ConsumerWidget {
  const _TopTabs({required this.marketKey});
  final MarketDetailKey marketKey;

  List<String> _getLabels(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    final tabs = [l10n.market, l10n.marketOverview];
    if (marketKey.isFutures) tabs.add(l10n.marketData);
    return tabs;
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final provider = marketDetailProvider(marketKey);
    final topTab = ref.watch(provider.select((s) => s.topTab));
    final notifier = ref.read(provider.notifier);

    final cs = Theme.of(context).colorScheme;
    final semanticsLabels = [
      'market_detail_tab_chart',
      'market_detail_tab_overview',
      if (marketKey.isFutures) 'market_detail_tab_data',
    ];
    return Container(
      decoration: BoxDecoration(
        border: Border(bottom: BorderSide(color: cs.outline)),
      ),
      child: Row(
        children: List.generate(_getLabels(context).length, (i) {
          final selected = i == topTab;
          return Semantics(
            label: semanticsLabels[i],
            button: true,
            enabled: true,
            onTap: () => notifier.setTopTab(i),
            child: GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () => notifier.setTopTab(i),
              child: Padding(
                padding: const EdgeInsets.only(left: 16, right: 8),
                child: Column(
                  children: [
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 6),
                      child: Text(
                        _getLabels(context)[i],
                        style: TextStyle(
                          fontSize: 14,
                          color: selected
                              ? cs.onSurface
                              : cs.onSurface.withAlpha(153),
                          fontWeight:
                              selected ? FontWeight.w600 : FontWeight.w400,
                        ),
                      ),
                    ),
                    // 未选中时用透明占位保持高度一致，避免切换时布局跳动
                    Container(
                      height: 2,
                      width: 24,
                      color: selected ? AppColors.brand : Colors.transparent,
                    ),
                  ],
                ),
              ),
            ),
          );
        }),
      ),
    );
  }
}

// ── 价格区 ────────────────────────────────────────────────

// 只 select stats，K线更新不会触发价格区重建
class _PriceHeader extends ConsumerWidget {
  const _PriceHeader({required this.marketKey});

  final MarketDetailKey marketKey;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbol = marketKey.symbol;
    final isFutures = marketKey.isFutures;
    final cs = Theme.of(context).colorScheme;
    final stats = ref.watch(
      marketDetailProvider(marketKey).select((s) => s.stats),
    );
    if (stats == null) return const SizedBox.shrink();
    final priceColor = AppColors.changeColor(stats.change24h);
    final sign = stats.change24h >= 0 ? '+' : '';
    // 提取基础币名（BTCUSDT → BTC）
    final baseCoin = symbol.toUpperCase().replaceFirst(RegExp(r'USDT$'), '');

    return Padding(
      padding: const EdgeInsets.fromLTRB(12, 8, 12, 6),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 大价格：用主文字色，禁止跟随涨跌色（规范 1.2 节）
          Text(
            stats.lastPriceStr != null
                ? formatRawPrice(stats.lastPriceStr!)
                : formatPrice(stats.lastPrice),
            style: TextStyle(
              color: cs.onSurface,
              fontSize: 26,
              fontWeight: FontWeight.w700,
              letterSpacing: -0.5,
              fontFeatures: const [FontFeature.tabularFigures()],
            ),
          ),
          const SizedBox(height: 2),
          // 副行：≈$xxx | 涨跌幅 |（合约：标记价格）
          Row(
            children: [
              Flexible(
                child: Text(
                  '≈ \$${formatPrice(stats.lastPrice)}',
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 11),
                ),
              ),
              const SizedBox(width: 8),
              Text(
                '$sign${stats.change24h.toStringAsFixed(2)}%',
                style: TextStyle(
                    color: priceColor,
                    fontSize: 11,
                    fontWeight: FontWeight.w500),
              ),
              if (isFutures) ...[
                const SizedBox(width: 8),
                Flexible(
                  child: Text(
                    '${AppLocalizations.of(context)!.markPrice} ${formatPrice(stats.markPrice)}',
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(153), fontSize: 11),
                  ),
                ),
              ],
            ],
          ),
          const SizedBox(height: 8),
          // 合约：3 列（含资金费率/倒计时）；现货：2 列
          Row(
            children: [
              // 列1：最高/最低
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _StatItem(
                        label: AppLocalizations.of(context)!.high24h,
                        value: formatPrice(stats.high24h),
                        color: AppColors.rise),
                    const SizedBox(height: 6),
                    _StatItem(
                        label: AppLocalizations.of(context)!.low24h,
                        value: formatPrice(stats.low24h),
                        color: AppColors.fall),
                  ],
                ),
              ),
              // 列2：成交量/额
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _StatItem(
                      label: AppLocalizations.of(context)!
                          .volume24hLabel(baseCoin),
                      value: stats.volume24h >= 1000
                          ? '${(stats.volume24h / 1000).toStringAsFixed(2)}K'
                          : stats.volume24h.toStringAsFixed(2),
                    ),
                    const SizedBox(height: 6),
                    _StatItem(
                      label: AppLocalizations.of(context)!.turnover24hLabel,
                      value: stats.turnover24h >= 1e6
                          ? '${(stats.turnover24h / 1e6).toStringAsFixed(2)}M'
                          : '${(stats.turnover24h / 1000).toStringAsFixed(2)}K',
                    ),
                  ],
                ),
              ),
              if (isFutures)
                Expanded(
                  child: _FundingColumn(symbol: symbol),
                ),
            ],
          ),
        ],
      ),
    );
  }
}

// 资金费率 + 倒计时列（仅永续合约行情页展示）
class _FundingColumn extends ConsumerWidget {
  const _FundingColumn({required this.symbol});
  final String symbol;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final fundingRate = ref.watch(
      futuresProvider(symbol).select((s) => s.fundingRate),
    );
    final fundingCountdown = ref.watch(
      futuresProvider(symbol).select((s) => s.fundingCountdown),
    );
    final sign = fundingRate >= 0 ? '+' : '';
    final rate = '$sign${(fundingRate * 100).toStringAsFixed(4)}%';
    final countdown = fundingCountdown;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        _StatItem(
            label: AppLocalizations.of(context)!.fundingRate,
            value: rate,
            align: TextAlign.right),
        const SizedBox(height: 6),
        _StatItem(
            label: AppLocalizations.of(context)!.countdown,
            value: countdown,
            align: TextAlign.right),
      ],
    );
  }
}

class _StatItem extends StatelessWidget {
  const _StatItem(
      {required this.label, required this.value, this.color, this.align});

  final String label;
  final String value;
  final Color? color;
  final TextAlign? align;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Column(
      crossAxisAlignment: align == TextAlign.right
          ? CrossAxisAlignment.end
          : CrossAxisAlignment.start,
      children: [
        Text(label,
            textAlign: align,
            style: TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 9)),
        const SizedBox(height: 1),
        Text(
          value,
          textAlign: align,
          style: TextStyle(
            color: color ?? cs.onSurface,
            fontSize: 11,
            fontWeight: FontWeight.w600,
          ),
        ),
      ],
    );
  }
}

String _klinePeriodLabel(KlinePeriod p, AppLocalizations l10n) {
  switch (p) {
    case KlinePeriod.min1:
      return l10n.klinePeriod1m;
    case KlinePeriod.min5:
      return l10n.klinePeriod5m;
    case KlinePeriod.min15:
      return l10n.klinePeriod15m;
    case KlinePeriod.min30:
      return l10n.klinePeriod30m;
    case KlinePeriod.hour1:
      return l10n.klinePeriod1h;
    case KlinePeriod.hour4:
      return l10n.klinePeriod4h;
    case KlinePeriod.day1:
      return l10n.klinePeriod1d;
    case KlinePeriod.week1:
      return l10n.klinePeriod1w;
    case KlinePeriod.month1:
      return l10n.klinePeriod1mon;
  }
}

// ── 周期 Tab ──────────────────────────────────────────────

// 只 select period，其他字段变化不触发重建
class _PeriodTabBar extends ConsumerWidget {
  const _PeriodTabBar({required this.marketKey});

  final MarketDetailKey marketKey;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cs = Theme.of(context).colorScheme;
    final l10n = AppLocalizations.of(context)!;
    final period = ref.watch(
      marketDetailProvider(marketKey).select((s) => s.period),
    );
    final onChanged =
        ref.read(marketDetailProvider(marketKey).notifier).setPeriod;
    // 主栏只展示前4个周期，其余通过"更多"选择
    const mainPeriods = [
      KlinePeriod.min1,
      KlinePeriod.min5,
      KlinePeriod.min15,
      KlinePeriod.hour1,
      KlinePeriod.day1
    ];
    final inMore = !mainPeriods.contains(period);
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
      decoration: BoxDecoration(
        border: Border(bottom: BorderSide(color: cs.outline)),
      ),
      child: Row(
        children: [
          ...mainPeriods.map((p) {
            final selected = p == period;
            return Semantics(
              label: 'market_detail_period_${p.wsInterval}',
              button: true,
              enabled: true,
              onTap: () => onChanged(p),
              child: GestureDetector(
                onTap: () => onChanged(p),
                child: Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
                  child: Text(
                    _klinePeriodLabel(p, l10n),
                    style: TextStyle(
                      fontSize: 13,
                      color: selected
                          ? AppColors.brand
                          : cs.onSurface.withAlpha(153),
                      fontWeight: selected ? FontWeight.w600 : FontWeight.w400,
                    ),
                  ),
                ),
              ),
            );
          }),
          const Spacer(),
          GestureDetector(
            onTap: () => _showMorePeriods(context, period, onChanged, l10n),
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text(
                    inMore ? _klinePeriodLabel(period, l10n) : l10n.more,
                    style: TextStyle(
                      fontSize: 13,
                      color: inMore
                          ? AppColors.brand
                          : cs.onSurface.withAlpha(153),
                      fontWeight: inMore ? FontWeight.w600 : FontWeight.w400,
                    ),
                  ),
                  Icon(Icons.keyboard_arrow_down,
                      size: 14,
                      color: inMore
                          ? AppColors.brand
                          : cs.onSurface.withAlpha(153)),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

void _showMorePeriods(
  BuildContext context,
  KlinePeriod current,
  void Function(KlinePeriod) onChanged,
  AppLocalizations l10n,
) {
  final cs = Theme.of(context).colorScheme;
  showModalBottomSheet<void>(
    context: context,
    useRootNavigator: true,
    isScrollControlled: true,
    constraints: const BoxConstraints(maxWidth: double.infinity),
    backgroundColor: Theme.of(context).colorScheme.surface,
    shape: const RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
    ),
    builder: (_) {
      return SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const SizedBox(height: 12),
            Center(
              child: Container(
                  width: 36,
                  height: 4,
                  decoration: BoxDecoration(
                    color: cs.outline,
                    borderRadius: BorderRadius.circular(2),
                  )),
            ),
            const SizedBox(height: 16),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Wrap(
                spacing: 12,
                runSpacing: 12,
                children: KlinePeriod.values.map((p) {
                  final selected = p == current;
                  return GestureDetector(
                    onTap: () {
                      onChanged(p);
                      Navigator.of(context).pop();
                    },
                    child: Container(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 20, vertical: 10),
                      decoration: BoxDecoration(
                        color: selected
                            ? AppColors.brand.withAlpha(30)
                            : cs.surface,
                        border: Border.all(
                          color: selected ? AppColors.brand : cs.outline,
                        ),
                        borderRadius: BorderRadius.circular(6),
                      ),
                      child: Text(
                        _klinePeriodLabel(p, l10n),
                        style: TextStyle(
                          fontSize: 14,
                          color: selected ? AppColors.brand : cs.onSurface,
                          fontWeight:
                              selected ? FontWeight.w600 : FontWeight.w400,
                        ),
                      ),
                    ),
                  );
                }).toList(),
              ),
            ),
            const SizedBox(height: 24),
          ],
        ),
      );
    },
  );
}

// ── K 线图区域（使用 k_chart_plus）──────────────────────

class _KlineChartArea extends ConsumerStatefulWidget {
  const _KlineChartArea({required this.marketKey, this.dismissNotifier});
  final MarketDetailKey marketKey;
  final ValueNotifier<bool>? dismissNotifier;

  @override
  ConsumerState<_KlineChartArea> createState() => _KlineChartAreaState();
}

class _KlineChartAreaState extends ConsumerState<_KlineChartArea> {
  // 主图指标（MA/BOLL/SAR 可多选）—— 默认只选 MA
  Set<MainState> _mainStates = {MainState.MA};
  // 副图指标（MACD/KDJ/RSI/WR/CCI 可多选）—— 默认全不选
  Set<SecondaryState> _secondaryStates = {};
  bool _volHidden = false;

  /// 去掉 WS 原始价格字符串的尾零，用于图表右侧标签（不加千分符）
  static String _stripRawPrice(String s) {
    final parts = s.split('.');
    if (parts.length < 2) return s;
    final decimal = parts[1].replaceAll(RegExp(r'0+$'), '');
    return decimal.isEmpty ? parts[0] : '${parts[0]}.$decimal';
  }

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final provider = marketDetailProvider(widget.marketKey);
    final entities = ref.watch(provider.select((s) => s.entities));
    final nowPriceStr = ref.watch(provider.select((s) => s.stats?.lastPriceStr));
    final notifier = ref.read(provider.notifier);

    if (entities.isEmpty) {
      final isLoading = ref.watch(provider.select((s) => s.isLoading));
      return SizedBox(
        height: 350,
        child: Center(
          child: isLoading
              ? const CircularProgressIndicator(strokeWidth: 2)
              : Text(AppLocalizations.of(context)!.noKlineData,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(128), fontSize: 14)),
        ),
      );
    }

    // 动态计算图表高度：主图 + VOL(20%) + 副图(20%×数量) + 标签(12×数量)
    const baseH = 260.0;
    final volH = _volHidden ? 0.0 : baseH * 0.2;
    final secH = baseH * 0.2 * _secondaryStates.length;
    final labelH = 12.0 * _mainStates.length;
    final chartH = baseH + volH + secH + labelH;

    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        // K 线图（高度随指标数量动态变化）
        SizedBox(
          height: chartH,
          child: Stack(
            children: [
              KChartWidget(
                entities,
                _chartStyle,
                _buildChartColors(cs, isDark),
                isTrendLine: false,
                isTapShowInfoDialog: true,
                dismissInfoNotifier: widget.dismissNotifier,
                mainStateLi: _mainStates,
                secondaryStateLi: _secondaryStates,
                volHidden: _volHidden,
                showNowPrice: true,
                maDayList: const [5, 10, 20],
                mBaseHeight: baseH,
                fixedLength: 2,
                nowPriceStr: nowPriceStr != null
                    ? _stripRawPrice(nowPriceStr)
                    : null,
                timeFormat: const [
                  yyyy,
                  '-',
                  mm,
                  '-',
                  dd,
                  ' ',
                  HH,
                  ':',
                  nn,
                  ':',
                  ss
                ],
                chartTranslations: _buildChartTranslations(context),
                verticalTextAlignment: VerticalTextAlignment.right,
                onLoadMore: (isLeft) {
                  if (!isLeft) notifier.loadMoreKlines();
                },
                isOnDrag: (isDrag) {},
              ),
              // 水印：logo（去黑底）+ 文字，居中半透明叠加
              const _KlineWatermark(),
            ],
          ),
        ),
        // 指标选择器（主图 + 副图）
        _buildIndicatorBar(),
      ],
    );
  }

  /// 指标切换栏：MA BOLL SAR | VOL MACD KDJ RSI WR
  Widget _buildIndicatorBar() {
    final cs = Theme.of(context).colorScheme;
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        border: Border(top: BorderSide(color: cs.outline)),
      ),
      child: SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: Row(
          children: [
            // 主图指标
            ..._mainIndicators.map((e) => _indicatorChip(
                  label: e.$1,
                  active: _mainStates.contains(e.$2),
                  onTap: () => setState(() {
                    if (_mainStates.contains(e.$2)) {
                      _mainStates = Set.from(_mainStates)..remove(e.$2);
                    } else {
                      _mainStates = Set.from(_mainStates)..add(e.$2);
                    }
                  }),
                )),
            // 分隔线
            Container(
                width: 1,
                height: 16,
                color: cs.outline,
                margin: const EdgeInsets.symmetric(horizontal: 6)),
            // VOL 开关
            _indicatorChip(
              label: 'VOL',
              active: !_volHidden,
              onTap: () => setState(() => _volHidden = !_volHidden),
            ),
            // 副图指标
            ..._secondaryIndicators.map((e) => _indicatorChip(
                  label: e.$1,
                  active: _secondaryStates.contains(e.$2),
                  onTap: () => setState(() {
                    if (_secondaryStates.contains(e.$2)) {
                      _secondaryStates = Set.from(_secondaryStates)
                        ..remove(e.$2);
                    } else {
                      _secondaryStates = Set.from(_secondaryStates)..add(e.$2);
                    }
                  }),
                )),
          ],
        ),
      ),
    );
  }

  Widget _indicatorChip({
    required String label,
    required bool active,
    required VoidCallback onTap,
  }) {
    final cs = Theme.of(context).colorScheme;
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: onTap,
      child: Container(
        margin: const EdgeInsets.symmetric(horizontal: 4),
        padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
        decoration: BoxDecoration(
          color: active ? AppColors.brand.withAlpha(30) : Colors.transparent,
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(
          label,
          style: TextStyle(
            fontSize: 12,
            color: active ? AppColors.brand : cs.onSurface.withAlpha(153),
            fontWeight: active ? FontWeight.w600 : FontWeight.w400,
          ),
        ),
      ),
    );
  }

  static const _mainIndicators = [
    ('MA', MainState.MA),
    ('BOLL', MainState.BOLL),
    ('SAR', MainState.SAR),
  ];

  static const _secondaryIndicators = [
    ('MACD', SecondaryState.MACD),
    ('KDJ', SecondaryState.KDJ),
    ('RSI', SecondaryState.RSI),
    ('WR', SecondaryState.WR),
    ('CCI', SecondaryState.CCI),
  ];

  // ── 主题感知图表配色 ────────────────────────────────
  ChartColors _buildChartColors(ColorScheme cs, bool isDark) => ChartColors(
        bgColor: isDark ? AppColors.darkBg : AppColors.lightBg,
        ma5Color: AppColors.chartMa5,
        ma10Color: AppColors.chartMa10,
        ma30Color: AppColors.chartMa30,
        upColor: AppColors.rise,
        dnColor: AppColors.fall,
        volColor: AppColors.chartLineBlue,
        macdColor: AppColors.chartLineBlue,
        difColor: AppColors.chartMa10,
        deaColor: AppColors.chartMa30,
        nowPriceUpColor: AppColors.rise,
        nowPriceDnColor: AppColors.fall,
        nowPriceTextColor: Colors.white,
        gridColor: cs.outline,
        kLineColor: AppColors.chartLineBlue,
        selectBorderColor: cs.outline,
        selectFillColor:
            isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        defaultTextColor:
            isDark ? AppColors.darkTextSecondary : AppColors.lightTextSecondary,
        maxColor: cs.onSurface,
        minColor: cs.onSurface,
        infoWindowNormalColor: cs.onSurface,
        infoWindowTitleColor:
            isDark ? AppColors.darkTextSecondary : AppColors.lightTextSecondary,
        infoWindowUpColor: AppColors.rise,
        infoWindowDnColor: AppColors.fall,
        hCrossColor: cs.onSurface,
        vCrossColor: cs.onSurface,
        crossTextColor: cs.onSurface,
      );

  static final _chartStyle = ChartStyle()
    ..childPadding = 12.0 // 主图与 VOL/副图之间的间距
    ..bottomPadding = 20.0 // 底部留给时间轴标签
    ..vCrossWidth = 0.5 // 十字线竖线宽度（默认 8.5 过粗）
    ..hCrossWidth = 0.5; // 十字线横线宽度

  ChartTranslations _buildChartTranslations(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    return ChartTranslations(
      date: l10n.klineDate,
      open: l10n.klineOpen,
      high: l10n.klineHigh,
      low: l10n.klineLow,
      close: l10n.klineClose,
      changeAmount: l10n.klineChangeAmt,
      change: l10n.klineChange,
      amount: l10n.klineAmount,
      vol: l10n.klineVol,
    );
  }
}

// ── 订单簿区域 ────────────────────────────────────────────

// 只 select orderBook 和 bottomTab，K线/价格变化不触发订单簿重建
class _OrderBookSection extends ConsumerWidget {
  const _OrderBookSection({required this.marketKey});

  final MarketDetailKey marketKey;

  List<String> _getTabs(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    return [l10n.orderBook, l10n.latestTrades, l10n.depthChart];
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbol = marketKey.symbol;
    final isFutures = marketKey.isFutures;
    final cs = Theme.of(context).colorScheme;
    final provider = marketDetailProvider(marketKey);
    final OrderBook? orderBook;
    int? obPriceDecimals;
    int obQtyDecimals;
    if (isFutures) {
      orderBook = ref.watch(provider.select((s) => s.orderBook));
      obPriceDecimals = null;
      obQtyDecimals = 4;
    } else {
      final spot = ref.watch(spotProvider(symbol));
      orderBook = spotRawDepthToOrderBook(
        rawAsks: spot.orderBookAsks,
        rawBids: spot.orderBookBids,
        depthPrecision: spot.depth2Pre,
      );
      obPriceDecimals = spot.depth2Pre;
      obQtyDecimals = spot.volumePrecision;
    }
    final tabIndex = ref.watch(provider.select((s) => s.bottomTab));
    final onTabChanged = ref.read(provider.notifier).setBottomTab;
    final tabs = _getTabs(context);
    return Column(
      children: [
        // Tab 行
        Container(
          decoration: BoxDecoration(
            border: Border(bottom: BorderSide(color: cs.outline)),
          ),
          child: Row(
            children: List.generate(tabs.length, (i) {
              final selected = i == tabIndex;
              return GestureDetector(
                behavior: HitTestBehavior.opaque, // 整个 padding 区域都响应点击
                onTap: () => onTabChanged(i),
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16),
                  child: Column(
                    children: [
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 14),
                        child: Text(
                          tabs[i],
                          style: TextStyle(
                            fontSize: 14,
                            color: selected
                                ? cs.onSurface
                                : cs.onSurface.withAlpha(153),
                            fontWeight:
                                selected ? FontWeight.w600 : FontWeight.w400,
                          ),
                        ),
                      ),
                      Container(
                        height: 2,
                        width: 24,
                        color: selected ? AppColors.brand : Colors.transparent,
                      ),
                    ],
                  ),
                ),
              );
            }),
          ),
        ),
        // 按 tab 切换内容
        if (tabIndex == 0) ...[
          // ── 订单簿 ────────────────────────────────
          _MergedOrderBook(
            orderBook: orderBook,
            priceDecimalPlaces: obPriceDecimals,
            qtyDecimals: obQtyDecimals,
          ),
        ] else if (tabIndex == 1) ...[
          // ── 最新成交 ──────────────────────────────
          _RecentTradesPanel(marketKey: marketKey),
        ] else if (tabIndex == 2) ...[
          // ── 深度图 ────────────────────────────────
          _DepthChartPanel(marketKey: marketKey),
        ],
      ],
    );
  }
}

// ── 合并订单簿（每行同时显示买盘/卖盘配对）─────────────────────
// 原型设计：买入qty | 买价 卖价 | 卖出qty，每行对应同一档位索引

class _MergedOrderBook extends StatelessWidget {
  const _MergedOrderBook({
    required this.orderBook,
    this.priceDecimalPlaces,
    this.qtyDecimals = 4,
  });
  final OrderBook? orderBook;

  /// 现货：与交易对 `depth2Pre` 一致；合约为 null 走 formatPrice 默认规则
  final int? priceDecimalPlaces;
  final int qtyDecimals;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    if (orderBook == null) {
      return const SizedBox(
        height: 240,
        child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
      );
    }

    final ob = orderBook!;
    // bids 按价格降序（index 0 = 最优买价），asks 按价格升序（index 0 = 最优卖价）
    final bids = ob.bids.take(12).toList();
    final asks = ob.asks.take(12).toList();
    final rowCount = bids.length > asks.length ? bids.length : asks.length;

    final maxBidAmt = bids.isEmpty
        ? 1.0
        : bids.map((e) => e.amount).fold(0.0, (a, b) => a > b ? a : b);
    final maxAskAmt = asks.isEmpty
        ? 1.0
        : asks.map((e) => e.amount).fold(0.0, (a, b) => a > b ? a : b);

    return Column(
      children: [
        // 表头
        Padding(
          padding: const EdgeInsets.fromLTRB(12, 6, 12, 2),
          child: Row(
            children: [
              Expanded(
                child: Text(AppLocalizations.of(context)!.buy,
                    style: TextStyle(color: AppColors.rise, fontSize: 10)),
              ),
              Expanded(
                child: Text(
                  AppLocalizations.of(context)!.priceLabel,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 10),
                ),
              ),
              Expanded(
                child: Text(
                  AppLocalizations.of(context)!.sell,
                  textAlign: TextAlign.right,
                  style: TextStyle(color: AppColors.fall, fontSize: 10),
                ),
              ),
            ],
          ),
        ),
        // 数据行：买卖配对展示
        for (int i = 0; i < rowCount; i++)
          _PairedRow(
            bid: i < bids.length ? bids[i] : null,
            ask: i < asks.length ? asks[i] : null,
            bidDepth: i < bids.length
                ? (bids[i].amount / maxBidAmt).clamp(0.0, 1.0)
                : 0.0,
            askDepth: i < asks.length
                ? (asks[i].amount / maxAskAmt).clamp(0.0, 1.0)
                : 0.0,
            priceDecimalPlaces: priceDecimalPlaces,
            qtyDecimals: qtyDecimals,
          ),
      ],
    );
  }
}

class _PairedRow extends StatelessWidget {
  const _PairedRow({
    this.bid,
    this.ask,
    required this.bidDepth,
    required this.askDepth,
    this.priceDecimalPlaces,
    this.qtyDecimals = 4,
  });
  final OrderBookEntry? bid;
  final OrderBookEntry? ask;
  final double bidDepth;
  final double askDepth;
  final int? priceDecimalPlaces;
  final int qtyDecimals;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;

    return SizedBox(
      height: 26,
      child: LayoutBuilder(
        builder: (_, constraints) {
          final colW = constraints.maxWidth / 3;
          final bidBarW = (colW * bidDepth).clamp(0.0, colW);
          final askBarW = (colW * askDepth).clamp(0.0, colW);

          return Stack(
            children: [
              // 买盘深度条（左列，绿色）
              if (bid != null)
                Positioned(
                  left: 0,
                  top: 0,
                  bottom: 0,
                  child: Container(
                    width: bidBarW,
                    color: const Color(0xFF23D2A1).withAlpha(25),
                  ),
                ),
              // 卖盘深度条（右列，红色）
              if (ask != null)
                Positioned(
                  right: 0,
                  top: 0,
                  bottom: 0,
                  child: Container(
                    width: askBarW,
                    color: const Color(0xFFFF767B).withAlpha(25),
                  ),
                ),
              // 文字内容
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12),
                child: Row(
                  children: [
                    // 左列：买入数量（绿色）
                    Expanded(
                      child: Text(
                        bid != null
                            ? formatAmount(bid!.amount, decimals: qtyDecimals)
                            : '',
                        style: const TextStyle(
                          color: AppColors.rise,
                          fontSize: 11,
                          fontFeatures: [FontFeature.tabularFigures()],
                        ),
                      ),
                    ),
                    // 中列：买价 + 卖价（窄屏时用 scaleDown 避免横向溢出）
                    Expanded(
                      child: FittedBox(
                        fit: BoxFit.scaleDown,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            if (bid != null)
                              Text(
                                priceDecimalPlaces != null
                                    ? formatPrice(bid!.price,
                                        decimalPlaces: priceDecimalPlaces)
                                    : formatPrice(bid!.price),
                                style: const TextStyle(
                                  color: AppColors.rise,
                                  fontSize: 11,
                                  fontWeight: FontWeight.w600,
                                  fontFeatures: [FontFeature.tabularFigures()],
                                ),
                              ),
                            if (bid != null && ask != null)
                              const SizedBox(width: 4),
                            if (ask != null)
                              Text(
                                priceDecimalPlaces != null
                                    ? formatPrice(ask!.price,
                                        decimalPlaces: priceDecimalPlaces)
                                    : formatPrice(ask!.price),
                                style: const TextStyle(
                                  color: AppColors.fall,
                                  fontSize: 11,
                                  fontWeight: FontWeight.w600,
                                  fontFeatures: [FontFeature.tabularFigures()],
                                ),
                              ),
                          ],
                        ),
                      ),
                    ),
                    // 右列：卖出数量（灰色）
                    Expanded(
                      child: Text(
                        ask != null
                            ? formatAmount(ask!.amount, decimals: qtyDecimals)
                            : '',
                        textAlign: TextAlign.right,
                        style: TextStyle(
                          color: cs.onSurface.withAlpha(153),
                          fontSize: 11,
                          fontFeatures: const [FontFeature.tabularFigures()],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

// ── K 线图水印 ────────────────────────────────────────────

class _KlineWatermark extends StatelessWidget {
  const _KlineWatermark();

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return IgnorePointer(
      child: Align(
        alignment: const Alignment(0, -0.5),
        child: Opacity(
          opacity: isDark ? 0.35 : 0.15,
          child: Image.asset(
            isDark ? 'assets/images/C2.png' : 'assets/images/C1.png',
            width: 120,
          ),
        ),
      ),
    );
  }
}

// ── 深度图面板（使用 k_chart_plus DepthChart）─────────────

class _DepthChartPanel extends ConsumerWidget {
  const _DepthChartPanel({required this.marketKey});
  final MarketDetailKey marketKey;

  /// 买盘预累计量
  /// bids 按价格降序传入（index 0 = 最优买价）。
  /// 绘制器期望 index 0 在左端（最差价、最大累计量），index last 在右端中间价附近（最优价、最小累计量）。
  /// 因此先累计再 reversed：最终 [最差价/最大量, ..., 最优价/最小量]
  static List<DepthEntity> _toBidDepth(List<OrderBookEntry> bids) {
    double cum = 0;
    final result = bids.map((e) {
      cum += e.amount;
      return DepthEntity(e.price, cum);
    }).toList();
    return result.reversed.toList();
  }

  /// 卖盘预累计量（价格升序，累计从最低价开始）
  static List<DepthEntity> _toAskDepth(List<OrderBookEntry> asks) {
    double cum = 0;
    return asks.map((e) {
      cum += e.amount;
      return DepthEntity(e.price, cum);
    }).toList();
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cs = Theme.of(context).colorScheme;
    final isFutures = marketKey.isFutures;
    final OrderBook? orderBook;
    var baseUnit = 4;
    var quoteUnit = 2;
    if (isFutures) {
      orderBook = ref.watch(
        marketDetailProvider(marketKey).select((s) => s.orderBook),
      );
    } else {
      final spot = ref.watch(spotProvider(marketKey.symbol));
      orderBook = spotRawDepthToOrderBook(
        rawAsks: spot.orderBookAsks,
        rawBids: spot.orderBookBids,
        depthPrecision: spot.depth2Pre,
      );
      baseUnit = spot.volumePrecision;
      quoteUnit = spot.depth2Pre;
    }

    if (orderBook == null || orderBook.bids.isEmpty || orderBook.asks.isEmpty) {
      return SizedBox(
        height: 230,
        child: Center(
          child: Text(AppLocalizations.of(context)!.noDepthData,
              style:
                  TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 13)),
        ),
      );
    }

    final bids = _toBidDepth(orderBook.bids);
    final asks = _toAskDepth(orderBook.asks);
    final depthColors = ChartColors(
      bgColor: cs.surface,
      upColor: AppColors.rise,
      dnColor: AppColors.fall,
      gridColor: cs.outline,
      defaultTextColor: cs.onSurface.withAlpha(153),
      depthBuyColor: AppColors.rise,
      depthSellColor: AppColors.fall,
    );

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 图例
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
          child: Row(
            children: [
              _DepthLegendDot(color: AppColors.rise),
              const SizedBox(width: 4),
              Text(AppLocalizations.of(context)!.buy,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 11)),
              const SizedBox(width: 16),
              _DepthLegendDot(color: AppColors.fall),
              const SizedBox(width: 4),
              Text(AppLocalizations.of(context)!.sell,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 11)),
            ],
          ),
        ),
        SizedBox(
          height: 260,
          child: DepthChart(
            bids,
            asks,
            depthColors,
            baseUnit: baseUnit,
            quoteUnit: quoteUnit,
          ),
        ),
      ],
    );
  }
}

class _DepthLegendDot extends StatelessWidget {
  const _DepthLegendDot({required this.color});
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 8,
      height: 8,
      decoration: BoxDecoration(color: color, shape: BoxShape.circle),
    );
  }
}

// ── 最新成交面板 ─────────────────────────────────────────

/// 按照设计稿：表头（时间 / 价格(USDT) / 数量(BTC)）+ 成交列表
/// 通过 .select((s) => s.trades) 独立订阅，订单簿变化不触发此面板重建
class _RecentTradesPanel extends ConsumerWidget {
  const _RecentTradesPanel({required this.marketKey});
  final MarketDetailKey marketKey;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbol = marketKey.symbol;
    final isFutures = marketKey.isFutures;
    final cs = Theme.of(context).colorScheme;
    final List<RecentTrade> trades;
    var qtyDecimals = 2;
    if (isFutures) {
      trades = ref.watch(
        marketDetailProvider(marketKey).select((s) => s.trades),
      );
    } else {
      final pub = ref.watch(
        spotProvider(symbol).select((s) => s.recentPublicTrades),
      );
      qtyDecimals = ref.watch(
        spotProvider(symbol).select((s) => s.volumePrecision),
      );
      trades = pub
          .map(
            (t) => RecentTrade(
              price: t.price,
              quantity: t.quantity,
              isBuyerMaker: t.isBuyerMaker,
              time: t.time,
              tradeId: t.tradeId,
            ),
          )
          .toList();
    }
    final base = symbol
        .replaceAll('USDT', '')
        .replaceAll('PERP', '')
        .replaceAll('/', '');

    return Column(
      children: [
        // 表头
        Padding(
          padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
          child: Row(
            children: [
              Expanded(
                child: Text(AppLocalizations.of(context)!.timeLabel2,
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(153), fontSize: 11)),
              ),
              Expanded(
                child: Text(AppLocalizations.of(context)!.priceLabel,
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(153), fontSize: 11)),
              ),
              Expanded(
                child: Text(AppLocalizations.of(context)!.amountLabel2(base),
                    textAlign: TextAlign.right,
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(153), fontSize: 11)),
              ),
            ],
          ),
        ),
        // 成交列表
        if (trades.isEmpty)
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 30),
            child: Center(
              child: Text(AppLocalizations.of(context)!.noTradeData,
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 13)),
            ),
          )
        else
          ...trades.take(20).map(
                (t) => _TradeRow(trade: t, qtyDecimals: qtyDecimals),
              ),
      ],
    );
  }
}

class _TradeRow extends StatelessWidget {
  const _TradeRow({required this.trade, this.qtyDecimals = 2});
  final RecentTrade trade;
  final int qtyDecimals;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    // 主动卖出（isBuyerMaker=true）显示红色，主动买入显示绿色
    final color = trade.isBuyerMaker ? AppColors.fall : AppColors.rise;
    final time = DateTime.fromMillisecondsSinceEpoch(trade.time);
    final timeStr = '${time.hour.toString().padLeft(2, '0')}:'
        '${time.minute.toString().padLeft(2, '0')}:'
        '${time.second.toString().padLeft(2, '0')}';

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
      child: Row(
        children: [
          Expanded(
            child: Text(
              timeStr,
              style:
                  TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 12),
            ),
          ),
          Expanded(
            child: Text(
              formatPrice(trade.price),
              textAlign: TextAlign.center,
              style: TextStyle(
                  color: color, fontSize: 12, fontWeight: FontWeight.w500),
            ),
          ),
          Expanded(
            child: Text(
              formatAmount(trade.quantity, decimals: qtyDecimals),
              textAlign: TextAlign.right,
              style: TextStyle(color: cs.onSurface, fontSize: 12),
            ),
          ),
        ],
      ),
    );
  }
}

// ── 底部买入/卖出 或 开多/开空 按钮 ─────────────────────────────────────

class _BottomActions extends StatelessWidget {
  const _BottomActions({required this.marketKey});

  final MarketDetailKey marketKey;

  @override
  Widget build(BuildContext context) {
    final symbol = marketKey.symbol;
    final isFutures = marketKey.isFutures;
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final l10n = AppLocalizations.of(context)!;
    final buyLabel = isFutures ? l10n.openLong : l10n.buy;
    final sellLabel = isFutures ? l10n.openShort : l10n.sell;
    final route = isFutures ? '/futures/$symbol' : '/spot/$symbol';

    return Container(
      padding: const EdgeInsets.fromLTRB(16, 10, 16, 16),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        border: Border(top: BorderSide(color: cs.outline)),
      ),
      child: Row(
        children: [
          Expanded(
            child: ElevatedButton(
              onPressed: () => context.go(route),
              style: ElevatedButton.styleFrom(
                backgroundColor: AppColors.rise,
                foregroundColor: Colors.white,
                minimumSize: const Size(0, 46),
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8)),
                elevation: 0,
              ),
              child: Text(buyLabel,
                  style: const TextStyle(
                      fontSize: 16, fontWeight: FontWeight.w600)),
            ),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: ElevatedButton(
              onPressed: () => context.go(route),
              style: ElevatedButton.styleFrom(
                backgroundColor: AppColors.fall,
                foregroundColor: Colors.white,
                minimumSize: const Size(0, 46),
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(8)),
                elevation: 0,
              ),
              child: Text(sellLabel,
                  style: const TextStyle(
                      fontSize: 16, fontWeight: FontWeight.w600)),
            ),
          ),
        ],
      ),
    );
  }
}

// ══════════════════════════════════════════════════════════════
// 概览 Tab（币种信息 + 关键数据）
// ══════════════════════════════════════════════════════════════

class _InfoTab extends ConsumerWidget {
  const _InfoTab({required this.marketKey});
  final MarketDetailKey marketKey;

  String _formatPrice(double? v) {
    if (v == null) return '--';
    // 移除多余尾零，保留有效精度
    final s = v.toStringAsFixed(8).replaceAll(RegExp(r'\.?0+$'), '');
    return '\$$s';
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbol = marketKey.symbol;
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final baseAsset =
        symbol.toUpperCase().replaceAll('USDT', '').replaceAll('PERP', '');
    final coinExt = ref.watch(
      marketDetailProvider(marketKey).select((s) => s.coinExt),
    );

    // 从 API 数据构建关键数据行（无数据时展示 --）
    List<(String, String, String?)> buildInfoRows() {
      final l10n = AppLocalizations.of(context)!;
      return [
        (l10n.rank, coinExt?.rank != null ? 'No.${coinExt!.rank}' : '--', null),
        (l10n.marketCap, coinExt?.marketCap ?? '--', null),
        (l10n.circulatingSupply, coinExt?.circulatingSupply ?? '--', null),
        (l10n.issuePrice, _formatPrice(coinExt?.issuePrice), null),
        (l10n.athPrice, _formatPrice(coinExt?.athPrice), coinExt?.athDate),
      ];
    }

    final info = buildInfoRows();
    final coinName = coinExt?.nameCn ?? baseAsset;
    final coinNameEn = coinExt?.nameEn ?? '';
    final iconUrl = coinExt?.icon;

    return SingleChildScrollView(
      physics: const ClampingScrollPhysics(),
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // ── 币种信息卡 ──────────────────────────────────
          Container(
            padding: const EdgeInsets.all(14),
            decoration: BoxDecoration(
              color: isDark
                  ? AppColors.darkBgSecondary
                  : AppColors.lightBgSecondary,
              borderRadius: BorderRadius.circular(12),
            ),
            child: Row(
              children: [
                // 圆形图标（优先网络图片，失败降级为字母）
                CoinIcon(
                  symbol: baseAsset,
                  iconUrl: iconUrl ?? '',
                  size: 40,
                  shape: BoxShape.circle,
                ),
                const SizedBox(width: 12),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        Text(
                          baseAsset,
                          style: TextStyle(
                            color: cs.onSurface,
                            fontSize: 16,
                            fontWeight: FontWeight.w700,
                          ),
                        ),
                        if (coinName.isNotEmpty && coinName != baseAsset) ...[
                          const SizedBox(width: 6),
                          Text(
                            '（$coinName）',
                            style: TextStyle(
                              color: cs.onSurface.withAlpha(153),
                              fontSize: 14,
                            ),
                          ),
                        ],
                      ],
                    ),
                    if (coinNameEn.isNotEmpty) ...[
                      const SizedBox(height: 2),
                      Text(
                        coinNameEn,
                        style: TextStyle(
                          color: cs.onSurface.withAlpha(153),
                          fontSize: 12,
                        ),
                      ),
                    ],
                  ],
                ),
              ],
            ),
          ),

          if (info.isNotEmpty) ...[
            const SizedBox(height: 20),
            // ── 关键数据 ──────────────────────────────────
            Text(
              AppLocalizations.of(context)!.keyData,
              style: TextStyle(
                color: cs.onSurface,
                fontSize: 16,
                fontWeight: FontWeight.w600,
              ),
            ),
            const SizedBox(height: 8),
            Container(
              decoration: BoxDecoration(
                color: isDark
                    ? AppColors.darkBgSecondary
                    : AppColors.lightBgSecondary,
                borderRadius: BorderRadius.circular(12),
              ),
              child: Column(
                children: [
                  for (var i = 0; i < info.length; i++) ...[
                    if (i > 0)
                      Divider(
                        color: cs.outline,
                        height: 1,
                        indent: 16,
                        endIndent: 16,
                      ),
                    _InfoRow(
                      label: info[i].$1,
                      value: info[i].$2,
                      subValue: info[i].$3,
                    ),
                  ],
                ],
              ),
            ),
          ],

          const SizedBox(height: 20),
          // ── 免责声明 ──────────────────────────────────
          Center(
            child: Text(
              AppLocalizations.of(context)!.dataDisclaimer,
              style: TextStyle(
                color: cs.onSurface.withAlpha(120),
                fontSize: 11,
              ),
            ),
          ),
          const SizedBox(height: 16),
        ],
      ),
    );
  }
}

// ── 关键数据行 ──────────────────────────────────────────────

class _InfoRow extends StatelessWidget {
  const _InfoRow({
    required this.label,
    required this.value,
    this.subValue,
  });
  final String label;
  final String value;
  final String? subValue;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            label,
            style: TextStyle(
              color: cs.onSurface.withAlpha(153),
              fontSize: 14,
            ),
          ),
          Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Text(
                value,
                style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                ),
              ),
              if (subValue != null)
                Text(
                  subValue!,
                  style: TextStyle(
                    color: cs.onSurface.withAlpha(150),
                    fontSize: 11,
                  ),
                ),
            ],
          ),
        ],
      ),
    );
  }
}

// ══════════════════════════════════════════════════════════════
// 数据 Tab（资金费率图表 + 历史记录）
// ══════════════════════════════════════════════════════════════

class _DataTab extends ConsumerWidget {
  const _DataTab({required this.symbol});
  final String symbol;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final contractCoinId = ref.watch(
      futuresProvider(symbol).select((s) => s.contractCoinId),
    );

    if (contractCoinId <= 0) {
      return const Center(child: CircularProgressIndicator());
    }

    final state = ref.watch(fundingRateProvider(contractCoinId));
    final l10n = AppLocalizations.of(context)!;
    final cs = Theme.of(context).colorScheme;

    if (state.isLoading) {
      return const Center(child: CircularProgressIndicator());
    }

    if (state.error != null && state.history.isEmpty) {
      return Center(
        child: Text(l10n.loadFailed,
            style: TextStyle(color: cs.onSurface.withAlpha(153))),
      );
    }

    final current = state.current;
    final history = state.history;
    final ratePct = current != null
        ? '${current.rate >= 0 ? '+' : ''}${(current.rate * 100).toStringAsFixed(4)}%'
        : '--';

    // 下次结算倒计时（使用 futuresProvider 的 fundingCountdown，已由 WS 驱动）
    final countdown = ref.watch(
      futuresProvider(symbol).select((s) => s.fundingCountdown),
    );

    // 去掉 ScrollView 的横向 padding，改为对各区块单独加 padding，
    // 图表本身不加，实现全宽贴边显示
    const hPad = EdgeInsets.symmetric(horizontal: 16);

    return SingleChildScrollView(
      physics: const ClampingScrollPhysics(),
      padding: const EdgeInsets.only(top: 16, bottom: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // ── 当前资金费率 ──────────────────────────────────
          Padding(
            padding: hPad,
            child: RichText(
              text: TextSpan(
                children: [
                  TextSpan(
                    text: '${l10n.fundingRate}：',
                    style: TextStyle(
                      color: cs.onSurface.withAlpha(180),
                      fontSize: 14,
                    ),
                  ),
                  TextSpan(
                    text: ratePct,
                    style: TextStyle(
                      color: current != null && current.rate >= 0
                          ? AppColors.rise
                          : AppColors.fall,
                      fontSize: 14,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 12),

          // ── 折线图（全宽，不加横向 padding）────────────────
          if (history.isNotEmpty)
            _FundingRateChart(history: history)
          else
            Container(
              height: 180,
              alignment: Alignment.center,
              child: Text(l10n.noData,
                  style: TextStyle(color: cs.onSurface.withAlpha(120))),
            ),

          const SizedBox(height: 16),

          // ── 时间周期 & 倒计时 ────────────────────────────
          Padding(
            padding: hPad,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _infoRow(context, l10n.timePeriod, '8H'),
                Divider(color: cs.outline.withAlpha(80), height: 1),
                _infoRow(context, l10n.nextFundingCountdown, countdown),
                Divider(color: cs.outline, height: 1),
                const SizedBox(height: 12),

                // ── 历史表头 ──────────────────────────────────────
                _HistoryHeader(l10n: l10n),
                const SizedBox(height: 4),

                // ── 历史列表 ──────────────────────────────────────
                if (history.isEmpty)
                  Padding(
                    padding: const EdgeInsets.symmetric(vertical: 24),
                    child: Center(
                      child: Text(l10n.noData,
                          style: TextStyle(color: cs.onSurface.withAlpha(120))),
                    ),
                  )
                else
                  ...history.reversed.map((item) => _HistoryRow(item: item)),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _infoRow(BuildContext context, String label, String value) {
    final cs = Theme.of(context).colorScheme;
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 12),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(label,
              style:
                  TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 14)),
          Text(value, style: TextStyle(color: cs.onSurface, fontSize: 14)),
        ],
      ),
    );
  }
}

// ── 资金费率折线图 ────────────────────────────────────────

class _FundingRateChart extends StatelessWidget {
  const _FundingRateChart({required this.history});
  final List<FundingRateHistoryItem> history;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final items = history;
    if (items.isEmpty) return const SizedBox.shrink();

    final rates = items.map((e) => e.rate).toList();
    final minRate = rates.reduce((a, b) => a < b ? a : b);
    final maxRate = rates.reduce((a, b) => a > b ? a : b);
    final rangePad = (maxRate - minRate) * 0.25;
    final yMin = minRate - rangePad;
    final yMax = maxRate + rangePad;

    final spots = items.asMap().entries.map((e) {
      return FlSpot(e.key.toDouble(), e.value.rate);
    }).toList();

    // 与 K 线图保持一致的配色
    final bgColor = isDark ? AppColors.darkBg : AppColors.lightBg;
    final gridColor = cs.outline.withAlpha(50);
    final textColor =
        isDark ? AppColors.darkTextSecondary : AppColors.lightTextSecondary;
    const lineColor = AppColors.chartLineBlue;
    final tooltipBg =
        isDark ? AppColors.darkBgSecondary : const Color(0xFF3A3A3C);

    // x 轴标签间距：最多显示 5 个
    final xInterval = (items.length / 5).floorToDouble().clamp(1.0, 999.0);

    return Container(
      height: 220,
      color: bgColor,
      padding: const EdgeInsets.only(top: 8, bottom: 2, left: 4),
      child: LineChart(
        LineChartData(
          minY: yMin,
          maxY: yMax,
          clipData: const FlClipData.all(),
          gridData: FlGridData(
            show: true,
            drawVerticalLine: true,
            verticalInterval: xInterval,
            horizontalInterval: (yMax - yMin) / 4,
            getDrawingHorizontalLine: (_) =>
                FlLine(color: gridColor, strokeWidth: 0.5),
            getDrawingVerticalLine: (_) =>
                FlLine(color: gridColor, strokeWidth: 0.5),
          ),
          borderData: FlBorderData(show: false),
          titlesData: FlTitlesData(
            leftTitles:
                const AxisTitles(sideTitles: SideTitles(showTitles: false)),
            topTitles:
                const AxisTitles(sideTitles: SideTitles(showTitles: false)),
            rightTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                reservedSize: 58,
                getTitlesWidget: (val, meta) {
                  // 只在网格线位置显示，跳过首尾极值
                  if (val == meta.min || val == meta.max) {
                    return const SizedBox.shrink();
                  }
                  final pct = (val * 100).toStringAsFixed(3);
                  return Padding(
                    padding: const EdgeInsets.only(left: 4),
                    child: Text('$pct%',
                        style: TextStyle(fontSize: 9, color: textColor)),
                  );
                },
              ),
            ),
            bottomTitles: AxisTitles(
              sideTitles: SideTitles(
                showTitles: true,
                reservedSize: 18,
                interval: xInterval,
                getTitlesWidget: (val, _) {
                  final idx = val.toInt();
                  if (idx < 0 || idx >= items.length) {
                    return const SizedBox.shrink();
                  }
                  final date = items[idx].fundingTime;
                  return Text(
                    DateFormat('MM/dd').format(date),
                    style: TextStyle(fontSize: 9, color: textColor),
                  );
                },
              ),
            ),
          ),
          // 零轴参考线（虚线），与 K 线图十字线风格对齐
          extraLinesData: ExtraLinesData(
            horizontalLines: [
              HorizontalLine(
                y: 0,
                color: cs.outline.withAlpha(160),
                strokeWidth: 0.8,
                dashArray: [4, 4],
              ),
            ],
          ),
          lineTouchData: LineTouchData(
            enabled: true,
            // 十字线：与 K 线图 vCrossWidth / hCrossWidth 对齐
            getTouchedSpotIndicator: (_, indices) => indices.map((_) {
              return TouchedSpotIndicatorData(
                FlLine(color: cs.onSurface.withAlpha(160), strokeWidth: 0.5),
                FlDotData(
                  show: true,
                  getDotPainter: (_, __, ___, ____) => FlDotCirclePainter(
                    radius: 3.5,
                    color: lineColor,
                    strokeWidth: 1.5,
                    strokeColor: Colors.white,
                  ),
                ),
              );
            }).toList(),
            touchTooltipData: LineTouchTooltipData(
              getTooltipColor: (_) => tooltipBg,
              tooltipRoundedRadius: 4,
              tooltipPadding:
                  const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
              getTooltipItems: (touchedSpots) {
                return touchedSpots.map((spot) {
                  final idx = spot.spotIndex;
                  if (idx < 0 || idx >= items.length) return null;
                  final item = items[idx];
                  final dateStr =
                      DateFormat('MM/dd HH:mm').format(item.fundingTime);
                  final rateStr =
                      '${item.rate >= 0 ? '+' : ''}${(item.rate * 100).toStringAsFixed(4)}%';
                  final rateColor =
                      item.rate >= 0 ? AppColors.rise : AppColors.fall;
                  return LineTooltipItem(
                    '$dateStr\n',
                    TextStyle(
                        color: isDark
                            ? AppColors.darkTextSecondary
                            : Colors.white70,
                        fontSize: 10),
                    children: [
                      TextSpan(
                        text: rateStr,
                        style: TextStyle(
                            color: rateColor,
                            fontSize: 11,
                            fontWeight: FontWeight.w600),
                      ),
                    ],
                  );
                }).toList();
              },
            ),
            touchCallback: (_, __) {},
            handleBuiltInTouches: true,
          ),
          lineBarsData: [
            LineChartBarData(
              spots: spots,
              isCurved: true,
              curveSmoothness: 0.25,
              color: lineColor,
              barWidth: 1.5,
              dotData: const FlDotData(show: false),
              // 线下渐变填充，与 K 线图折线模式风格一致
              belowBarData: BarAreaData(
                show: true,
                gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [
                    lineColor.withAlpha(60),
                    lineColor.withAlpha(0),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ── 历史表头 & 行 ─────────────────────────────────────────

class _HistoryHeader extends StatelessWidget {
  const _HistoryHeader({required this.l10n});
  final AppLocalizations l10n;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final style = TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 12);
    return Row(
      children: [
        Expanded(child: Text(l10n.timeLabel, style: style)),
        Expanded(
            child: Text(l10n.fundingRate,
                style: style, textAlign: TextAlign.right)),
      ],
    );
  }
}

class _HistoryRow extends StatelessWidget {
  const _HistoryRow({required this.item});
  final FundingRateHistoryItem item;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final rateStr =
        '${item.rate >= 0 ? '+' : ''}${(item.rate * 100).toStringAsFixed(4)}%';
    final rateColor = item.rate >= 0 ? AppColors.rise : AppColors.fall;
    final timeStr = DateFormat('yyyy-MM-dd HH:mm').format(item.fundingTime);

    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 10),
      child: Row(
        children: [
          Expanded(
            child: Text(
              timeStr,
              style: TextStyle(color: cs.onSurface, fontSize: 12),
            ),
          ),
          Text(
            rateStr,
            style: TextStyle(color: rateColor, fontSize: 12),
          ),
        ],
      ),
    );
  }
}

// ── 行情详情骨架屏 ─────────────────────────────────────────

class _MarketDetailShimmer extends StatelessWidget {
  const _MarketDetailShimmer();

  @override
  Widget build(BuildContext context) {
    return AppShimmer(
      child: SingleChildScrollView(
        physics: const NeverScrollableScrollPhysics(),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 行情/概览 Tab 占位
            Container(
              height: 44,
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Row(
                children: [
                  shimmerBox(32, 16),
                  const SizedBox(width: 24),
                  shimmerBox(32, 16),
                ],
              ),
            ),
            // 价格头部
            Padding(
              padding: const EdgeInsets.fromLTRB(12, 12, 12, 8),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  shimmerBox(160, 32, radius: 6),
                  const SizedBox(height: 8),
                  Row(
                    children: [
                      shimmerBox(80, 12),
                      const SizedBox(width: 8),
                      shimmerBox(50, 12),
                      const SizedBox(width: 8),
                      shimmerBox(90, 12),
                    ],
                  ),
                  const SizedBox(height: 12),
                  Row(
                    children: List.generate(
                        3,
                        (col) => Expanded(
                              child: Column(
                                crossAxisAlignment: col == 2
                                    ? CrossAxisAlignment.end
                                    : col == 1
                                        ? CrossAxisAlignment.center
                                        : CrossAxisAlignment.start,
                                children: [
                                  shimmerBox(48, 10),
                                  const SizedBox(height: 4),
                                  shimmerBox(60, 12),
                                  const SizedBox(height: 8),
                                  shimmerBox(48, 10),
                                  const SizedBox(height: 4),
                                  shimmerBox(60, 12),
                                ],
                              ),
                            )),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 4),
            // 周期 Tab 占位
            SizedBox(
              height: 36,
              child: ListView.separated(
                scrollDirection: Axis.horizontal,
                padding: const EdgeInsets.symmetric(horizontal: 12),
                physics: const NeverScrollableScrollPhysics(),
                itemCount: 7,
                separatorBuilder: (_, __) => const SizedBox(width: 16),
                itemBuilder: (_, __) => Center(child: shimmerBox(28, 14)),
              ),
            ),
            const SizedBox(height: 6),
            // K 线图区域占位
            shimmerFill(340, radius: 0),
            // 指标栏
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
              child: Row(
                children: List.generate(
                    4,
                    (i) => Padding(
                          padding: const EdgeInsets.only(right: 12),
                          child: shimmerBox(28, 14),
                        )),
              ),
            ),
            const SizedBox(height: 4),
            // 历史收益率行
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: List.generate(
                    6,
                    (_) => Column(
                          children: [
                            shimmerBox(24, 10),
                            const SizedBox(height: 4),
                            shimmerBox(32, 12),
                          ],
                        )),
              ),
            ),
            const SizedBox(height: 8),
            // 订单簿 Tab 行
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
              child: Row(
                children: [
                  shimmerBox(48, 14),
                  const SizedBox(width: 24),
                  shimmerBox(48, 14),
                  const SizedBox(width: 24),
                  shimmerBox(36, 14),
                ],
              ),
            ),
            // 订单簿表头
            Padding(
              padding: const EdgeInsets.fromLTRB(12, 4, 12, 4),
              child: Row(
                children: [
                  Expanded(child: shimmerBox(24, 10)),
                  Expanded(child: Center(child: shimmerBox(56, 10))),
                  Expanded(
                      child: Align(
                          alignment: Alignment.centerRight,
                          child: shimmerBox(24, 10))),
                ],
              ),
            ),
            // 订单簿数据行
            ...List.generate(
                10,
                (_) => Padding(
                      padding: const EdgeInsets.symmetric(
                          horizontal: 12, vertical: 5),
                      child: Row(
                        children: [
                          Expanded(child: shimmerBox(52, 12)),
                          Expanded(child: Center(child: shimmerBox(80, 12))),
                          Expanded(
                              child: Align(
                                  alignment: Alignment.centerRight,
                                  child: shimmerBox(52, 12))),
                        ],
                      ),
                    )),
            const SizedBox(height: 16),
          ],
        ),
      ),
    );
  }
}
