import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_ui/shadcn_ui.dart';

import '../../../common/domain/metal_type.dart';
import '../../../common/domain/money.dart';
import '../../../common/router/app_router.dart';
import '../../../common/widgets/prototype_ui.dart';
import '../../profile/application/price_color_theme.dart';
import '../../profile/application/profile_settings_controller.dart';
import '../application/exchange_calculator_controller.dart';
import '../application/market_controller.dart';
import '../data/market_models.dart';

class MarketPage extends HookConsumerWidget {
  const MarketPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final market = ref.watch(marketControllerProvider);
    final exchange = ref.watch(exchangeCalculatorControllerProvider);
    final palette = priceColorPalette(
      ref.watch(profileSettingsControllerProvider).priceColorMode,
    );
    final gramCtrl = useTextEditingController(
      text: exchange.gram.toStringAsFixed(2),
    );
    final amountCtrl = useTextEditingController(
      text: exchange.amount.toStringAsFixed(2),
    );
    final gramFocus = useFocusNode();
    final amountFocus = useFocusNode();
    final cs = ShadTheme.of(context).colorScheme;

    useEffect(
      () {
        if (!gramFocus.hasFocus) {
          gramCtrl.text = exchange.gram.toStringAsFixed(
            exchange.gram % 1 == 0 ? 0 : 2,
          );
        }
        if (!amountFocus.hasFocus) {
          amountCtrl.text = exchange.amount.toStringAsFixed(2);
        }
        return null;
      },
      [
        exchange.gram,
        exchange.amount,
        exchange.selectedChannel.id,
        exchange.metal.id,
      ],
    );

    return SafeArea(
      top: false,
      child: ListView(
        padding: const EdgeInsets.fromLTRB(0, 8, 0, 86),
        children: [
          PrototypeFrame(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Row(
                  children: [
                    const Text(
                      '行情',
                      style: TextStyle(
                        fontSize: 17,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    const Spacer(),
                    GestureDetector(
                      onTap: () =>
                          _showPriceAlertSheet(context, market.selectedMetal),
                      child: Container(
                        width: 30,
                        height: 30,
                        decoration: BoxDecoration(
                          color: const Color(0xFFF7F4EE),
                          borderRadius: BorderRadius.circular(999),
                        ),
                        child: const Icon(
                          Icons.notifications_none_outlined,
                          size: 18,
                          color: Color(0xFF9A968D),
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 14),
                Row(
                  children: [
                    for (var i = 0; i < MetalType.values.length; i++) ...[
                      Expanded(
                        child: _MetalTab(
                          label: MetalType.values[i].label,
                          selected: MetalType.values[i] == market.selectedMetal,
                          onTap: () {
                            final metal = MetalType.values[i];
                            ref
                                .read(marketControllerProvider.notifier)
                                .selectMetal(metal);
                            ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .selectMetal(metal);
                          },
                        ),
                      ),
                      if (i != MetalType.values.length - 1)
                        const SizedBox(width: 8),
                    ],
                  ],
                ),
                const SizedBox(height: 10),
                PrototypeCard(
                  padding: const EdgeInsets.fromLTRB(14, 12, 14, 13),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: [
                          Text(
                            '¥',
                            style: TextStyle(
                              fontSize: 15,
                              fontWeight: FontWeight.w600,
                              color: cs.foreground,
                            ),
                          ),
                          const SizedBox(width: 2),
                          Text(
                            formatCny(
                              market.quote.spotPrice,
                            ).replaceFirst('¥', ''),
                            style: TextStyle(
                              fontSize: 29,
                              fontWeight: FontWeight.w600,
                              color: cs.foreground,
                              letterSpacing: -1,
                              height: 1,
                            ),
                          ),
                          const Padding(
                            padding: EdgeInsets.only(left: 4, bottom: 2),
                            child: Text(
                              '元/克',
                              style: TextStyle(
                                fontSize: 12,
                                color: Color(0xFF8A8780),
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 6),
                      Row(
                        children: [
                          _ChangeChip(
                            amount: market.quote.changeAmount,
                            percent: market.quote.changePercent,
                            upColor: Color(palette.up),
                            downColor: Color(palette.down),
                            upBackground: Color(palette.upBackground),
                            downBackground: Color(palette.downBackground),
                          ),
                          const SizedBox(width: 8),
                          Text(
                            '报价 ${_timeLabel(market.quote.updatedAt)}',
                            style: const TextStyle(
                              fontSize: 12,
                              color: Color(0xFF8A8780),
                            ),
                          ),
                          const Spacer(),
                          GestureDetector(
                            onTap: () {},
                            child: const Icon(
                              Icons.info_outline,
                              size: 16,
                              color: Color(0xFFB3AFA5),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 10),
                      Row(
                        children: [
                          for (final period in MarketPeriod.values) ...[
                            _PeriodPill(
                              label: period.label,
                              selected: period == market.period,
                              onTap: () => ref
                                  .read(marketControllerProvider.notifier)
                                  .selectPeriod(period),
                            ),
                            if (period != MarketPeriod.values.last)
                              const SizedBox(width: 6),
                          ],
                        ],
                      ),
                      const SizedBox(height: 8),
                      GestureDetector(
                        onTap: () => context.push(
                          '${AppRoutes.marketKline}?metal=${market.selectedMetal.id}&period=${market.period.id}',
                        ),
                        child: SizedBox(
                          height: 88,
                          child: ClipRRect(
                            borderRadius: BorderRadius.circular(10),
                            child: PrototypeLineChart(
                              values: market.points
                                  .map((p) => p.close)
                                  .toList(growable: false),
                            ),
                          ),
                        ),
                      ),
                      const SizedBox(height: 10),
                      Container(height: 0.5, color: cs.border),
                      const SizedBox(height: 10),
                      Row(
                        children: [
                          const Text(
                            '兑换试算',
                            style: TextStyle(
                              fontSize: 14,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      SizedBox(
                        height: 32,
                        child: ListView.separated(
                          scrollDirection: Axis.horizontal,
                          physics: const BouncingScrollPhysics(),
                          itemCount: exchange.channels.length,
                          separatorBuilder: (context, index) =>
                              const SizedBox(width: 7),
                          itemBuilder: (context, index) {
                            final channel = exchange.channels[index];
                            return PrototypePill(
                              label: channel.name,
                              selected:
                                  channel.id == exchange.selectedChannel.id,
                              onTap: () => ref
                                  .read(
                                    exchangeCalculatorControllerProvider
                                        .notifier,
                                  )
                                  .selectChannel(channel.id),
                            );
                          },
                        ),
                      ),
                      const SizedBox(height: 10),
                      if (!exchange.swapped) ...[
                        _ExchangeField(
                          controller: gramCtrl,
                          focusNode: gramFocus,
                          unit: exchange.metal.label,
                          leading: '克',
                          onChanged: (value) {
                            final gram = double.tryParse(value) ?? 0;
                            ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .setGram(gram);
                          },
                        ),
                        const SizedBox(height: 8),
                        Center(
                          child: GestureDetector(
                            onTap: () => ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .toggleSwapped(),
                            child: Container(
                              width: 30,
                              height: 30,
                              decoration: BoxDecoration(
                                color: Colors.white,
                                border: Border.all(
                                  color: cs.border,
                                  width: 0.5,
                                ),
                                shape: BoxShape.circle,
                                boxShadow: const [
                                  BoxShadow(
                                    color: Color(0x1F281F0C),
                                    blurRadius: 7,
                                    offset: Offset(0, 2),
                                  ),
                                ],
                              ),
                              child: const Icon(
                                Icons.swap_vert,
                                size: 16,
                                color: Color(0xFFB5862A),
                              ),
                            ),
                          ),
                        ),
                        const SizedBox(height: 8),
                        _ExchangeField(
                          controller: amountCtrl,
                          focusNode: amountFocus,
                          unit: 'CNY',
                          leading: '¥',
                          onChanged: (value) {
                            final amount = double.tryParse(value) ?? 0;
                            ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .setAmount(amount);
                          },
                        ),
                      ] else ...[
                        _ExchangeField(
                          controller: amountCtrl,
                          focusNode: amountFocus,
                          unit: 'CNY',
                          leading: '¥',
                          onChanged: (value) {
                            final amount = double.tryParse(value) ?? 0;
                            ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .setAmount(amount);
                          },
                        ),
                        const SizedBox(height: 8),
                        Center(
                          child: GestureDetector(
                            onTap: () => ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .toggleSwapped(),
                            child: Container(
                              width: 30,
                              height: 30,
                              decoration: BoxDecoration(
                                color: Colors.white,
                                border: Border.all(
                                  color: cs.border,
                                  width: 0.5,
                                ),
                                shape: BoxShape.circle,
                                boxShadow: const [
                                  BoxShadow(
                                    color: Color(0x1F281F0C),
                                    blurRadius: 7,
                                    offset: Offset(0, 2),
                                  ),
                                ],
                              ),
                              child: const Icon(
                                Icons.swap_vert,
                                size: 16,
                                color: Color(0xFFB5862A),
                              ),
                            ),
                          ),
                        ),
                        const SizedBox(height: 8),
                        _ExchangeField(
                          controller: gramCtrl,
                          focusNode: gramFocus,
                          unit: exchange.metal.label,
                          leading: '克',
                          onChanged: (value) {
                            final gram = double.tryParse(value) ?? 0;
                            ref
                                .read(
                                  exchangeCalculatorControllerProvider.notifier,
                                )
                                .setGram(gram);
                          },
                        ),
                      ],
                      const SizedBox(height: 10),
                      Text(
                        '1 克 ${exchange.metal.label} = ${formatCny(exchange.selectedChannel.pricePerGram)} · ${exchange.selectedChannel.source} · ${_timeLabel(exchange.selectedChannel.updatedAt)} · 参考',
                        style: const TextStyle(
                          fontSize: 12,
                          color: Color(0xFF6E6A60),
                        ),
                      ),
                      const SizedBox(height: 5),
                      Text(
                        exchange.selectedChannel.hint,
                        style: const TextStyle(
                          fontSize: 11,
                          color: Color(0xFFB3AFA5),
                          height: 1.5,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _ExchangeField extends StatelessWidget {
  const _ExchangeField({
    required this.controller,
    required this.focusNode,
    required this.unit,
    required this.leading,
    required this.onChanged,
  });

  final TextEditingController controller;
  final FocusNode focusNode;
  final String unit;
  final String leading;
  final ValueChanged<String> onChanged;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 9),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(13),
        border: Border.all(color: const Color(0xFFE3D6B4), width: 0.5),
      ),
      child: Row(
        children: [
          Text(
            leading,
            style: const TextStyle(fontSize: 14, color: Color(0xFF8A8780)),
          ),
          const SizedBox(width: 8),
          Expanded(
            child: TextField(
              controller: controller,
              focusNode: focusNode,
              keyboardType: const TextInputType.numberWithOptions(
                decimal: true,
              ),
              textAlign: TextAlign.right,
              decoration: const InputDecoration(
                border: InputBorder.none,
                isDense: true,
                contentPadding: EdgeInsets.zero,
              ),
              style: const TextStyle(fontSize: 21, fontWeight: FontWeight.w600),
              onChanged: onChanged,
            ),
          ),
          const SizedBox(width: 8),
          Text(
            unit,
            style: const TextStyle(fontSize: 14, color: Color(0xFF8A8780)),
          ),
        ],
      ),
    );
  }
}

class _PeriodPill extends StatelessWidget {
  const _PeriodPill({
    required this.label,
    required this.selected,
    required this.onTap,
  });

  final String label;
  final bool selected;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return PrototypePill(label: label, selected: selected, onTap: onTap);
  }
}

class _MetalTab extends StatelessWidget {
  const _MetalTab({
    required this.label,
    required this.selected,
    required this.onTap,
  });

  final String label;
  final bool selected;
  final VoidCallback onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      borderRadius: BorderRadius.circular(12),
      child: Container(
        height: 32,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: selected ? const Color(0xFFF6ECD6) : Colors.white,
          borderRadius: BorderRadius.circular(12),
          border: Border.all(
            color: selected ? const Color(0xFFE3D6B4) : const Color(0xFFE6E1D8),
            width: 0.5,
          ),
        ),
        child: Text(
          label,
          style: TextStyle(
            fontSize: 13,
            fontWeight: selected ? FontWeight.w600 : FontWeight.w500,
            color: selected ? const Color(0xFF7A5B12) : const Color(0xFF6E6A60),
          ),
        ),
      ),
    );
  }
}

class _ChangeChip extends StatelessWidget {
  const _ChangeChip({
    required this.amount,
    required this.percent,
    required this.upColor,
    required this.downColor,
    required this.upBackground,
    required this.downBackground,
  });

  final double amount;
  final double percent;
  final Color upColor;
  final Color downColor;
  final Color upBackground;
  final Color downBackground;

  @override
  Widget build(BuildContext context) {
    final positive = amount >= 0;
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
      decoration: BoxDecoration(
        color: positive ? upBackground : downBackground,
        borderRadius: BorderRadius.circular(999),
      ),
      child: Text(
        '${positive ? '↑' : '↓'}¥${amount.abs().toStringAsFixed(2)} · ${positive ? '+' : '-'}${percent.abs().toStringAsFixed(2)}%',
        style: TextStyle(
          fontSize: 13,
          fontWeight: FontWeight.w600,
          color: positive ? upColor : downColor,
        ),
      ),
    );
  }
}

Future<void> _showPriceAlertSheet(BuildContext context, MetalType metal) async {
  var dir = 'up';
  final controller = TextEditingController(text: '960.00');
  try {
    await showModalBottomSheet<void>(
      context: context,
      backgroundColor: Colors.white,
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(22)),
      ),
      builder: (ctx) {
        return StatefulBuilder(
          builder: (ctx, setState) {
            return SafeArea(
              child: Padding(
                padding: EdgeInsets.only(
                  bottom: MediaQuery.viewInsetsOf(ctx).bottom,
                ),
                child: Padding(
                  padding: const EdgeInsets.fromLTRB(20, 8, 20, 24),
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Center(
                        child: Container(
                          width: 38,
                          height: 4,
                          margin: const EdgeInsets.only(bottom: 14),
                          decoration: BoxDecoration(
                            color: const Color(0xFFE3DFD4),
                            borderRadius: BorderRadius.circular(999),
                          ),
                        ),
                      ),
                      const Text(
                        '设置到价提醒',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w600,
                        ),
                      ),
                      const SizedBox(height: 4),
                      Text(
                        '${metal.label} 到价时提醒你',
                        style: const TextStyle(
                          fontSize: 12,
                          color: Color(0xFF8A8780),
                        ),
                      ),
                      const SizedBox(height: 14),
                      Row(
                        children: [
                          Expanded(
                            child: GestureDetector(
                              onTap: () => setState(() => dir = 'up'),
                              child: Container(
                                padding: const EdgeInsets.symmetric(
                                  vertical: 10,
                                ),
                                decoration: BoxDecoration(
                                  color: dir == 'up'
                                      ? const Color(0xFFF6ECD6)
                                      : Colors.white,
                                  borderRadius: BorderRadius.circular(10),
                                  border: Border.all(
                                    color: dir == 'up'
                                        ? const Color(0xFFE3D6B4)
                                        : const Color(0xFFECEAE3),
                                    width: 0.5,
                                  ),
                                ),
                                child: const Text(
                                  '涨到',
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    fontSize: 13,
                                    fontWeight: FontWeight.w600,
                                  ),
                                ),
                              ),
                            ),
                          ),
                          const SizedBox(width: 8),
                          Expanded(
                            child: GestureDetector(
                              onTap: () => setState(() => dir = 'down'),
                              child: Container(
                                padding: const EdgeInsets.symmetric(
                                  vertical: 10,
                                ),
                                decoration: BoxDecoration(
                                  color: dir == 'down'
                                      ? const Color(0xFFF6ECD6)
                                      : Colors.white,
                                  borderRadius: BorderRadius.circular(10),
                                  border: Border.all(
                                    color: dir == 'down'
                                        ? const Color(0xFFE3D6B4)
                                        : const Color(0xFFECEAE3),
                                    width: 0.5,
                                  ),
                                ),
                                child: const Text(
                                  '跌到',
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    fontSize: 13,
                                    fontWeight: FontWeight.w600,
                                  ),
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 14),
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 13,
                          vertical: 10,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(13),
                          border: Border.all(
                            color: const Color(0xFFE3D6B4),
                            width: 0.5,
                          ),
                        ),
                        child: Row(
                          children: [
                            const Text(
                              '¥',
                              style: TextStyle(
                                fontSize: 14,
                                color: Color(0xFF8A8780),
                              ),
                            ),
                            const SizedBox(width: 8),
                            Expanded(
                              child: TextField(
                                controller: controller,
                                keyboardType:
                                    const TextInputType.numberWithOptions(
                                      decimal: true,
                                    ),
                                textAlign: TextAlign.right,
                                decoration: const InputDecoration(
                                  border: InputBorder.none,
                                  isDense: true,
                                ),
                                style: const TextStyle(
                                  fontSize: 20,
                                  fontWeight: FontWeight.w600,
                                ),
                              ),
                            ),
                            const SizedBox(width: 8),
                            const Text(
                              '元/克',
                              style: TextStyle(
                                fontSize: 13,
                                color: Color(0xFF8A8780),
                              ),
                            ),
                          ],
                        ),
                      ),
                      const SizedBox(height: 16),
                      FilledButton(
                        onPressed: () {
                          Navigator.of(ctx).pop();
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(
                              content: Text(
                                '已设到价提醒 · $metal ${dir == 'up' ? '涨到' : '跌到'} ¥${controller.text}',
                              ),
                            ),
                          );
                        },
                        child: const Text('完成'),
                      ),
                    ],
                  ),
                ),
              ),
            );
          },
        );
      },
    );
  } finally {
    controller.dispose();
  }
}

String _timeLabel(DateTime value) {
  return '${value.hour.toString().padLeft(2, '0')}:${value.minute.toString().padLeft(2, '0')}';
}
