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

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:gal/gal.dart';
import 'package:go_router/go_router.dart';
import 'package:path_provider/path_provider.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:share_plus/share_plus.dart';

import '../../../core/l10n/app_localizations.dart';
import '../../../core/utils/avatar_urls.dart';
import '../../../core/network/dio_client.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/utils/dialog_utils.dart' show extractErrorMessage;
import '../../../core/utils/top_toast.dart';
import '../../../data/repositories/copy_trading_repository.dart';
import '../../../data/services/auth_service.dart';
import '../../../providers/app_provider.dart';
import '../../widgets/common/app_refresh_indicator.dart';
import '../../widgets/common/app_shimmer.dart';
import '../../widgets/common/app_tab_bar.dart';

class MyTradesScreen extends ConsumerStatefulWidget {
  const MyTradesScreen({super.key});

  @override
  ConsumerState<MyTradesScreen> createState() => _MyTradesScreenState();
}

class _MyTradesScreenState extends ConsumerState<MyTradesScreen>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;
  late PageController _pageController;

  bool _loadingProfile = true;
  Map<String, dynamic>? _traderInfo;
  List<Map<String, dynamic>> _tags = [];
  int? _followerCount;

  bool _loadingFollowers = true;
  bool _followersLoaded = false;
  List<Map<String, dynamic>> _followers = [];
  int _followersPage = 1;
  bool _followersHasMore = true;
  bool _followersLoadingMore = false;
  static const _followersPageSize = 20;

  bool _loadingCurrentOrders = true;
  bool _currentOrdersLoaded = false;
  List<Map<String, dynamic>> _currentOrders = [];

  bool _loadingHistoryOrders = true;
  bool _historyOrdersLoaded = false;
  List<Map<String, dynamic>> _historyOrders = [];

  String _traderId = '';
  List<String> _traderSymbols = [];
  bool _symbolExpanded = true;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);
    _pageController = PageController();
    _tabController.addListener(() {
      if (!context.mounted) return;
      if (_tabController.indexIsChanging) {
        _pageController.animateToPage(
          _tabController.index,
          duration: const Duration(milliseconds: 280),
          curve: Curves.easeOut,
        );
      } else {
        _onTabChanged(_tabController.index);
      }
    });
    _pageController.addListener(() {
      if (!context.mounted) return;
      if (!_pageController.hasClients) return;
      final page = _pageController.page!;
      final offset = page - _tabController.index;
      if (offset.abs() <= 1.0 && !_tabController.indexIsChanging) {
        _tabController.offset = offset.clamp(-1.0, 1.0);
      }
    });
    _loadProfile();
  }

  @override
  void dispose() {
    _tabController.dispose();
    _pageController.dispose();
    super.dispose();
  }

  Future<void> _loadProfile() async {
    if (!context.mounted) return;
    setState(() => _loadingProfile = true);
    try {
      final repo = ref.read(copyTradingRepositoryProvider);

      // Step1: traderId 是后续请求的依赖，先串行获取
      final followerInfo = await repo.getFollowerInfo();
      _traderId = followerInfo?['id']?.toString() ?? '';

      // Step2: 全部数据并行加载，skeleton 保持到所有数据就绪
      final results = await Future.wait([
        _traderId.isNotEmpty // [0] 带单员信息
            ? repo.getTraderInfo(_traderId).then<dynamic>((v) => v)
            : Future<dynamic>.value(null),
        repo.getMyTags().then<dynamic>((v) => v), // [1] 标签
        repo
            .getMyFollowerCount() // [2] 跟单人数
            .then<dynamic>((v) => v)
            .catchError((_) => 0 as dynamic),
        repo
            .getMyFollowers(page: 1, pageSize: _followersPageSize) // [3] 跟单用户
            .then<dynamic>((v) => v),
        _traderId.isNotEmpty // [4] 当前带单 + 合约持仓
            ? Future.wait([
                repo.getTraderOrders(traderId: _traderId, type: 'current'),
                repo.getFuturesPositions(),
              ]).then<dynamic>((v) => v)
            : Future<dynamic>.value(null),
        _traderId.isNotEmpty // [5] 历史带单
            ? repo
                .getTraderOrders(traderId: _traderId, type: 'history')
                .then<dynamic>((v) => v)
            : Future<dynamic>.value(null),
      ]);

      final info = results[0] as Map<String, dynamic>?;
      final tags = results[1] as List<Map<String, dynamic>>;
      final followerCount = results[2] as int;
      final followersList = results[3] as List<Map<String, dynamic>>;

      // 当前带单：enriching with futures position data
      List<Map<String, dynamic>> enrichedCurrentOrders = [];
      if (_traderId.isNotEmpty && results[4] != null) {
        final pair = results[4] as List;
        final currentRaw = pair[0] as List<Map<String, dynamic>>;
        final futuresPos = pair[1] as List<Map<String, dynamic>>;
        final futuresMap = <String, Map<String, dynamic>>{
          for (final p in futuresPos)
            if (p['id']?.toString().isNotEmpty == true) p['id'].toString(): p,
        };
        enrichedCurrentOrders = currentRaw.map((o) {
          final pid = o['positionId']?.toString() ??
              o['traderPositionId']?.toString() ??
              '';
          final fp = pid.isNotEmpty ? futuresMap[pid] : null;
          if (fp == null) return o;
          final coin = fp['coin'] as Map<String, dynamic>? ?? {};
          final pricePrecision = (coin['coinScale'] as num?)?.toInt() ?? 2;
          return <String, dynamic>{
            ...o,
            'marginRate': fp['marginRate'],
            if (fp['estimatedBlastPrice'] != null)
              'estimatedBlastPrice': fp['estimatedBlastPrice'],
            '_pricePrecision': pricePrecision,
          };
        }).toList();
      }

      final historyOrders = _traderId.isNotEmpty && results[5] != null
          ? results[5] as List<Map<String, dynamic>>
          : <Map<String, dynamic>>[];

      // 带单合约列表（与交易员详情页一致，标题走 l10n.tradingContracts）
      List<String> traderSymbols = [];
      if (_traderId.isNotEmpty) {
        try {
          final symRaw = await repo.getTraderSymbols(_traderId);
          traderSymbols = symRaw
              .map((s) =>
                  s['symbolName']?.toString() ?? s['symbol']?.toString() ?? '')
              .where((n) => n.isNotEmpty)
              .toList()
            ..sort();
        } catch (_) {}
      }

      if (context.mounted) {
        setState(() {
          _traderInfo = info;
          _tags = tags;
          _followerCount = followerCount;
          // 跟单用户
          _followers = followersList;
          _loadingFollowers = false;
          _followersLoaded = true;
          _followersHasMore = followersList.length >= _followersPageSize;
          // 当前带单
          _currentOrders = enrichedCurrentOrders;
          _loadingCurrentOrders = false;
          _currentOrdersLoaded = true;
          // 历史带单
          _historyOrders = historyOrders;
          _loadingHistoryOrders = false;
          _historyOrdersLoaded = true;
          _traderSymbols = traderSymbols;
          // 最后关掉骨架
          _loadingProfile = false;
        });
      }
    } catch (e) {
      if (context.mounted) setState(() => _loadingProfile = false);
    }
  }

  /// 仅刷新交易员信息卡（昵称/签名等），不重新加载订单列表
  Future<void> _refreshProfile() async {
    try {
      final repo = ref.read(copyTradingRepositoryProvider);
      final followerInfo = await repo.getFollowerInfo();
      final traderId = followerInfo?['id']?.toString() ?? '';
      if (traderId.isNotEmpty) {
        final info = await repo.getTraderInfo(traderId);
        List<String> sym = [];
        try {
          final symRaw = await repo.getTraderSymbols(traderId);
          sym = symRaw
              .map((s) =>
                  s['symbolName']?.toString() ?? s['symbol']?.toString() ?? '')
              .where((n) => n.isNotEmpty)
              .toList()
            ..sort();
        } catch (_) {}
        if (context.mounted) {
          setState(() {
            _traderId = traderId;
            _traderInfo = info;
            _traderSymbols = sym;
          });
        }
      }
    } catch (_) {}
  }

  void _onTabChanged(int index) {
    switch (index) {
      case 0:
        if (!_followersLoaded) _loadFollowers();
        break;
      case 1:
        if (!_currentOrdersLoaded) _loadCurrentOrders();
        break;
      case 2:
        if (!_historyOrdersLoaded) _loadHistoryOrders();
        break;
    }
  }

  Future<void> _loadFollowers() async {
    if (!context.mounted) return;
    setState(() {
      _loadingFollowers = true;
      _followersPage = 1;
      _followersHasMore = true;
    });
    try {
      final list = await ref
          .read(copyTradingRepositoryProvider)
          .getMyFollowers(page: 1, pageSize: _followersPageSize);
      if (context.mounted)
        setState(() {
          _followers = list;
          _loadingFollowers = false;
          _followersLoaded = true;
          _followersHasMore = list.length >= _followersPageSize;
        });
    } catch (_) {
      if (context.mounted)
        setState(() {
          _loadingFollowers = false;
          _followersLoaded = true;
        });
    }
  }

  Future<void> _loadMoreFollowers() async {
    if (!_followersHasMore || _followersLoadingMore || _loadingFollowers)
      return;
    final nextPage = _followersPage + 1;
    if (!context.mounted) return;
    setState(() => _followersLoadingMore = true);
    try {
      final list = await ref
          .read(copyTradingRepositoryProvider)
          .getMyFollowers(page: nextPage, pageSize: _followersPageSize);
      if (context.mounted)
        setState(() {
          _followers = [..._followers, ...list];
          _followersPage = nextPage;
          _followersHasMore = list.length >= _followersPageSize;
          _followersLoadingMore = false;
        });
    } catch (_) {
      if (context.mounted) setState(() => _followersLoadingMore = false);
    }
  }

  Future<void> _loadCurrentOrders() async {
    if (_traderId.isEmpty) {
      if (context.mounted)
        setState(() {
          _loadingCurrentOrders = false;
          _currentOrdersLoaded = true;
        });
      return;
    }
    if (!context.mounted) return;
    setState(() => _loadingCurrentOrders = true);
    try {
      final repo = ref.read(copyTradingRepositoryProvider);
      final results = await Future.wait([
        repo.getTraderOrders(traderId: _traderId, type: 'current'),
        repo.getFuturesPositions(),
      ]);
      final list = results[0];
      final futuresPositions = results[1];

      // Build positionId → futures position map for cross-referencing
      final futuresMap = <String, Map<String, dynamic>>{
        for (final p in futuresPositions)
          if (p['id']?.toString().isNotEmpty == true) p['id'].toString(): p,
      };

      // Enrich each copy order with marginRate from the matching futures position
      final enriched = list.map((o) {
        final pid = o['positionId']?.toString() ??
            o['traderPositionId']?.toString() ??
            '';
        final fp = pid.isNotEmpty ? futuresMap[pid] : null;
        if (fp == null) return o;

        final coin = fp['coin'] as Map<String, dynamic>? ?? {};
        final pricePrecision = (coin['coinScale'] as num?)?.toInt() ?? 2;
        return <String, dynamic>{
          ...o,
          'marginRate': fp['marginRate'],
          if (fp['estimatedBlastPrice'] != null)
            'estimatedBlastPrice': fp['estimatedBlastPrice'],
          '_pricePrecision': pricePrecision,
        };
      }).toList();

      if (context.mounted) {
        setState(() {
          _currentOrders = enriched;
          _loadingCurrentOrders = false;
          _currentOrdersLoaded = true;
        });
      }
    } catch (_) {
      if (context.mounted)
        setState(() {
          _loadingCurrentOrders = false;
          _currentOrdersLoaded = true;
        });
    }
  }

  Future<void> _loadHistoryOrders() async {
    if (_traderId.isEmpty) {
      if (context.mounted)
        setState(() {
          _loadingHistoryOrders = false;
          _historyOrdersLoaded = true;
        });
      return;
    }
    if (!context.mounted) return;
    setState(() => _loadingHistoryOrders = true);
    try {
      final list = await ref
          .read(copyTradingRepositoryProvider)
          .getTraderOrders(traderId: _traderId, type: 'history');
      if (context.mounted)
        setState(() {
          _historyOrders = list;
          _loadingHistoryOrders = false;
          _historyOrdersLoaded = true;
        });
    } catch (_) {
      if (context.mounted)
        setState(() {
          _loadingHistoryOrders = false;
          _historyOrdersLoaded = true;
        });
    }
  }

  Future<void> _removeFollower(String followId) async {
    final confirmed = await _showRemoveConfirmDialog();
    if (!confirmed || !context.mounted) return;
    try {
      await ref.read(copyTradingRepositoryProvider).removeFollower(followId);
      if (context.mounted) {
        setState(() {
          _followers.removeWhere((f) => f['id']?.toString() == followId);
          if (_followerCount != null && _followerCount! > 0) {
            _followerCount = _followerCount! - 1;
          }
        });
        showTopToast(context,
            message: AppLocalizations.of(context)!.removedSuccess,
            backgroundColor: AppColors.rise);
      }
    } catch (e) {
      if (context.mounted) {
        showTopToast(context,
            message: extractErrorMessage(e), backgroundColor: AppColors.fall);
      }
    }
  }

  Future<bool> _showRemoveConfirmDialog() async {
    final cs = Theme.of(context).colorScheme;
    final l10n = AppLocalizations.of(context)!;
    return await showDialog<bool>(
          context: context,
          builder: (ctx) => Dialog(
            backgroundColor: cs.surface,
            shape:
                RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const SizedBox(height: 24),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  child: Text(
                    l10n.confirmRemoveFollower,
                    style: TextStyle(
                        color: cs.onSurface,
                        fontSize: 17,
                        fontWeight: FontWeight.w600),
                  ),
                ),
                const SizedBox(height: 12),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  child: Text(
                    l10n.removeFollowerMsg,
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(180), fontSize: 14),
                    textAlign: TextAlign.center,
                  ),
                ),
                const SizedBox(height: 24),
                Divider(
                    height: 1,
                    thickness: 1,
                    color: cs.outlineVariant.withAlpha(60)),
                // 两个按钮各占一半
                IntrinsicHeight(
                  child: Row(
                    children: [
                      Expanded(
                        child: GestureDetector(
                          onTap: () => Navigator.of(ctx).pop(false),
                          child: Container(
                            height: 52,
                            decoration: BoxDecoration(
                              borderRadius: const BorderRadius.only(
                                  bottomLeft: Radius.circular(16)),
                            ),
                            alignment: Alignment.center,
                            child: Text(l10n.cancelLabel,
                                style: TextStyle(
                                    color: cs.onSurface.withAlpha(153),
                                    fontSize: 16)),
                          ),
                        ),
                      ),
                      VerticalDivider(
                          width: 1,
                          thickness: 1,
                          color: cs.outlineVariant.withAlpha(60)),
                      Expanded(
                        child: GestureDetector(
                          onTap: () => Navigator.of(ctx).pop(true),
                          child: Container(
                            height: 52,
                            decoration: const BoxDecoration(
                              color: AppColors.brand,
                              borderRadius: BorderRadius.only(
                                  bottomRight: Radius.circular(16)),
                            ),
                            alignment: Alignment.center,
                            child: Text(l10n.confirm,
                                style: const TextStyle(
                                    color: Colors.white,
                                    fontSize: 16,
                                    fontWeight: FontWeight.w600)),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ) ??
        false;
  }

  /// 格式化数字，向下截断（不四舍五入，对应 Android RoundingMode.DOWN）
  String _fmt(dynamic v, {int decimals = 2}) {
    if (v == null) return '--';
    final str = v.toString().trim();
    if (str.isEmpty) return '--';
    final d = double.tryParse(str);
    if (d == null) return str;
    final isNeg = str.startsWith('-');
    final absStr = isNeg ? str.substring(1) : str;
    final dotIdx = absStr.indexOf('.');
    String truncated;
    if (decimals == 0 || dotIdx < 0) {
      truncated = dotIdx < 0 ? absStr : absStr.substring(0, dotIdx);
    } else {
      final frac = absStr.substring(dotIdx + 1);
      truncated =
          '${absStr.substring(0, dotIdx)}.${frac.length >= decimals ? frac.substring(0, decimals) : frac.padRight(decimals, '0')}';
    }
    final parts = truncated.split('.');
    final intFmt = parts[0].replaceAllMapped(
        RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'), (m) => '${m[1]},');
    final result = decimals > 0
        ? '$intFmt.${parts.length > 1 ? parts[1] : '0' * decimals}'
        : intFmt;
    return isNeg ? '-$result' : result;
  }

  Widget _buildTradingContractsStrip(ColorScheme cs) {
    if (_traderSymbols.isEmpty) {
      return const SizedBox.shrink();
    }
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final l10n = AppLocalizations.of(context)!;
    return Container(
      margin: const EdgeInsets.fromLTRB(16, 0, 16, 8),
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBg,
        borderRadius: BorderRadius.circular(12),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          GestureDetector(
            onTap: () => setState(() => _symbolExpanded = !_symbolExpanded),
            behavior: HitTestBehavior.opaque,
            child: Row(
              children: [
                Text(
                  l10n.tradingContracts,
                  style: TextStyle(
                    color: cs.onSurface,
                    fontSize: 14,
                    fontWeight: FontWeight.w700,
                  ),
                ),
                const Spacer(),
                Icon(
                  _symbolExpanded
                      ? Icons.keyboard_arrow_up
                      : Icons.keyboard_arrow_down,
                  color: cs.onSurface.withAlpha(153),
                  size: 20,
                ),
              ],
            ),
          ),
          if (_symbolExpanded) ...[
            const SizedBox(height: 10),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: _traderSymbols.map((sym) {
                return Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 14, vertical: 7),
                  decoration: BoxDecoration(
                    color: AppColors.brand.withValues(alpha: 0.12),
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(
                      color: AppColors.brand.withValues(alpha: 0.6),
                      width: 1.5,
                    ),
                  ),
                  child: Text(
                    sym,
                    style: const TextStyle(
                      color: AppColors.brand,
                      fontSize: 13,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                );
              }).toList(),
            ),
          ],
        ],
      ),
    );
  }

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

    final l10n = AppLocalizations.of(context)!;
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios, size: 18),
          onPressed: () => context.pop(),
        ),
        title: Text(l10n.myTrades,
            style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600)),
        actions: [
          IconButton(
            icon: Icon(Icons.settings_outlined, color: cs.onSurface),
            onPressed: () => context.push('/trader-settings').then((_) {
              if (context.mounted) _refreshProfile();
            }),
          ),
        ],
      ),
      body: _loadingProfile
          ? const _MyTradesFullSkeleton()
          : Column(
              children: [
                // ── 交易员信息卡 ──────────────────────────
                _ProfileCard(traderInfo: _traderInfo, fmt: _fmt, tags: _tags),
                _buildTradingContractsStrip(cs),
                // ── Tab 栏 ────────────────────────────────
                Container(
                  decoration: BoxDecoration(
                    border: Border(
                        bottom: BorderSide(
                            color: cs.outlineVariant.withAlpha(60), width: 1)),
                  ),
                  child: TabBar(
                    controller: _tabController,
                    indicator: StretchTabIndicator(
                      controller: _tabController,
                      color: AppColors.brand,
                    ),
                    indicatorSize: TabBarIndicatorSize.tab,
                    dividerColor: Colors.transparent,
                    tabs: [
                      Tab(
                          text: (_followerCount != null && _followerCount! > 0)
                              ? '${l10n.followersTab}($_followerCount)'
                              : l10n.followersTab),
                      Tab(text: l10n.currentCopyOrders),
                      Tab(text: l10n.historyCopyOrders),
                    ],
                  ),
                ),
                // ── Tab 内容（PageView 支持左右滑动）─────────────
                Expanded(
                  child: PageView(
                    controller: _pageController,
                    physics: const BouncingScrollPhysics(
                      parent: AlwaysScrollableScrollPhysics(),
                    ),
                    onPageChanged: (index) {
                      if (_tabController.indexIsChanging) return;
                      _tabController.index = index;
                    },
                    children: [
                      _FollowersTab(
                        loading: _loadingFollowers,
                        loaded: _followersLoaded,
                        followers: _followers,
                        hasMore: _followersHasMore,
                        loadingMore: _followersLoadingMore,
                        onRemove: _removeFollower,
                        fmt: _fmt,
                        onRefresh: _loadFollowers,
                        onLoadMore: _loadMoreFollowers,
                      ),
                      _OrdersTab(
                        loading: _loadingCurrentOrders,
                        loaded: _currentOrdersLoaded,
                        orders: _currentOrders,
                        onLoad: _loadCurrentOrders,
                        fmt: _fmt,
                        onRefresh: _loadCurrentOrders,
                      ),
                      _OrdersTab(
                        loading: _loadingHistoryOrders,
                        loaded: _historyOrdersLoaded,
                        orders: _historyOrders,
                        onLoad: _loadHistoryOrders,
                        fmt: _fmt,
                        isHistory: true,
                        onRefresh: _loadHistoryOrders,
                      ),
                    ],
                  ),
                ),
              ],
            ),
    );
  }
}

// ── 交易员信息卡 ──────────────────────────────────────────

class _ProfileCard extends StatelessWidget {
  const _ProfileCard(
      {required this.traderInfo, required this.fmt, this.tags = const []});

  final Map<String, dynamic>? traderInfo;
  final String Function(dynamic, {int decimals}) fmt;
  final List<Map<String, dynamic>> tags;

  String get _nickname => traderInfo?['nickname']?.toString() ?? '--';
  String get _description => traderInfo?['description']?.toString() ?? '';
  String get _levelName => traderInfo?['levelName']?.toString() ?? '';
  String? get _avatarUrl => traderInfo == null
      ? null
      : resolvedAvatarUrlFromRecord(Map<String, dynamic>.from(traderInfo!));
  String get _followingCurrent => traderInfo?['following']?.toString() ?? '--';
  String get _followingMax => traderInfo?['maxFollow']?.toString() ?? '--';
  String get _joinDays =>
      traderInfo?['registerDays']?.toString() ??
      traderInfo?['settledDays']?.toString() ??
      '--';
  String get _moneyStrength => traderInfo?['moneyStrength']?.toString() ?? '--';
  String get _cumulativeProfit =>
      fmt(traderInfo?['profitAmount'] ?? traderInfo?['totalFollowProfit']);
  String get _cumulativeFollowers =>
      traderInfo?['followCustomer']?.toString() ?? '--';
  String get _totalTradeDays => traderInfo?['tradingDays']?.toString() ?? '--';

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final letter = _nickname.isNotEmpty ? _nickname[0].toUpperCase() : 'T';

    return Container(
      color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 头像 + 昵称 + 描述
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              _Avatar(
                  letter: letter, levelName: _levelName, avatarUrl: _avatarUrl),
              const SizedBox(width: 12),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(_nickname,
                        style: TextStyle(
                            color: cs.onSurface,
                            fontSize: 16,
                            fontWeight: FontWeight.w700)),
                    if (_description.isNotEmpty)
                      Padding(
                        padding: const EdgeInsets.only(top: 4),
                        child: Text(
                          _description,
                          style: TextStyle(
                              color: cs.onSurface.withAlpha(153), fontSize: 13),
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    if (tags.isNotEmpty)
                      Padding(
                        padding: const EdgeInsets.only(top: 8),
                        child: SingleChildScrollView(
                          scrollDirection: Axis.horizontal,
                          child: Row(
                            children: tags.map((tag) {
                              final name = tag['name']?.toString() ?? '';
                              if (name.isEmpty) return const SizedBox.shrink();
                              return Padding(
                                padding: const EdgeInsets.only(right: 6),
                                child: Container(
                                  padding: const EdgeInsets.symmetric(
                                      horizontal: 10, vertical: 3),
                                  decoration: BoxDecoration(
                                    color: AppColors.tagBlueBg,
                                    borderRadius: BorderRadius.circular(20),
                                  ),
                                  child: Text(
                                    name,
                                    style: const TextStyle(
                                        color: AppColors.tagBlue, fontSize: 12),
                                  ),
                                ),
                              );
                            }).toList(),
                          ),
                        ),
                      ),
                  ],
                ),
              ),
            ],
          ),
          const SizedBox(height: 16),
          // 统计网格：浅灰色背景圆角卡片（无边框）
          Builder(builder: (context) {
            final l10n = AppLocalizations.of(context)!;
            return Container(
              padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
              decoration: BoxDecoration(
                color: cs.onSurface.withAlpha(10),
                borderRadius: BorderRadius.circular(10),
              ),
              child: Column(
                children: [
                  // 第1行
                  Row(
                    children: [
                      _StatCell(
                        label: l10n.currentFollowersLabel,
                        value: _followingCurrent,
                        valueSuffix: ' / $_followingMax',
                      ),
                      _StatCell(
                          label: l10n.settledDaysTitle,
                          value: _joinDays,
                          alignCenter: true),
                      _StatCell(
                          label: l10n.fundStrength,
                          value: '$_moneyStrength USDT',
                          alignEnd: true),
                    ],
                  ),
                  const SizedBox(height: 12),
                  // 第2行
                  Row(
                    children: [
                      _StatCell(
                          label: l10n.cumCopyProfitUsdt,
                          value: _cumulativeProfit),
                      _StatCell(
                          label: l10n.cumFollowerCount,
                          value: _cumulativeFollowers,
                          alignCenter: true),
                      _StatCell(
                          label: l10n.cumTradingDays,
                          value: _totalTradeDays,
                          alignEnd: true),
                    ],
                  ),
                ],
              ),
            );
          }),
        ],
      ),
    );
  }
}

class _Avatar extends StatelessWidget {
  const _Avatar(
      {required this.letter, required this.levelName, this.avatarUrl});

  final String letter;
  final String levelName;
  final String? avatarUrl;

  @override
  Widget build(BuildContext context) {
    final hasAvatar = avatarUrl != null && avatarUrl!.isNotEmpty;
    return SizedBox(
      width: 54,
      height: 64,
      child: Stack(
        alignment: Alignment.topCenter,
        children: [
          if (hasAvatar)
            ClipOval(
              child: Image.network(
                avatarUrl!,
                width: 54,
                height: 54,
                fit: BoxFit.cover,
                errorBuilder: (_, __, ___) => _LetterAvatar(letter: letter),
              ),
            )
          else
            _LetterAvatar(letter: letter),
          if (levelName.isNotEmpty)
            Positioned(
              bottom: 0,
              child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
                decoration: BoxDecoration(
                  color: AppColors.brand,
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Text(levelName,
                    style: const TextStyle(
                        color: Colors.black,
                        fontSize: 10,
                        fontWeight: FontWeight.w700)),
              ),
            ),
        ],
      ),
    );
  }
}

class _LetterAvatar extends StatelessWidget {
  const _LetterAvatar({required this.letter});
  final String letter;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 54,
      height: 54,
      decoration:
          const BoxDecoration(color: Color(0xFF5B7BE8), shape: BoxShape.circle),
      child: Center(
          child: Text(letter,
              style: const TextStyle(
                  color: Colors.white,
                  fontSize: 22,
                  fontWeight: FontWeight.w700))),
    );
  }
}

class _StatCell extends StatelessWidget {
  const _StatCell(
      {required this.label,
      required this.value,
      this.valueSuffix,
      this.alignEnd = false,
      this.alignCenter = false});

  final String label;
  final String value;
  final String? valueSuffix; // 灰色后缀，如 " / 300"
  final bool alignEnd;
  final bool alignCenter;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final align = alignEnd
        ? CrossAxisAlignment.end
        : alignCenter
            ? CrossAxisAlignment.center
            : CrossAxisAlignment.start;
    final greyColor = cs.onSurface.withAlpha(120);
    return Expanded(
      child: Column(
        crossAxisAlignment: align,
        children: [
          Text(label, style: TextStyle(color: greyColor, fontSize: 11)),
          const SizedBox(height: 3),
          valueSuffix != null
              ? RichText(
                  text: TextSpan(
                    style: TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.w600,
                        color: cs.onSurface),
                    children: [
                      TextSpan(text: value),
                      TextSpan(
                          text: valueSuffix,
                          style: TextStyle(
                              color: greyColor, fontWeight: FontWeight.w400)),
                    ],
                  ),
                )
              : Text(value,
                  style: TextStyle(
                      color: cs.onSurface,
                      fontSize: 14,
                      fontWeight: FontWeight.w600)),
        ],
      ),
    );
  }
}

// ── 跟单用户 Tab ──────────────────────────────────────────

class _FollowersTab extends StatelessWidget {
  const _FollowersTab({
    required this.loading,
    required this.loaded,
    required this.followers,
    required this.hasMore,
    required this.loadingMore,
    required this.onRemove,
    required this.fmt,
    required this.onRefresh,
    required this.onLoadMore,
  });

  final bool loading;
  final bool loaded;
  final List<Map<String, dynamic>> followers;
  final bool hasMore;
  final bool loadingMore;
  final void Function(String id) onRemove;
  final String Function(dynamic, {int decimals}) fmt;
  final Future<void> Function() onRefresh;
  final VoidCallback onLoadMore;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isLoading = !loaded || (loading && followers.isEmpty);
    return NotificationListener<ScrollNotification>(
      onNotification: (n) {
        if (!isLoading &&
            n is ScrollEndNotification &&
            n.metrics.pixels >= n.metrics.maxScrollExtent - 200) {
          onLoadMore();
        }
        return false;
      },
      child: AppRefreshIndicator(
        onRefresh: onRefresh,
        child: ListView.builder(
          physics: const AlwaysScrollableScrollPhysics(),
          padding: const EdgeInsets.only(bottom: 16),
          itemCount:
              isLoading ? 4 : (followers.isEmpty ? 1 : followers.length + 1),
          itemBuilder: (_, i) {
            if (isLoading) return const _FollowerCardSkeleton();
            if (followers.isEmpty) {
              return SizedBox(
                height: 200,
                child: Center(
                  child: Text(AppLocalizations.of(context)!.noFollowers,
                      style: TextStyle(color: cs.onSurface.withAlpha(100))),
                ),
              );
            }
            if (i >= followers.length) {
              if (loadingMore) {
                return const Padding(
                  padding: EdgeInsets.symmetric(vertical: 16),
                  child: Center(
                      child: CircularProgressIndicator(
                          color: AppColors.brand, strokeWidth: 2)),
                );
              }
              if (!hasMore) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: Center(
                      child: Text(AppLocalizations.of(context)!.noMore,
                          style: TextStyle(
                              color: cs.onSurface.withAlpha(100),
                              fontSize: 12))),
                );
              }
              return const SizedBox(height: 16);
            }
            return _FollowerCard(
                follower: followers[i], onRemove: onRemove, fmt: fmt);
          },
        ),
      ),
    );
  }
}

class _FollowerCard extends StatelessWidget {
  const _FollowerCard(
      {required this.follower, required this.onRemove, required this.fmt});

  final Map<String, dynamic> follower;
  final void Function(String) onRemove;
  final String Function(dynamic, {int decimals}) fmt;

  static const _avatarColors = [
    Color(0xFF5B7BE8),
    Color(0xFFf7931a),
    Color(0xFF9945ff),
    Color(0xFFf3ba2f),
    Color(0xFF2775ca),
    Color(0xFF00aae4),
  ];

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final uid = follower['id']?.toString() ?? '';
    final nickname = follower['nickname']?.toString() ?? uid;
    final display = nickname.isNotEmpty ? nickname : uid;
    final colorIdx =
        uid.isNotEmpty ? uid.codeUnitAt(0) % _avatarColors.length : 0;
    final letter = display.isNotEmpty ? display[0].toUpperCase() : '?';

    // 跟随人数
    final following = follower['following']?.toString();
    final maxFollow = follower['maxFollow']?.toString();
    final hasFollowInfo = following != null || maxFollow != null;

    return Container(
      margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        borderRadius: BorderRadius.circular(12),
        boxShadow: [
          BoxShadow(
              color: Colors.black.withAlpha(15),
              blurRadius: 8,
              offset: const Offset(0, 2)),
        ],
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 头部：头像 + 昵称+跟随人数 + 移除按钮
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                width: 44,
                height: 44,
                decoration: BoxDecoration(
                    color: _avatarColors[colorIdx], shape: BoxShape.circle),
                child: Center(
                  child: Text(letter,
                      style: const TextStyle(
                          color: Colors.white,
                          fontSize: 18,
                          fontWeight: FontWeight.w700)),
                ),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      display.isNotEmpty
                          ? display
                          : AppLocalizations.of(context)!.copyUser,
                      style: TextStyle(
                          color: cs.onSurface,
                          fontSize: 15,
                          fontWeight: FontWeight.w600),
                    ),
                    if (hasFollowInfo) ...[
                      const SizedBox(height: 4),
                      Row(
                        children: [
                          Icon(Icons.people_outline,
                              size: 13, color: cs.onSurface.withAlpha(120)),
                          const SizedBox(width: 4),
                          Text(
                            maxFollow != null
                                ? AppLocalizations.of(context)!
                                    .followersMaxLabel(
                                        following ?? '--', maxFollow)
                                : AppLocalizations.of(context)!
                                    .followersCountLabel(following ?? '--'),
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(153),
                                fontSize: 12),
                          ),
                        ],
                      ),
                    ],
                  ],
                ),
              ),
              const SizedBox(width: 8),
              OutlinedButton(
                onPressed: () => onRemove(uid),
                style: OutlinedButton.styleFrom(
                  side: BorderSide(color: cs.onSurface, width: 1.5),
                  foregroundColor: cs.onSurface,
                  padding:
                      const EdgeInsets.symmetric(horizontal: 14, vertical: 6),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20)),
                  minimumSize: Size.zero,
                  tapTargetSize: MaterialTapTargetSize.shrinkWrap,
                ),
                child: Text(AppLocalizations.of(context)!.remove,
                    style: const TextStyle(
                        fontSize: 12, fontWeight: FontWeight.w500)),
              ),
            ],
          ),
          const SizedBox(height: 12),
          Divider(
              height: 1,
              thickness: 0.5,
              color: cs.outlineVariant.withAlpha(80)),
          const SizedBox(height: 12),
          // 底部统计行（含竖向分隔线）
          Builder(builder: (context) {
            final l10n = AppLocalizations.of(context)!;
            return IntrinsicHeight(
              child: Row(
                children: [
                  _FollowerStat(
                      label: l10n.accountEquityUsdt,
                      value:
                          fmt(follower['balance'] ?? follower['totalBalance'])),
                  VerticalDivider(
                      width: 1,
                      thickness: 0.8,
                      color: Colors.grey.withAlpha(100)),
                  _FollowerStat(
                      label: l10n.cumProfitShareUsdt,
                      value: fmt(follower['totalProfitSharing']),
                      alignCenter: true),
                  VerticalDivider(
                      width: 1,
                      thickness: 0.8,
                      color: Colors.grey.withAlpha(100)),
                  _FollowerStat(
                      label: l10n.lastProfitShare,
                      value: fmt(follower['lastProfitSharing']),
                      alignEnd: true),
                ],
              ),
            );
          }),
          // 跟随时间
          Builder(builder: (context) {
            final followTime = follower['followTime']?.toString() ?? '';
            if (followTime.isEmpty) return const SizedBox.shrink();
            return Padding(
              padding: const EdgeInsets.only(top: 8),
              child: Row(
                children: [
                  Icon(Icons.access_time,
                      size: 12, color: cs.onSurface.withAlpha(100)),
                  const SizedBox(width: 4),
                  Text(
                    '${AppLocalizations.of(context)!.followerFollowTime}：$followTime',
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(153), fontSize: 12),
                  ),
                ],
              ),
            );
          }),
        ],
      ),
    );
  }
}

class _FollowerStat extends StatelessWidget {
  const _FollowerStat(
      {required this.label,
      required this.value,
      this.alignEnd = false,
      this.alignCenter = false});

  final String label;
  final String value;
  final bool alignEnd;
  final bool alignCenter;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final align = alignEnd
        ? CrossAxisAlignment.end
        : alignCenter
            ? CrossAxisAlignment.center
            : CrossAxisAlignment.start;
    return Expanded(
      child: Column(
        crossAxisAlignment: align,
        children: [
          Text(label,
              style:
                  TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 11)),
          const SizedBox(height: 2),
          Text(value,
              style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 13,
                  fontWeight: FontWeight.w600)),
        ],
      ),
    );
  }
}

// ── 带单仓位 Tab ──────────────────────────────────────────

class _OrdersTab extends StatelessWidget {
  const _OrdersTab({
    required this.loading,
    required this.loaded,
    required this.orders,
    required this.onLoad,
    required this.fmt,
    required this.onRefresh,
    this.isHistory = false,
  });

  final bool loading;
  final bool loaded;
  final List<Map<String, dynamic>> orders;
  final VoidCallback onLoad;
  final String Function(dynamic, {int decimals}) fmt;
  final Future<void> Function() onRefresh;
  final bool isHistory;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isLoading = !loaded || (loading && orders.isEmpty);
    return AppRefreshIndicator(
      onRefresh: onRefresh,
      child: ListView.builder(
        physics: const AlwaysScrollableScrollPhysics(),
        padding: const EdgeInsets.only(bottom: 16),
        itemCount: isLoading ? 4 : (orders.isEmpty ? 1 : orders.length),
        itemBuilder: (_, i) {
          if (isLoading) return const _OrderCardSkeleton();
          if (orders.isEmpty) {
            return SizedBox(
              height: 200,
              child: Center(
                child: Text(
                  isHistory
                      ? AppLocalizations.of(context)!.noHistoryTrades
                      : AppLocalizations.of(context)!.noCurrentTrades,
                  style: TextStyle(color: cs.onSurface.withAlpha(100)),
                ),
              ),
            );
          }
          if (i < 0 || i >= orders.length) return const SizedBox.shrink();
          return _OrderCard(order: orders[i], fmt: fmt, isHistory: isHistory);
        },
      ),
    );
  }
}

class _OrderCard extends StatelessWidget {
  const _OrderCard(
      {required this.order, required this.fmt, this.isHistory = false});

  final Map<String, dynamic> order;
  final String Function(dynamic, {int decimals}) fmt;
  final bool isHistory;

  /// 按交易对价格精度截断（RoundingMode.DOWN），去除尾部零，与安卓 coinScale 逻辑一致
  String _fmtWithScale(double v, int scale) {
    if (scale < 0) scale = 0;
    final factor = scale == 0
        ? 1.0
        : List.generate(scale, (_) => 10).fold(1.0, (a, b) => a * b);
    final truncated = v >= 0
        ? (v * factor).floorToDouble() / factor
        : (v * factor).ceilToDouble() / factor;
    String s = truncated.toStringAsFixed(scale);
    if (s.contains('.')) {
      s = s.replaceAll(RegExp(r'0+$'), '').replaceAll(RegExp(r'\.$'), '');
    }
    return s.isEmpty ? '0' : s;
  }

  String _fmtTimestamp(dynamic ts) {
    if (ts == null) return '--';
    final ms = int.tryParse(ts.toString());
    if (ms == null) return ts.toString();
    // 后台时间戳为 UTC 毫秒，统一转为 UTC+8（北京时间）展示
    final dt = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: true)
        .add(const Duration(hours: 8));
    final y = dt.year;
    final mo = dt.month.toString().padLeft(2, '0');
    final d = dt.day.toString().padLeft(2, '0');
    final h = dt.hour.toString().padLeft(2, '0');
    final mi = dt.minute.toString().padLeft(2, '0');
    final s = dt.second.toString().padLeft(2, '0');
    return '$y-$mo-$d $h:$mi:$s';
  }

  /// 数量字段专用：4位小数、向下截断、去尾零（对应 Android textDigital=4 + stripTrailingZeros）
  String _fmtQty(dynamic v) {
    final s = fmt(v, decimals: 4);
    if (s == '--' || !s.contains('.')) return s;
    return s.replaceAll(RegExp(r'0+$'), '').replaceAll(RegExp(r'\.$'), '');
  }

  @override
  Widget build(BuildContext context) {
    return isHistory ? _buildHistory(context) : _buildCurrent(context);
  }

  // ── 当前带单卡片 ────────────────────────────────────────
  Widget _buildCurrent(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final l10n = AppLocalizations.of(context)!;
    final symbol = order['symbol']?.toString() ?? '--';
    // 提取基础币种：BTC/USDT → BTC
    final baseCoin = symbol.contains('/') ? symbol.split('/')[0] : symbol;
    final isLong = (order['direction']?.toString() ?? '0') == '0';
    final leverage = order['leverage']?.toString() ?? '--';

    final profit = double.tryParse(order['profit']?.toString() ?? '0') ?? 0.0;
    final profitColor = profit >= 0 ? AppColors.rise : AppColors.fall;
    final profitRateRaw =
        double.tryParse(order['profitRate']?.toString() ?? '0') ?? 0.0;
    final profitRateStr =
        '${profitRateRaw >= 0 ? '+' : ''}${profitRateRaw.toStringAsFixed(2)}%';
    final profitRateColor =
        profitRateRaw >= 0 ? AppColors.rise : AppColors.fall;

    final openTime = _fmtTimestamp(order['openTime']);
    final positionId = order['positionId']?.toString() ??
        order['traderPositionId']?.toString() ??
        '--';

    // ── 保证金比率：参照合约持仓页公式 principalAmount / (totalPosition * currentPrice) * 100
    // 若 API 直接返回 marginRate 则优先使用
    final principalAmount =
        double.tryParse(order['principalAmount']?.toString() ?? '0') ?? 0.0;
    final apiMarginRate =
        double.tryParse(order['marginRate']?.toString() ?? '');
    final currentPrice =
        double.tryParse(order['currentPrice']?.toString() ?? '0') ?? 0.0;
    final qty =
        double.tryParse(order['totalPosition']?.toString() ?? '0') ?? 0.0;
    String marginRatioStr;
    if (apiMarginRate != null && apiMarginRate > 0) {
      marginRatioStr = '${apiMarginRate.toStringAsFixed(2)}%';
    } else if (qty > 0 && currentPrice > 0) {
      marginRatioStr =
          '${(principalAmount / (qty * currentPrice) * 100).toStringAsFixed(2)}%';
    } else {
      marginRatioStr = '--';
    }

    // ── 强平价格：按交易对价格精度（coinScale）截断显示，与安卓合约持仓页保持一致
    final pricePrecision = (order['_pricePrecision'] as int?) ?? 2;
    String liquidationPriceStr = '--';
    final blastVal =
        double.tryParse(order['estimatedBlastPrice']?.toString() ?? '');
    if (blastVal != null && blastVal > 0) {
      liquidationPriceStr = _fmtWithScale(blastVal, pricePrecision);
    }

    return Container(
      margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        borderRadius: BorderRadius.circular(12),
        border: isDark
            ? null
            : Border.all(color: AppColors.lightBorder, width: 0.5),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 标题行
          Row(
            children: [
              Text(symbol,
                  style: TextStyle(
                      color: cs.onSurface,
                      fontSize: 15,
                      fontWeight: FontWeight.w700)),
              const SizedBox(width: 4),
              Text(l10n.perpetual,
                  style: TextStyle(color: cs.onSurface, fontSize: 13)),
              const SizedBox(width: 8),
              _Badge(
                  text: isLong ? l10n.openLong : l10n.openShort,
                  color: isLong ? AppColors.rise : AppColors.fall),
              const SizedBox(width: 6),
              _Badge(
                  text: l10n.crossMargin, color: cs.onSurface.withAlpha(120)),
              const SizedBox(width: 6),
              _Badge(text: '${leverage}X', color: cs.onSurface.withAlpha(120)),
            ],
          ),
          const SizedBox(height: 12),
          // 未实现盈亏（大字）+ 收益率
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(l10n.unrealizedPnlUsdt,
                        style: TextStyle(
                            color: cs.onSurface.withAlpha(120), fontSize: 11)),
                    const SizedBox(height: 3),
                    Text('${profit >= 0 ? '+' : ''}${fmt(profit)}',
                        style: TextStyle(
                            color: profitColor,
                            fontSize: 22,
                            fontWeight: FontWeight.w700)),
                  ],
                ),
              ),
              Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(l10n.returnRate,
                      style: TextStyle(
                          color: cs.onSurface.withAlpha(120), fontSize: 11)),
                  const SizedBox(height: 3),
                  Text(profitRateStr,
                      style: TextStyle(
                          color: profitRateColor,
                          fontSize: 14,
                          fontWeight: FontWeight.w600)),
                ],
              ),
            ],
          ),
          const SizedBox(height: 12),
          const Divider(height: 1),
          const SizedBox(height: 10),
          Row(
            children: [
              _OrderStat(
                  label: l10n.positionSizeWithCoin(baseCoin),
                  value: _fmtQty(order['totalPosition'])),
              _OrderStat(
                  label: l10n.marginUsdt,
                  value: fmt(principalAmount),
                  alignCenter: true),
              _OrderStat(
                  label: l10n.marginRatio,
                  value: marginRatioStr,
                  alignEnd: true),
            ],
          ),
          const SizedBox(height: 10),
          Row(
            children: [
              _OrderStat(
                  label: l10n.openAvgPriceUsdt, value: fmt(order['openPrice'])),
              _OrderStat(
                  label: l10n.currentPriceUsdt,
                  value: fmt(order['currentPrice']),
                  alignCenter: true),
              _OrderStat(
                  label: l10n.liqPriceUsdt,
                  value: liquidationPriceStr,
                  alignEnd: true),
            ],
          ),
          const SizedBox(height: 10),
          const Divider(height: 1),
          const SizedBox(height: 8),
          Row(
            children: [
              Expanded(
                child: Text(l10n.openTimeWithValue(openTime),
                    style: TextStyle(
                        color: cs.onSurface.withAlpha(120), fontSize: 11)),
              ),
              GestureDetector(
                onTap: () {
                  Clipboard.setData(ClipboardData(text: positionId));
                  showTopToast(context,
                      message: l10n.positionIdCopied,
                      backgroundColor: AppColors.rise);
                },
                child: Padding(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 4, vertical: 6),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text('${l10n.positionIdPrefix}$positionId',
                          style: TextStyle(
                              color: cs.onSurface.withAlpha(120),
                              fontSize: 11)),
                      const SizedBox(width: 4),
                      Icon(Icons.content_copy,
                          size: 14, color: cs.onSurface.withAlpha(120)),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }

  // ── 历史带单卡片 ────────────────────────────────────────
  Widget _buildHistory(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final l10n = AppLocalizations.of(context)!;
    final symbol = order['symbol']?.toString() ?? '--';
    final baseCoin = symbol.contains('/') ? symbol.split('/')[0] : symbol;
    final isLong = (order['direction']?.toString() ?? '0') == '0';
    final leverage = order['leverage']?.toString() ?? '--';

    final profit = double.tryParse(order['profit']?.toString() ?? '0') ?? 0.0;
    final profitColor = profit >= 0 ? AppColors.rise : AppColors.fall;
    final profitRateRaw =
        double.tryParse(order['profitRate']?.toString() ?? '0') ?? 0.0;
    final profitRateStr =
        '${profitRateRaw >= 0 ? '+' : ''}${profitRateRaw.toStringAsFixed(2)}%';
    final profitRateColor =
        profitRateRaw >= 0 ? AppColors.rise : AppColors.fall;

    final openTime = _fmtTimestamp(order['openTime']);
    final closeTime = _fmtTimestamp(order['closeTime']);

    final headerBg = cs.onSurface.withAlpha(22);
    final bodyBg = cs.onSurface.withAlpha(8);
    final dividerColor = cs.outlineVariant.withAlpha(80);

    return Container(
      margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        borderRadius: BorderRadius.circular(12),
      ),
      child: ClipRRect(
        borderRadius: BorderRadius.circular(12),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // ── 第一部分：深灰色标题行 ─────────────────────────
            Container(
              color: headerBg,
              padding: const EdgeInsets.fromLTRB(14, 12, 14, 12),
              child: Row(
                children: [
                  Text(symbol,
                      style: TextStyle(
                          color: cs.onSurface,
                          fontSize: 15,
                          fontWeight: FontWeight.w700)),
                  const SizedBox(width: 4),
                  Text(l10n.perpetual,
                      style: TextStyle(color: cs.onSurface, fontSize: 13)),
                  const SizedBox(width: 8),
                  _Badge(
                      text: isLong ? l10n.openLong : l10n.openShort,
                      color: isLong ? AppColors.rise : AppColors.fall),
                  const SizedBox(width: 6),
                  _Badge(
                      text: l10n.crossMargin,
                      color: cs.onSurface.withAlpha(120)),
                  const SizedBox(width: 6),
                  _Badge(
                      text: '${leverage}X', color: cs.onSurface.withAlpha(120)),
                  const Spacer(),
                  GestureDetector(
                    onTap: () => _showShareSheet(context),
                    child: Icon(Icons.share_outlined,
                        size: 18, color: cs.onSurface.withAlpha(120)),
                  ),
                ],
              ),
            ),
            // ── 第二部分：灰色 — 平仓数量 / 已实现盈亏 / 收益率 ──
            Container(
              color: bodyBg,
              padding: const EdgeInsets.fromLTRB(14, 12, 14, 12),
              child: Row(
                children: [
                  _OrderStat(
                      label: l10n.closeSizeWithCoin(baseCoin),
                      value: _fmtQty(order['totalPosition'])),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(l10n.realizedPnlUsdt,
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(120),
                                fontSize: 11)),
                        const SizedBox(height: 2),
                        Text(
                            '${profit >= 0 ? '+' : ''}${_fmtQty(order['profit'])}',
                            style: TextStyle(
                                color: profitColor,
                                fontSize: 15,
                                fontWeight: FontWeight.w700)),
                      ],
                    ),
                  ),
                  Column(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Text(l10n.returnRate,
                          style: TextStyle(
                              color: cs.onSurface.withAlpha(120),
                              fontSize: 11)),
                      const SizedBox(height: 2),
                      Text(profitRateStr,
                          style: TextStyle(
                              color: profitRateColor,
                              fontSize: 14,
                              fontWeight: FontWeight.w600)),
                    ],
                  ),
                ],
              ),
            ),
            // ── 分割线 ─────────────────────────────────────────
            Divider(height: 0.5, thickness: 0.5, color: dividerColor),
            // ── 第三部分：灰色 — 开仓均价 / 平仓均价 ─────────────
            Container(
              color: bodyBg,
              padding: const EdgeInsets.fromLTRB(14, 12, 14, 12),
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(l10n.openAvgPriceUsdt,
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(120),
                                fontSize: 11)),
                        const SizedBox(height: 2),
                        Text(fmt(order['openPrice']),
                            style: TextStyle(
                                color: cs.onSurface,
                                fontSize: 14,
                                fontWeight: FontWeight.w600)),
                        const SizedBox(height: 4),
                        Text(openTime,
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(100),
                                fontSize: 11)),
                      ],
                    ),
                  ),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: [
                        Text(l10n.closeAvgPriceUsdt,
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(120),
                                fontSize: 11)),
                        const SizedBox(height: 2),
                        Text(fmt(order['closePrice']),
                            style: TextStyle(
                                color: cs.onSurface,
                                fontSize: 14,
                                fontWeight: FontWeight.w600)),
                        const SizedBox(height: 4),
                        Text(closeTime,
                            style: TextStyle(
                                color: cs.onSurface.withAlpha(100),
                                fontSize: 11)),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showShareSheet(BuildContext context) {
    showModalBottomSheet(
      context: context,
      useRootNavigator: true,
      backgroundColor: Colors.transparent,
      isScrollControlled: true,
      builder: (_) => _ShareOrderSheet(order: order, fmt: fmt),
    );
  }
}

// ── 骨架屏 ────────────────────────────────────────────────

/// 「我的带单」首次加载时的全页骨架（交易员信息卡 + Tab 栏）
class _MyTradesFullSkeleton extends StatelessWidget {
  const _MyTradesFullSkeleton();

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return Column(
      children: [
        // 交易员信息卡骨架
        AppShimmer(
          child: Container(
            color: isDark ? AppColors.darkBgSecondary : AppColors.lightBg,
            padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    shimmerCircle(54),
                    const SizedBox(width: 12),
                    Expanded(
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          shimmerBox(120, 16),
                          const SizedBox(height: 8),
                          shimmerBox(200, 13),
                        ],
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 16),
                Container(
                  padding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
                  decoration: BoxDecoration(
                    color: cs.onSurface.withAlpha(10),
                    borderRadius: BorderRadius.circular(10),
                  ),
                  child: Column(
                    children: [
                      Row(
                          children: List.generate(
                              3,
                              (i) => Expanded(
                                    child: Padding(
                                      padding: EdgeInsets.symmetric(
                                          horizontal: i == 1 ? 8.0 : 0),
                                      child: Column(
                                        crossAxisAlignment: i == 0
                                            ? CrossAxisAlignment.start
                                            : i == 1
                                                ? CrossAxisAlignment.center
                                                : CrossAxisAlignment.end,
                                        children: [
                                          shimmerBox(55, 11),
                                          const SizedBox(height: 5),
                                          shimmerBox(40, 14),
                                        ],
                                      ),
                                    ),
                                  ))),
                      const SizedBox(height: 12),
                      Row(
                          children: List.generate(
                              3,
                              (i) => Expanded(
                                    child: Padding(
                                      padding: EdgeInsets.symmetric(
                                          horizontal: i == 1 ? 8.0 : 0),
                                      child: Column(
                                        crossAxisAlignment: i == 0
                                            ? CrossAxisAlignment.start
                                            : i == 1
                                                ? CrossAxisAlignment.center
                                                : CrossAxisAlignment.end,
                                        children: [
                                          shimmerBox(55, 11),
                                          const SizedBox(height: 5),
                                          shimmerBox(40, 14),
                                        ],
                                      ),
                                    ),
                                  ))),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
        // Tab 栏骨架
        AppShimmer(
          child: Container(
            decoration: BoxDecoration(
              border: Border(
                  bottom: BorderSide(
                      color: cs.outlineVariant.withAlpha(60), width: 1)),
            ),
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
              child: Row(
                children: List.generate(
                    3,
                    (i) => Expanded(
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: i == 1 ? 8.0 : 0),
                            child: shimmerFill(16, radius: 4),
                          ),
                        )),
              ),
            ),
          ),
        ),
        // 列表骨架
        Expanded(
          child: ListView.builder(
            padding: const EdgeInsets.only(bottom: 16),
            itemCount: 4,
            itemBuilder: (_, __) => const _FollowerCardSkeleton(),
          ),
        ),
      ],
    );
  }
}

/// 跟单用户卡片骨架（对应 _FollowerCard 样式）
class _FollowerCardSkeleton extends StatelessWidget {
  const _FollowerCardSkeleton();

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return AppShimmer(
      child: Container(
        margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
        padding: const EdgeInsets.all(14),
        decoration: BoxDecoration(
          color: isDark ? AppColors.darkBgSecondary : AppColors.lightBg,
          borderRadius: BorderRadius.circular(12),
        ),
        child: Column(
          children: [
            Row(
              children: [
                shimmerCircle(40),
                const SizedBox(width: 10),
                Expanded(child: shimmerBox(100, 14)),
                shimmerBox(55, 32, radius: 20),
              ],
            ),
            const SizedBox(height: 10),
            Row(
                children: List.generate(
                    3,
                    (i) => Expanded(
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: i == 1 ? 8.0 : 0),
                            child: Column(
                              crossAxisAlignment: i == 0
                                  ? CrossAxisAlignment.start
                                  : i == 1
                                      ? CrossAxisAlignment.center
                                      : CrossAxisAlignment.end,
                              children: [
                                shimmerBox(50, 11),
                                const SizedBox(height: 4),
                                shimmerBox(40, 13),
                              ],
                            ),
                          ),
                        ))),
            const SizedBox(height: 8),
            Row(children: [
              shimmerBox(16, 12),
              const SizedBox(width: 4),
              shimmerBox(120, 12)
            ]),
          ],
        ),
      ),
    );
  }
}

/// 带单仓位卡片骨架（对应 _OrderCard 当前带单样式）
class _OrderCardSkeleton extends StatelessWidget {
  const _OrderCardSkeleton();

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    return AppShimmer(
      child: Container(
        margin: const EdgeInsets.fromLTRB(16, 8, 16, 0),
        padding: const EdgeInsets.all(14),
        decoration: BoxDecoration(
          color:
              isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
          borderRadius: BorderRadius.circular(12),
          border: isDark
              ? null
              : Border.all(color: AppColors.lightBorder, width: 0.5),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 标题行：交易对 + badges
            Row(children: [
              shimmerBox(80, 15),
              const SizedBox(width: 8),
              shimmerBox(40, 20, radius: 4),
              const SizedBox(width: 6),
              shimmerBox(30, 20, radius: 4),
              const SizedBox(width: 6),
              shimmerBox(35, 20, radius: 4),
            ]),
            const SizedBox(height: 12),
            // 未实现盈亏
            Row(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                Expanded(
                    child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                      shimmerBox(90, 11),
                      const SizedBox(height: 5),
                      shimmerBox(120, 22),
                    ])),
                Column(crossAxisAlignment: CrossAxisAlignment.end, children: [
                  shimmerBox(45, 11),
                  const SizedBox(height: 5),
                  shimmerBox(70, 14),
                ]),
              ],
            ),
            const SizedBox(height: 12),
            shimmerFill(0.5),
            const SizedBox(height: 10),
            Row(
                children: List.generate(
                    3,
                    (i) => Expanded(
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: i == 1 ? 8.0 : 0),
                            child: Column(
                              crossAxisAlignment: i == 0
                                  ? CrossAxisAlignment.start
                                  : i == 1
                                      ? CrossAxisAlignment.center
                                      : CrossAxisAlignment.end,
                              children: [
                                shimmerBox(70, 11),
                                const SizedBox(height: 4),
                                shimmerBox(50, 13)
                              ],
                            ),
                          ),
                        ))),
            const SizedBox(height: 10),
            Row(
                children: List.generate(
                    3,
                    (i) => Expanded(
                          child: Padding(
                            padding: EdgeInsets.symmetric(
                                horizontal: i == 1 ? 8.0 : 0),
                            child: Column(
                              crossAxisAlignment: i == 0
                                  ? CrossAxisAlignment.start
                                  : i == 1
                                      ? CrossAxisAlignment.center
                                      : CrossAxisAlignment.end,
                              children: [
                                shimmerBox(70, 11),
                                const SizedBox(height: 4),
                                shimmerBox(50, 13)
                              ],
                            ),
                          ),
                        ))),
          ],
        ),
      ),
    );
  }
}

class _Badge extends StatelessWidget {
  const _Badge({required this.text, required this.color});

  final String text;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
      decoration: BoxDecoration(
        color: color.withAlpha(30),
        borderRadius: BorderRadius.circular(4),
      ),
      child: Text(text,
          style: TextStyle(
              color: color, fontSize: 11, fontWeight: FontWeight.w600)),
    );
  }
}

class _OrderStat extends StatelessWidget {
  const _OrderStat(
      {required this.label,
      required this.value,
      this.alignEnd = false,
      this.alignCenter = false});

  final String label;
  final String value;
  final bool alignEnd;
  final bool alignCenter;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final align = alignEnd
        ? CrossAxisAlignment.end
        : alignCenter
            ? CrossAxisAlignment.center
            : CrossAxisAlignment.start;
    return Expanded(
      child: Column(
        crossAxisAlignment: align,
        children: [
          Text(label,
              style:
                  TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 11)),
          const SizedBox(height: 2),
          Text(value,
              style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 13,
                  fontWeight: FontWeight.w600)),
        ],
      ),
    );
  }
}

// ── 分享带单 BottomSheet ───────────────────────────────────

class _ShareOrderSheet extends ConsumerStatefulWidget {
  const _ShareOrderSheet({required this.order, required this.fmt});

  final Map<String, dynamic> order;
  final String Function(dynamic, {int decimals}) fmt;

  @override
  ConsumerState<_ShareOrderSheet> createState() => _ShareOrderSheetState();
}

class _ShareOrderSheetState extends ConsumerState<_ShareOrderSheet> {
  final _cardKey = GlobalKey();
  bool _sharing = false;
  bool _saving = false;
  String? _inviteCode;
  String? _inviteUrl;

  @override
  void initState() {
    super.initState();
    _loadInviteInfo();
  }

  Future<void> _loadInviteInfo() async {
    try {
      final dio = ref.read(dioClientProvider);
      final data = await AuthService(dio).getMyInfo();
      final prefix = data['promotionPrefix']?.toString() ?? '';
      final code = data['promotionCode']?.toString() ?? '';
      final url =
          (prefix.isNotEmpty || code.isNotEmpty) ? '$prefix$code' : null;
      if (context.mounted) {
        setState(() {
          _inviteCode = code.isNotEmpty ? code : null;
          _inviteUrl = url;
        });
      }
    } catch (_) {}
  }

  String _fmtTimestamp(dynamic ts) {
    if (ts == null) return '--';
    final ms = int.tryParse(ts.toString());
    if (ms == null) return ts.toString();
    final dt = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: true)
        .add(const Duration(hours: 8));
    return '${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} '
        '${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}:${dt.second.toString().padLeft(2, '0')}';
  }

  Future<Uint8List?> _renderCard() async {
    final boundary =
        _cardKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
    if (boundary == null) return null;
    final image = await boundary.toImage(pixelRatio: 3.0);
    final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    return byteData?.buffer.asUint8List();
  }

  Future<void> _doSave(BuildContext context) async {
    setState(() => _saving = true);
    try {
      final bytes = await _renderCard();
      if (bytes == null) return;
      await Gal.requestAccess();
      await Gal.putImageBytes(
        bytes,
        name: 'trade_share_${DateTime.now().millisecondsSinceEpoch}',
      );
      if (!context.mounted) return;
      showTopToast(context,
          message: AppLocalizations.of(context)!.saveSuccess,
          backgroundColor: AppColors.rise);
    } on GalException catch (e) {
      if (!context.mounted) return;
      final l10n = AppLocalizations.of(context)!;
      if (e.type == GalExceptionType.accessDenied) {
        showTopToast(context,
            message: l10n.photoPermissionDenied,
            backgroundColor: AppColors.fall);
      } else {
        showTopToast(context,
            message: l10n.saveFailed, backgroundColor: AppColors.fall);
      }
    } catch (e) {
      if (context.mounted) {
        showTopToast(context,
            message: AppLocalizations.of(context)!.saveFailed,
            backgroundColor: AppColors.fall);
      }
    } finally {
      if (context.mounted) setState(() => _saving = false);
    }
  }

  Future<void> _doShare(BuildContext context) async {
    setState(() => _sharing = true);
    try {
      final bytes = await _renderCard();
      if (bytes == null) return;
      final tmpDir = await getTemporaryDirectory();
      final file = File(
          '${tmpDir.path}/trade_share_${DateTime.now().millisecondsSinceEpoch}.png');
      await file.writeAsBytes(bytes);
      if (!context.mounted) return;
      Navigator.of(context).pop();
      await Share.shareXFiles(
        [XFile(file.path, mimeType: 'image/png')],
        subject: AppLocalizations.of(context)!.myTradingProfit,
      );
    } catch (e) {
      if (context.mounted) {
        showTopToast(context,
            message: AppLocalizations.of(context)!.shareFailed,
            backgroundColor: AppColors.fall);
      }
    } finally {
      if (context.mounted) setState(() => _sharing = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final order = widget.order;
    final profit = double.tryParse(order['profit']?.toString() ?? '0') ?? 0.0;
    final pnlPositive = profit >= 0;
    final l10n = AppLocalizations.of(context)!;

    final symbol = order['symbol']?.toString() ?? '--';
    final isLong = (order['direction']?.toString() ?? '0') == '0';
    final leverage = order['leverage']?.toString() ?? '--';
    final profitRateRaw =
        double.tryParse(order['profitRate']?.toString() ?? '0') ?? 0.0;
    final profitRateStr =
        '${profitRateRaw >= 0 ? '+' : ''}${profitRateRaw.toStringAsFixed(2)}%';
    final openPrice = widget.fmt(order['openPrice']);
    final closePrice = widget.fmt(order['closePrice']);
    final openTime = _fmtTimestamp(order['openTime']);
    final closeTime = _fmtTimestamp(order['closeTime']);

    return Container(
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        borderRadius: const BorderRadius.vertical(top: Radius.circular(16)),
      ),
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 32),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          // 拖拽指示条
          Container(
            width: 36,
            height: 4,
            decoration: BoxDecoration(
              color: cs.onSurface.withAlpha(60),
              borderRadius: BorderRadius.circular(2),
            ),
          ),
          const SizedBox(height: 16),

          // 分享卡片预览
          RepaintBoundary(
            key: _cardKey,
            child: _TradeShareCard(
              symbol: symbol,
              isLong: isLong,
              leverage: leverage,
              profitRateStr: profitRateStr,
              pnlPositive: pnlPositive,
              openPrice: openPrice,
              closePrice: closePrice,
              openTime: openTime,
              closeTime: closeTime,
              inviteCode: _inviteCode,
              inviteUrl: _inviteUrl,
            ),
          ),
          const SizedBox(height: 24),

          // 操作按钮行：取消 | 保存海报 | 分享
          Row(
            children: [
              Expanded(
                child: OutlinedButton(
                  onPressed: () => Navigator.of(context).pop(),
                  style: OutlinedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 12),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(8)),
                  ),
                  child: Text(l10n.cancelLabel,
                      style: TextStyle(color: cs.onSurface, fontSize: 14)),
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: OutlinedButton(
                  onPressed: _saving ? null : () => _doSave(context),
                  style: OutlinedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 12),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(8)),
                  ),
                  child: _saving
                      ? SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(
                              strokeWidth: 2,
                              color: cs.onSurface.withAlpha(153)),
                        )
                      : Text(l10n.savePoster,
                          style: TextStyle(color: cs.onSurface, fontSize: 14)),
                ),
              ),
              const SizedBox(width: 8),
              Expanded(
                child: ElevatedButton(
                  onPressed: _sharing ? null : () => _doShare(context),
                  style: ElevatedButton.styleFrom(
                    backgroundColor:
                        pnlPositive ? AppColors.rise : AppColors.fall,
                    padding: const EdgeInsets.symmetric(vertical: 12),
                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(8)),
                    elevation: 0,
                  ),
                  child: _sharing
                      ? const SizedBox(
                          width: 16,
                          height: 16,
                          child: CircularProgressIndicator(
                              strokeWidth: 2, color: Colors.white),
                        )
                      : Text(l10n.shareLabel,
                          style: const TextStyle(
                              color: Colors.white,
                              fontSize: 14,
                              fontWeight: FontWeight.w600)),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// ── 带单分享卡片内容 ─────────────────────────────────────────

class _TradeShareCard extends StatelessWidget {
  const _TradeShareCard({
    required this.symbol,
    required this.isLong,
    required this.leverage,
    required this.profitRateStr,
    required this.pnlPositive,
    required this.openPrice,
    required this.closePrice,
    required this.openTime,
    required this.closeTime,
    this.inviteCode,
    this.inviteUrl,
  });

  final String symbol;
  final bool isLong;
  final String leverage;
  final String profitRateStr;
  final bool pnlPositive;
  final String openPrice;
  final String closePrice;
  final String openTime;
  final String closeTime;
  final String? inviteCode;
  final String? inviteUrl;

  String _baseCoin(String sym) {
    if (sym.contains('/')) return sym.split('/').first;
    return sym.toUpperCase().replaceFirst(RegExp(r'USDT$'), '');
  }

  @override
  Widget build(BuildContext context) {
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final l10n = AppLocalizations.of(context)!;
    final sideColor = isLong ? AppColors.rise : AppColors.fall;
    final pnlColor = pnlPositive ? AppColors.rise : AppColors.fall;
    final coinSymbol = _baseCoin(symbol);

    // 主题色变量
    final bgColors = isDark
        ? const [Color(0xFF1A1F2E), Color(0xFF0D1117)]
        : const [Color(0xFFF8F9FB), Color(0xFFEEF0F3)];
    final textPrimary = isDark ? Colors.white : const Color(0xFF1A1F2E);
    final textSecondary = isDark
        ? Colors.white.withAlpha(120)
        : const Color(0xFF1A1F2E).withAlpha(120);
    final textMuted = isDark
        ? Colors.white.withAlpha(80)
        : const Color(0xFF1A1F2E).withAlpha(80);
    final borderColor = isDark
        ? Colors.white.withAlpha(40)
        : const Color(0xFF1A1F2E).withAlpha(30);
    final qrFgColor = isDark ? Colors.white : Colors.black;
    final qrBgColor = isDark ? const Color(0xFF1A1F2E) : Colors.white;

    return Container(
      width: double.infinity,
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: bgColors,
        ),
        borderRadius: BorderRadius.circular(16),
      ),
      clipBehavior: Clip.antiAlias,
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // LOGO + 品牌名
            Row(
              children: [
                Image.asset(
                  'assets/images/app_icon.png',
                  height: 28,
                  width: 28,
                  errorBuilder: (_, __, ___) => const SizedBox.shrink(),
                ),
                const SizedBox(width: 8),
                Text(
                  'iBit',
                  style: TextStyle(
                      color: textPrimary,
                      fontSize: 14,
                      fontWeight: FontWeight.w700,
                      letterSpacing: 0.5),
                ),
              ],
            ),
            const SizedBox(height: 14),

            // 币对 + 永续 tag
            Row(
              children: [
                Text(
                  '${coinSymbol}USDT',
                  style: TextStyle(
                      color: textPrimary,
                      fontSize: 22,
                      fontWeight: FontWeight.w800),
                ),
                const SizedBox(width: 8),
                Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
                  decoration: BoxDecoration(
                    color: const Color(0xFFFFAB00),
                    borderRadius: BorderRadius.circular(4),
                  ),
                  child: Text(l10n.perpetual,
                      style: const TextStyle(
                          color: Colors.white,
                          fontSize: 11,
                          fontWeight: FontWeight.w700)),
                ),
              ],
            ),
            const SizedBox(height: 4),

            // 方向 + 杠杆
            Text(
              '${isLong ? l10n.openLong : l10n.openShort} ${leverage}X',
              style: TextStyle(
                  color: sideColor, fontSize: 15, fontWeight: FontWeight.w700),
            ),
            const SizedBox(height: 14),

            // 收益率（大字）
            Text(l10n.returnRate,
                style: TextStyle(color: textSecondary, fontSize: 12)),
            const SizedBox(height: 4),
            Text(profitRateStr,
                style: TextStyle(
                    color: pnlColor,
                    fontSize: 36,
                    fontWeight: FontWeight.w800,
                    letterSpacing: -0.5)),
            const SizedBox(height: 16),

            // 开仓均价 + 平仓均价
            Row(
              children: [
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(l10n.openAvgPrice,
                          style: TextStyle(color: textSecondary, fontSize: 11)),
                      const SizedBox(height: 2),
                      Text(openPrice,
                          style: TextStyle(
                              color: textPrimary,
                              fontSize: 13,
                              fontWeight: FontWeight.w600)),
                    ],
                  ),
                ),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: [
                      Text(l10n.avgClosePrice,
                          style: TextStyle(color: textSecondary, fontSize: 11)),
                      const SizedBox(height: 2),
                      Text(closePrice,
                          style: TextStyle(
                              color: textPrimary,
                              fontSize: 13,
                              fontWeight: FontWeight.w600)),
                    ],
                  ),
                ),
              ],
            ),
            const SizedBox(height: 10),

            // 时间
            Text(closeTime != '--' ? closeTime : openTime,
                style: TextStyle(color: textMuted, fontSize: 11)),
            const SizedBox(height: 14),

            // 分隔线
            Divider(color: borderColor, height: 1),
            const SizedBox(height: 14),

            // 邀请码 + 二维码
            Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      if (inviteCode != null)
                        RichText(
                          text: TextSpan(
                            style: const TextStyle(fontSize: 15),
                            children: [
                              TextSpan(
                                text: l10n.inviteCodeLabel,
                                style: TextStyle(color: textSecondary),
                              ),
                              TextSpan(
                                text: inviteCode!,
                                style: const TextStyle(
                                    color: AppColors.brand,
                                    fontWeight: FontWeight.w700),
                              ),
                            ],
                          ),
                        ),
                      const SizedBox(height: 4),
                      Text(l10n.registerAndEarnRebate,
                          style: TextStyle(color: textMuted, fontSize: 12)),
                    ],
                  ),
                ),
                Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: borderColor, width: 1),
                    borderRadius: BorderRadius.circular(6),
                  ),
                  padding: const EdgeInsets.all(4),
                  child: inviteUrl != null
                      ? QrImageView(
                          data: inviteUrl!,
                          version: QrVersions.auto,
                          size: 80,
                          eyeStyle: QrEyeStyle(
                            eyeShape: QrEyeShape.square,
                            color: qrFgColor,
                          ),
                          dataModuleStyle: QrDataModuleStyle(
                            dataModuleShape: QrDataModuleShape.square,
                            color: qrFgColor,
                          ),
                          backgroundColor: qrBgColor,
                          errorCorrectionLevel: QrErrorCorrectLevel.M,
                        )
                      : const SizedBox(width: 80, height: 80),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
