import 'dart:async';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:go_router/go_router.dart';
import 'package:shimmer/shimmer.dart';
import 'package:url_launcher/url_launcher.dart';

import '../../../core/config/app_config.dart';
import '../../../core/l10n/app_localizations.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/navigation/broker_navigation.dart';
import '../../../core/utils/number_format.dart';
import '../../../core/utils/symbol_display.dart';
import '../../../providers/currency_provider.dart';
import '../../../data/models/announcement/announcement.dart';
import '../../../data/models/home/app_header_item.dart';
import '../../../data/models/home/market_ticker.dart';
import '../../../providers/announcement_popup_provider.dart';
import '../../../providers/announcement_unread_provider.dart';
import '../../../core/network/dio_client.dart' show versionOutdatedProvider;
import '../../../providers/app_version_provider.dart';
import '../../../providers/customer_service_provider.dart';
import '../../../providers/asset_provider.dart';
import '../../../providers/home_provider.dart';
import '../../../providers/market_provider.dart'
    show marketProvider, spotTickerProvider, MarketMode;
import '../../widgets/common/app_refresh_indicator.dart';
import '../../widgets/common/coin_icon.dart';
import '../../widgets/common/update_dialog.dart';
import '../../widgets/market_list_row_layout.dart';
import 'activity_carousel.dart';
import 'top_traders_section.dart';

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

  @override
  ConsumerState<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends ConsumerState<HomeScreen>
    with WidgetsBindingObserver {
  bool _popupQueueStarted = false;
  bool _updateDialogShown = false;
  Timer? _unreadPollTimer;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _unreadPollTimer = Timer.periodic(const Duration(minutes: 1), (_) {
      if (mounted) ref.invalidate(announcementUnreadProvider);
    });
  }

  @override
  void dispose() {
    _unreadPollTimer?.cancel();
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      ref.invalidate(announcementUnreadProvider);
    }
  }

  @override
  Widget build(BuildContext context) {
    final state = ref.watch(homeProvider);

    // 监听系统弹窗公告（支持多个，按顺序逐一弹出）
    ref.listen<AsyncValue<List<AnnouncementBean>>>(
      announcementPopupProvider,
      (_, next) {
        final beans = next.valueOrNull;
        if (beans != null &&
            beans.isNotEmpty &&
            !_popupQueueStarted &&
            context.mounted) {
          _popupQueueStarted = true;
          _showAnnouncementPopupQueue(context, beans, 0);
        }
      },
    );

    // 监听版本更新
    ref.listen<AsyncValue<VersionCheckResult?>>(
      appVersionProvider,
      (_, next) {
        next.whenData((result) {
          if (result != null &&
              result.hasUpdate &&
              !_updateDialogShown &&
              context.mounted) {
            _updateDialogShown = true;
            UpdateDialog.show(context, result);
          }
        });
      },
    );

    // 后端返回 4099 时重新触发版本检查并弹出更新弹窗
    ref.listen<bool>(
      versionOutdatedProvider,
      (_, isOutdated) {
        if (isOutdated && context.mounted) {
          _updateDialogShown = false;
          ref.invalidate(appVersionProvider);
        }
      },
    );

    return Scaffold(
      body: SafeArea(
        child: state.isLoading && state.tickers.isEmpty
            ? _HomeShimmer(isLoggedIn: state.isLoggedIn)
            : _HomeBody(state: state),
      ),
    );
  }

  void _showAnnouncementPopupQueue(
      BuildContext context, List<AnnouncementBean> beans, int index) {
    if (index >= beans.length || !context.mounted) return;
    final bean = beans[index];
    final cs = Theme.of(context).colorScheme;
    // 限制弹窗最大高度为屏幕 65%，给 Flexible 提供有界约束
    final maxHeight = MediaQuery.of(context).size.height * 0.65;

    showDialog<void>(
      context: context,
      barrierDismissible: true,
      builder: (dialogContext) => Dialog(
        backgroundColor: cs.surface,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
        insetPadding: const EdgeInsets.symmetric(horizontal: 28, vertical: 48),
        child: ConstrainedBox(
          constraints: BoxConstraints(maxHeight: maxHeight),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // 标题（固定高度）
              Padding(
                padding: const EdgeInsets.fromLTRB(20, 20, 20, 16),
                child: Text(
                  bean.title,
                  style: TextStyle(
                    color: cs.onSurface,
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                  ),
                  textAlign: TextAlign.center,
                ),
              ),
              Divider(height: 1, thickness: 1, color: cs.outline),
              // Flexible 在 ConstrainedBox 有界约束下正确填充剩余空间
              Flexible(
                child: SingleChildScrollView(
                  padding: const EdgeInsets.fromLTRB(20, 16, 20, 16),
                  child: HtmlWidget(
                    bean.content,
                    textStyle: TextStyle(
                      color: cs.onSurface,
                      fontSize: 14,
                      height: 1.6,
                    ),
                  ),
                ),
              ),
              Divider(height: 1, thickness: 1, color: cs.outline),
              // 确认按钮（固定高度，始终在底部）
              Padding(
                padding: const EdgeInsets.fromLTRB(20, 12, 20, 20),
                child: ElevatedButton(
                  onPressed: () => Navigator.of(dialogContext).pop(),
                  child: Text(AppLocalizations.of(dialogContext)!.iUnderstand),
                ),
              ),
            ],
          ),
        ),
      ),
    ).whenComplete(() {
      // 无论按按钮还是点空白关闭，都标记已读并显示下一条
      markPopupShown(bean.id);
      final rid = int.tryParse(bean.id);
      if (rid != null) markAnnouncementsRead(ref, id: rid);
      if (context.mounted) {
        _showAnnouncementPopupQueue(context, beans, index + 1);
      }
    });
  }
}

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

class _HomeShimmer extends StatelessWidget {
  const _HomeShimmer({required this.isLoggedIn});
  final bool isLoggedIn;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Shimmer.fromColors(
      baseColor: cs.onSurface.withAlpha(15),
      highlightColor: cs.onSurface.withAlpha(30),
      child: CustomScrollView(
        physics: const NeverScrollableScrollPhysics(),
        slivers: [
          // AppBar 占位
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
              child: Row(
                children: [
                  _shimmerCircle(32),
                  const SizedBox(width: 10),
                  Expanded(
                    child: Container(
                      height: 36,
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(18),
                      ),
                    ),
                  ),
                  const SizedBox(width: 10),
                  _shimmerCircle(22),
                  const SizedBox(width: 14),
                  _shimmerCircle(22),
                ],
              ),
            ),
          ),

          // 资产卡片 / 未登录引导区 占位
          if (isLoggedIn) ...[
            SliverToBoxAdapter(
              child: Container(
                margin: const EdgeInsets.fromLTRB(16, 8, 16, 4),
                padding:
                    const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(16),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _shimmerBox(80, 13),
                    const SizedBox(height: 10),
                    _shimmerBox(150, 28),
                    const SizedBox(height: 10),
                    _shimmerBox(200, 13),
                  ],
                ),
              ),
            ),
            // 快捷入口占位
            SliverToBoxAdapter(
              child: Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: List.generate(5, (_) {
                    return Column(
                      children: [
                        Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.circular(14),
                          ),
                        ),
                        const SizedBox(height: 6),
                        _shimmerBox(30, 10),
                      ],
                    );
                  }),
                ),
              ),
            ),
          ] else ...[
            SliverToBoxAdapter(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(24, 16, 24, 16),
                child: Column(
                  children: [
                    _shimmerCircle(90),
                    const SizedBox(height: 20),
                    Container(
                      height: 52,
                      decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(12),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],

          // Banner 占位
          SliverToBoxAdapter(
            child: Container(
              margin: const EdgeInsets.fromLTRB(16, 8, 16, 8),
              height: 100,
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
              ),
            ),
          ),

          // 行情标题占位
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(16, 20, 16, 12),
              child: Row(
                children: [
                  _shimmerBox(60, 14),
                  const SizedBox(width: 20),
                  _shimmerBox(50, 14),
                  const SizedBox(width: 20),
                  _shimmerBox(50, 14),
                ],
              ),
            ),
          ),

          // 行情列表行占位
          SliverList.builder(
            itemCount: 6,
            itemBuilder: (_, __) => Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
              child: MarketListDataRow(
                leading: Container(
                  width: 36,
                  height: 36,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(10),
                  ),
                ),
                name: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    _shimmerBox(70, 14),
                    const SizedBox(height: 6),
                    _shimmerBox(50, 11),
                  ],
                ),
                price: Column(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    _shimmerBox(80, 14),
                    const SizedBox(height: 6),
                    _shimmerBox(50, 11),
                  ],
                ),
                change: Container(
                  height: 30,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(6),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  static Widget _shimmerBox(double width, double height) {
    return Container(
      width: width,
      height: height,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(4),
      ),
    );
  }

  static Widget _shimmerCircle(double size) {
    return Container(
      width: size,
      height: size,
      decoration: const BoxDecoration(
        color: Colors.white,
        shape: BoxShape.circle,
      ),
    );
  }
}

// ── 主体内容 ──────────────────────────────────────────────

class _HomeBody extends ConsumerWidget {
  const _HomeBody({required this.state});

  final HomeState state;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final notifier = ref.read(homeProvider.notifier);
    ref.watch(currencyProvider); // 法币切换时触发行情列表重建

    return AppRefreshIndicator(
      onRefresh: notifier.refresh,
      child: CustomScrollView(
        slivers: [
          // AppBar
          SliverToBoxAdapter(child: _HomeAppBar(state: state)),

          // 未登录：引导区域
          if (!state.isLoggedIn) ...[
            const SliverToBoxAdapter(child: _GuestHeroSection()),
          ],

          // 已登录：资产卡片 + 快捷入口
          if (state.isLoggedIn) ...[
            SliverToBoxAdapter(child: _AssetCard(state: state)),
            const SliverToBoxAdapter(child: _QuickActions()),

            // 活动专区
            SliverToBoxAdapter(child: ActivityCarousel(banners: state.banners)),
          ],

          // 顶级交易专家（登录/未登录共享）
          const SliverToBoxAdapter(child: TopTradersSection()),

          // 热门行情（登录/未登录共享）
          SliverToBoxAdapter(
            child: _MarketSectionHeader(
              tabIndex: state.marketTabIndex,
              notifier: notifier,
              showFavorites: state.isLoggedIn,
            ),
          ),
          const SliverToBoxAdapter(child: _MarketListHeader()),
          // tabIndex=4 展示现货，其余展示合约
          if (state.marketTabIndex == 4)
            _HomeSpotTickerSliver()
          else
            SliverList.builder(
              itemCount: state.displayTickers.length,
              itemBuilder: (context, index) {
                final ticker = state.displayTickers[index];
                return _MarketTickerRow(
                  ticker: ticker,
                  isFavorite: state.favorites.contains(ticker.symbol),
                  onToggleFavorite: () =>
                      notifier.toggleFavorite(ticker.symbol),
                  onTap: () => context.push('/market/futures/${ticker.symbol}'),
                );
              },
            ),

          const SliverToBoxAdapter(child: SizedBox(height: 24)),
        ],
      ),
    );
  }
}

// ── AppBar ────────────────────────────────────────────────

class _HomeAppBar extends ConsumerWidget {
  const _HomeAppBar({required this.state});

  final HomeState state;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
      child: Row(
        children: [
          // 个人中心入口
          Semantics(
            label: 'home_btn_profile',
            button: true,
            enabled: state.isLoggedIn,
            onTap: state.isLoggedIn ? () => context.push('/user') : null,
            child: GestureDetector(
              onTap: () => context.push('/user'),
              child: Container(
                width: 32,
                height: 32,
                decoration: BoxDecoration(
                  color: state.isLoggedIn
                      ? (isDark
                          ? AppColors.darkBgTertiary
                          : AppColors.lightBgTertiary)
                      : cs.onSurface.withAlpha(30),
                  shape: BoxShape.circle,
                ),
                child: Icon(
                  state.isLoggedIn ? Icons.person : Icons.person_outline,
                  color: state.isLoggedIn
                      ? cs.onSurface
                      : cs.onSurface.withAlpha(153),
                  size: 20,
                ),
              ),
            ),
          ),
          const SizedBox(width: 10),

          // 搜索栏
          Expanded(
            child: Semantics(
              label: 'home_search_market',
              onTap: () => context.go('/market'),
              child: GestureDetector(
                onTap: () => context.go('/market'),
                child: Container(
                  height: 36,
                  padding: const EdgeInsets.symmetric(horizontal: 12),
                  decoration: BoxDecoration(
                    color: isDark
                        ? AppColors.darkBgTertiary
                        : AppColors.lightBgTertiary,
                    borderRadius: BorderRadius.circular(18),
                  ),
                  child: Row(
                    children: [
                      Icon(Icons.search,
                          color: cs.onSurface.withAlpha(100), size: 18),
                      const SizedBox(width: 6),
                      Text(
                        AppLocalizations.of(context)!.searchPair,
                        style: TextStyle(
                          color: cs.onSurface.withAlpha(100),
                          fontSize: 13,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
          const SizedBox(width: 10),

          // 客服入口
          if (AppConfig.customerServiceEnabled)
            Padding(
              padding: const EdgeInsets.only(right: 14),
              child: Semantics(
                label: 'home_btn_service',
                button: true,
                onTap: () => openCustomerService(context, ref),
                child: GestureDetector(
                  onTap: () => openCustomerService(context, ref),
                  child: Icon(Icons.headset_mic_outlined,
                      color: cs.onSurface, size: 22),
                ),
              ),
            ),
          Semantics(
            label: 'home_btn_messages',
            button: true,
            onTap: () => context.push('/user/messages'),
            child: GestureDetector(
              onTap: () => context.push('/user/messages'),
              child: Stack(
                clipBehavior: Clip.none,
                children: [
                  Icon(Icons.notifications_outlined,
                      color: cs.onSurface, size: 22),
                  if (ref.watch(announcementUnreadProvider).valueOrNull
                      case final s? when s.isLoaded && s.hasUnread)
                    Positioned(
                      top: -2,
                      right: -2,
                      child: Container(
                        width: 8,
                        height: 8,
                        decoration: const BoxDecoration(
                          color: AppColors.fall,
                          shape: BoxShape.circle,
                        ),
                      ),
                    ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// ── 未登录/已登录：主视觉引导区 ───────────────────────────

class _GuestHeroSection extends ConsumerWidget {
  // ignore: unused_element_parameter
  const _GuestHeroSection({this.showLoginButton = true});

  final bool showLoginButton;

  Future<void> _onHeaderTap(BuildContext context, AppHeaderItem item) async {
    if (item.linkUrl.isEmpty) return;

    if (item.isExternal) {
      await launchUrl(Uri.parse(item.linkUrl),
          mode: LaunchMode.externalApplication);
      return;
    }

    final url = item.linkUrl;

    // 复用 ActivityCarousel 的跳转逻辑
    const tabRoutes = {
      '/',
      'market',
      '/market',
      '/futures',
      '/copy-trading',
      '/asset'
    };
    final isTabRoute = tabRoutes.any((r) => url == r || url.startsWith('$r/'));

    if (!context.mounted) return;
    if (isTabRoute) {
      context.go(url);
    } else {
      context.push(url);
    }
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // 仅在 appHeaders 变化时重建（不因行情 WS 刷新而重建）
    final appHeaders = ref.watch(homeProvider.select((s) => s.appHeaders));

    final children = [
      // Header 媒体区域
      _HomeHeaderMedia(
        appHeaders: appHeaders,
        onHeaderTap: (item) => _onHeaderTap(context, item),
      ),
      if (showLoginButton) ...[
        const SizedBox(height: 12),
        // 登录 / 注册 按钮
        SizedBox(
          width: double.infinity,
          height: 52,
          child: ElevatedButton(
            onPressed: () => context.push('/login'),
            style: ElevatedButton.styleFrom(
              backgroundColor: const Color(0xFF1E1E1E),
              foregroundColor: Colors.white,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(12),
              ),
              elevation: 0,
            ),
            child: Text(
              AppLocalizations.of(context)!.loginRegister,
              style: const TextStyle(
                fontSize: 17,
                fontWeight: FontWeight.w600,
                letterSpacing: 1,
              ),
            ),
          ),
        ),
      ]
    ];

    return Padding(
      padding: EdgeInsets.fromLTRB(16, 8, 16, showLoginButton ? 0 : 12),
      child: Column(children: children),
    );
  }
}

// ── Header 媒体区域（统一走图片管线：本地 WebP 动图 / 远程图片）──

class _HomeHeaderMedia extends StatelessWidget {
  const _HomeHeaderMedia({
    required this.appHeaders,
    required this.onHeaderTap,
  });

  final List<AppHeaderItem> appHeaders;
  final Future<void> Function(AppHeaderItem) onHeaderTap;

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

    Widget placeholder() => Container(
          color: cs.surface,
          child: Center(
            child: Icon(
              Icons.image_outlined,
              color: cs.onSurface.withAlpha(60),
              size: 32,
            ),
          ),
        );

    Widget errorBox() => Container(
          color: cs.surface,
          child: Center(
            child: Icon(
              Icons.broken_image_outlined,
              color: cs.onSurface.withAlpha(80),
              size: 28,
            ),
          ),
        );

    // 本地兜底：深色/浅色 PNG（与 assets/animations 资源一致）
    Widget localFallback() {
      final asset = brightness == Brightness.dark
          ? 'assets/animations/home_header_dart.png'
          : 'assets/animations/home_header_light.png';
      return Image.asset(
        asset,
        fit: BoxFit.cover,
        gaplessPlayback: true,
        errorBuilder: (_, __, ___) => errorBox(),
      );
    }

    // 接口返回时用远程图片，否则走本地兜底
    Widget content;
    VoidCallback? onTap;
    if (appHeaders.isNotEmpty) {
      final item = appHeaders.first;
      final url = item.resolveUrl(brightness);
      onTap = () => onHeaderTap(item);
      if (url.isNotEmpty) {
        content = CachedNetworkImage(
          imageUrl: url,
          fit: BoxFit.cover,
          placeholder: (_, __) => placeholder(),
          errorWidget: (_, __, ___) => localFallback(),
        );
      } else {
        content = localFallback();
      }
    } else {
      content = localFallback();
    }

    final media = ClipRRect(
      borderRadius: BorderRadius.circular(16),
      child: AspectRatio(
        aspectRatio: 16 / 9,
        child: Container(
          color: Colors.black,
          child: content,
        ),
      ),
    );

    return onTap == null ? media : GestureDetector(onTap: onTap, child: media);
  }
}

// ══════════════════════════════════════════════════════════
// 以下是已登录状态下的组件
// ══════════════════════════════════════════════════════════

// ── 已登录：资产卡片 ───────────────────────────────────────

class _AssetCard extends ConsumerWidget {
  const _AssetCard({required this.state});

  final HomeState state;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final assetState = ref.watch(assetProvider);
    final obscure = assetState.obscureBalance;
    final pnlColor = AppColors.changeColor(state.todayPnl);
    final sign = state.todayPnl >= 0 ? '+' : '';

    return Container(
      margin: const EdgeInsets.fromLTRB(16, 8, 16, 4),
      padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18),
      decoration: BoxDecoration(
        color: isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
        borderRadius: BorderRadius.circular(16),
        border: isDark
            ? null
            : Border.all(color: AppColors.lightBorder, width: 0.5),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            children: [
              Text(
                AppLocalizations.of(context)!.totalAssetsValue,
                style:
                    TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 13),
              ),
              const SizedBox(width: 6),
              GestureDetector(
                onTap: () => ref.read(assetProvider.notifier).toggleObscure(),
                child: Icon(
                  obscure
                      ? Icons.visibility_off_outlined
                      : Icons.visibility_outlined,
                  size: 16,
                  color: cs.onSurface.withAlpha(153),
                ),
              ),
              const Spacer(),
              GestureDetector(
                onTap: () => context.push('/asset/deposit'),
                child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
                  decoration: BoxDecoration(
                    color: AppColors.brand,
                    borderRadius: BorderRadius.circular(4),
                  ),
                  child: Text(
                    AppLocalizations.of(context)!.recharge,
                    style: const TextStyle(
                        color: Colors.black,
                        fontSize: 12,
                        fontWeight: FontWeight.w500),
                  ),
                ),
              ),
            ],
          ),
          const SizedBox(height: 6),
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Flexible(
                child: Text(
                  obscure
                      ? '****'
                      : formatPrice(state.totalAsset, decimalPlaces: 2),
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(
                    color: cs.onSurface,
                    fontSize: 28,
                    fontWeight: FontWeight.w700,
                    letterSpacing: -0.5,
                  ),
                ),
              ),
              const SizedBox(width: 6),
              Padding(
                padding: const EdgeInsets.only(bottom: 4),
                child: Text(
                  'USDT',
                  style: TextStyle(
                      color: cs.onSurface.withAlpha(153), fontSize: 13),
                ),
              ),
            ],
          ),
          const SizedBox(height: 6),
          Row(
            children: [
              Text(
                AppLocalizations.of(context)!.todayPnl,
                style:
                    TextStyle(color: cs.onSurface.withAlpha(153), fontSize: 12),
              ),
              const SizedBox(width: 8),
              Flexible(
                child: Text(
                  obscure
                      ? '****'
                      : state.todayPnlRateAvailable
                          ? '$sign$fiatSymbol${(state.todayPnl * fiatRate).toStringAsFixed(2)} ($sign${state.todayPnlPct.toStringAsFixed(2)}%)'
                          : '$sign$fiatSymbol${(state.todayPnl * fiatRate).toStringAsFixed(2)} (--)',
                  maxLines: 1,
                  overflow: TextOverflow.ellipsis,
                  style: TextStyle(
                    color: obscure ? cs.onSurface.withAlpha(153) : pnlColor,
                    fontSize: 13,
                    fontWeight: FontWeight.w500,
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

// ── 快捷入口 ──────────────────────────────────────────────

class _QuickActions extends ConsumerWidget {
  const _QuickActions();

  static const _actionDefs = [
    (
      icon: Icons.trending_up,
      iconAsset: null,
      key: 'perpetual',
      route: '/futures/BTCUSDT',
      useGo: true
    ),
    (
      icon: Icons.people_alt_outlined,
      iconAsset: null,
      key: 'copy',
      route: '/copy-trading',
      useGo: true
    ),
    (
      icon: Icons.account_balance_wallet_outlined,
      iconAsset: null,
      key: 'recharge',
      route: '/asset/deposit',
      useGo: false
    ),
    (
      icon: Icons.card_giftcard_outlined,
      iconAsset: null,
      key: 'invite',
      route: '/user/referral',
      useGo: false
    ),
    (
      icon: Icons.business_center_outlined,
      iconAsset: null,
      key: 'broker',
      route: '/broker',
      useGo: false
    ),
    (
      icon: null,
      iconAsset: 'assets/images/ico_licai.png',
      key: 'ido',
      route: '/finance/ido',
      useGo: false
    ),
    (
      icon: null,
      iconAsset: 'assets/images/ico_dzgjs.png',
      key: 'commodity',
      route: '',
      useGo: false
    ),
    (
      icon: null,
      iconAsset: 'assets/images/ico_gp.png',
      key: 'stock',
      route: '',
      useGo: false
    ),
    (
      icon: null,
      iconAsset: 'assets/images/ico_wh.png',
      key: 'forex',
      route: '',
      useGo: false
    ),
    (
      icon: null,
      iconAsset: 'assets/images/ico_yy.png',
      key: 'app',
      route: '',
      useGo: false
    ),
  ];

  Future<void> _onBrokerTap(BuildContext context, WidgetRef ref) async {
    await openBrokerEntry(context, ref);
  }

  static void _showDevelopingDialog(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final dialogBg = isDark ? AppColors.darkBgSecondary : Colors.white;
    final titleColor = isDark ? AppColors.darkTextPrimary : Colors.black;
    final messageColor = isDark
        ? AppColors.darkTextSecondary
        : const Color(0xFF666666);
    final buttonBg = isDark ? AppColors.brand : Colors.black;
    final buttonFg = isDark ? Colors.black : Colors.white;

    showDialog<void>(
      context: context,
      barrierDismissible: true,
      builder: (dialogContext) => Dialog(
        backgroundColor: dialogBg,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
        insetPadding: const EdgeInsets.symmetric(horizontal: 48, vertical: 48),
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 28),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                l10n.appHomeComingSoon,
                style: TextStyle(
                  color: titleColor,
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                ),
              ),
              const SizedBox(height: 8),
              Text(
                l10n.appHomeDevelopingMessage,
                style: TextStyle(
                  color: messageColor,
                  fontSize: 13,
                ),
              ),
              const SizedBox(height: 20),
              SizedBox(
                width: double.infinity,
                child: TextButton(
                  onPressed: () => Navigator.of(dialogContext).pop(),
                  style: TextButton.styleFrom(
                    backgroundColor: buttonBg,
                    foregroundColor: buttonFg,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8),
                    ),
                    padding: const EdgeInsets.symmetric(vertical: 12),
                  ),
                  child: Text(l10n.confirmLabel),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final l10n = AppLocalizations.of(context)!;
    final labelMap = {
      'perpetual': l10n.perpetualFutures,
      'copy': l10n.copyTrading,
      'recharge': l10n.recharge,
      'invite': l10n.inviteFriends,
      'broker': l10n.broker,
      'ido': 'IDO理财',
      'commodity': '大宗贵金属',
      'stock': '股票',
      'forex': '外汇',
      'app': '应用',
    };
    final semanticsMap = {
      'perpetual': 'home_btn_futures',
      'copy': 'home_btn_copy_trading',
      'recharge': 'home_btn_deposit',
      'invite': 'home_btn_referral',
      'broker': 'home_btn_broker',
      'ido': 'home_btn_ido',
      'commodity': 'home_btn_commodity',
      'stock': 'home_btn_stock',
      'forex': 'home_btn_forex',
      'app': 'home_btn_app',
    };
    const developingKeys = {'commodity', 'stock', 'forex'};
    List<Widget> buildActionItems() {
      return _actionDefs.map((action) {
        return _QuickActionItem(
          icon: action.icon,
          iconAsset: action.iconAsset,
          label: labelMap[action.key]!,
          semanticsLabel: semanticsMap[action.key]!,
          onTap: developingKeys.contains(action.key)
              ? () => _showDevelopingDialog(context)
              : action.key == 'app'
              ? () => context.push('/app')
              : action.key == 'broker'
                  ? () => _onBrokerTap(context, ref)
                  : () => action.useGo
                      ? context.go(action.route)
                      : context.push(action.route),
        );
      }).toList();
    }

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
      child: GridView.count(
        crossAxisCount: 5,
        shrinkWrap: true,
        physics: const NeverScrollableScrollPhysics(),
        mainAxisSpacing: 12,
        crossAxisSpacing: 4,
        childAspectRatio: 0.84,
        children: buildActionItems(),
      ),
    );
  }
}

class _QuickActionItem extends StatelessWidget {
  const _QuickActionItem({
    required this.icon,
    this.iconAsset,
    required this.label,
    required this.semanticsLabel,
    required this.onTap,
  });

  final IconData? icon;
  final String? iconAsset;
  final String label;
  final String semanticsLabel;
  final VoidCallback onTap;

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

    return Semantics(
      label: semanticsLabel,
      button: true,
      onTap: onTap,
      child: GestureDetector(
        onTap: onTap,
        child: SizedBox(
          width: 62,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: 48,
                height: 48,
                decoration: BoxDecoration(
                  color: isDark
                      ? AppColors.darkBgTertiary
                      : AppColors.lightBgTertiary,
                  borderRadius: BorderRadius.circular(14),
                ),
                child: iconAsset != null
                    ? Container(
                  alignment:Alignment.center,
                        child: Image.asset(
                          iconAsset!,
                          fit: BoxFit.contain,
                          width:22,
                          height:22,
                        ),
                      )
                    : Icon(icon, color: AppColors.brand, size: 22),
              ),
              const SizedBox(height: 6),
              Text(
                label == "应用" ? '$label >' : label,
                style: TextStyle(
                  color: cs.onSurface.withAlpha(153),
                  fontSize: 11,
                ),
                textAlign: TextAlign.center,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// ── 行情区块：标题 + Tab ──────────────────────────────────

class _MarketSectionHeader extends StatelessWidget {
  const _MarketSectionHeader({
    required this.tabIndex,
    required this.notifier,
    this.showFavorites = true,
  });

  final int tabIndex;
  final HomeNotifier notifier;
  final bool showFavorites;

  List<String> _getTabs(BuildContext context) {
    final l10n = AppLocalizations.of(context)!;
    return [l10n.hotTrading, l10n.gainers, l10n.losers, l10n.spotTab];
  }

  static const _tabIndices = [1, 2, 3, 4];

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

    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 20, 16, 0),
      child: Row(
        children: List.generate(_tabIndices.length, (i) {
          final tabs = _getTabs(context);
          final actualIndex = _tabIndices[i];
          final selected = actualIndex == tabIndex;
          final tabSemantics = [
            'home_tab_market_hot',
            'home_tab_market_gainers',
            'home_tab_market_losers',
            'home_tab_market_spot'
          ];
          return Semantics(
            label: tabSemantics[i],
            button: true,
            enabled: true,
            onTap: () => notifier.setMarketTab(actualIndex),
            child: GestureDetector(
              onTap: () => notifier.setMarketTab(actualIndex),
              child: Padding(
                padding: const EdgeInsets.only(right: 20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      tabs[i],
                      style: TextStyle(
                        fontSize: 14,
                        fontWeight:
                            selected ? FontWeight.w600 : FontWeight.w400,
                        color: selected
                            ? cs.onSurface
                            : cs.onSurface.withAlpha(153),
                      ),
                    ),
                    const SizedBox(height: 4),
                    if (selected)
                      Container(height: 2, width: 20, color: AppColors.brand),
                  ],
                ),
              ),
            ),
          );
        }),
      ),
    );
  }
}

// ── 行情列表表头 ──────────────────────────────────────────

// ── 首页现货行情 Sliver（tabIndex=4）─────────────────────────

class _HomeSpotTickerSliver extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final symbols = ref.watch(
      marketProvider.select((s) => s.spotDisplaySymbols.take(10).toList()),
    );
    final spotLoading = ref.watch(
      marketProvider.select((s) => s.spotLoading),
    );
    // 首次进入现货 Tab 时触发加载
    final loaded =
        ref.watch(marketProvider.select((s) => s.spotTickers.isNotEmpty));
    if (!loaded && !spotLoading) {
      Future.microtask(() {
        ref.read(marketProvider.notifier).setMode(MarketMode.spot);
      });
    }
    if (spotLoading || symbols.isEmpty) {
      return SliverToBoxAdapter(
        child: SizedBox(
          height: 80,
          child: const Center(child: CircularProgressIndicator()),
        ),
      );
    }
    return SliverList.builder(
      itemCount: symbols.length,
      itemBuilder: (context, index) {
        final sym = symbols[index];
        return _HomeSpotTickerRow(symbol: sym);
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final cs = Theme.of(context).colorScheme;
    final ticker = ref.watch(spotTickerProvider(symbol));
    if (ticker == null) return const SizedBox.shrink();

    final changeColor = AppColors.changeColor(ticker.change24h);
    final changeStr = formatChange(ticker.change24h);

    return InkWell(
      onTap: () => context.push('/market/spot/${ticker.symbol}'),
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        child: MarketListDataRow(
          leading: CoinIcon(
            symbol: ticker.baseAsset,
            iconUrl: ticker.icon,
            size: 36,
            borderRadius: 10,
          ),
          name: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                formatUsdtPairDisplay(ticker.symbol),
                style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
              Text(
                AppLocalizations.of(context)!.spot,
                style: TextStyle(
                  color: cs.onSurface.withAlpha(153),
                  fontSize: 11,
                ),
              ),
            ],
          ),
          price: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                ticker.lastPrice > 0
                    ? (ticker.lastPriceStr != null
                        ? formatRawPrice(ticker.lastPriceStr!)
                        : formatPrice(ticker.lastPrice))
                    : '--',
                style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                  fontFeatures: const [FontFeature.tabularFigures()],
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
              Text(
                ticker.lastPrice > 0 ? formatFiatPrice(ticker.lastPrice) : '--',
                style: TextStyle(
                  color: cs.onSurface.withAlpha(153),
                  fontSize: 11,
                  fontFeatures: const [FontFeature.tabularFigures()],
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
            ],
          ),
          change: Container(
            height: 34,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: changeColor,
              borderRadius: BorderRadius.circular(6),
            ),
            child: Text(
              changeStr,
              style: const TextStyle(
                color: Colors.white,
                fontSize: 13,
                fontWeight: FontWeight.w600,
                fontFeatures: [FontFeature.tabularFigures()],
              ),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }
}

class _MarketListHeader extends StatelessWidget {
  const _MarketListHeader();

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return Padding(
      padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
      child: MarketListHeaderRow(
        leading: const SizedBox(width: 36),
        name: Text(
          AppLocalizations.of(context)!.coinNameLabel,
          style: TextStyle(
            color: cs.onSurface.withAlpha(153),
            fontSize: 12,
          ),
        ),
        price: Text(
          AppLocalizations.of(context)!.latestPrice,
          textAlign: TextAlign.end,
          style: TextStyle(
            color: cs.onSurface.withAlpha(153),
            fontSize: 12,
          ),
        ),
        change: Text(
          AppLocalizations.of(context)!.change24h,
          textAlign: TextAlign.center,
          style: TextStyle(
            color: cs.onSurface.withAlpha(153),
            fontSize: 12,
          ),
        ),
      ),
    );
  }
}

// ── 行情行 ────────────────────────────────────────────────

class _MarketTickerRow extends StatelessWidget {
  const _MarketTickerRow({
    required this.ticker,
    required this.isFavorite,
    required this.onToggleFavorite,
    required this.onTap,
  });

  final MarketTicker ticker;
  final bool isFavorite;
  final VoidCallback onToggleFavorite;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final color = AppColors.changeColor(ticker.change24h);
    final changeStr = formatChange(ticker.change24h);

    final vol = ticker.volume24h;
    final volStr = vol >= 1e9
        ? '${(vol / 1e9).toStringAsFixed(2)}B'
        : '${(vol / 1e6).toStringAsFixed(0)}M';

    return InkWell(
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        child: MarketListDataRow(
          leading: CoinIcon(
            symbol: ticker.baseAsset,
            iconUrl: ticker.icon,
            size: 36,
            borderRadius: 10,
          ),
          name: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                formatUsdtPairDisplay(ticker.symbol),
                style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
              Text(
                ticker.isFutures
                    ? '${AppLocalizations.of(context)!.turnover} $volStr'
                    : AppLocalizations.of(context)!.spot,
                style: TextStyle(
                  color: cs.onSurface.withAlpha(153),
                  fontSize: 11,
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
            ],
          ),
          price: Column(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                ticker.lastPriceStr != null
                    ? formatRawPrice(ticker.lastPriceStr!)
                    : formatPrice(ticker.lastPrice,
                        decimalPlaces: ticker.pricePrecision),
                style: TextStyle(
                  color: cs.onSurface,
                  fontSize: 14,
                  fontWeight: FontWeight.w500,
                  fontFeatures: const [FontFeature.tabularFigures()],
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
              Text(
                formatFiatPrice(ticker.lastPrice,
                    pricePrecision: ticker.pricePrecision),
                style: TextStyle(
                  color: cs.onSurface.withAlpha(153),
                  fontSize: 11,
                  fontFeatures: const [FontFeature.tabularFigures()],
                ),
                maxLines: 1,
                overflow: TextOverflow.ellipsis,
              ),
            ],
          ),
          change: Container(
            height: 34,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: color,
              borderRadius: BorderRadius.circular(6),
            ),
            child: Text(
              changeStr,
              style: const TextStyle(
                color: Colors.white,
                fontSize: 13,
                fontWeight: FontWeight.w600,
                fontFeatures: [FontFeature.tabularFigures()],
              ),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }
}
