import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../../../core/l10n/app_localizations.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/utils/number_format.dart';
import '../../../core/utils/top_toast.dart';
import '../../../core/utils/transfer_pair.dart';
import '../../../providers/transfer_provider.dart';
import '../../../providers/futures_provider.dart'
    show futuresProvider, futuresActiveSymbolProvider;

class TransferScreen extends ConsumerStatefulWidget {
  const TransferScreen({
    super.key,
    this.initialFrom,
    this.initialTo,
    this.initialSymbol,
    this.preferDefaultSymbol = false,
    this.spotTradingBridgeOnly = false,
  });

  final String? initialFrom;
  final String? initialTo;
  final String? initialSymbol;
  final bool preferDefaultSymbol;
  final bool spotTradingBridgeOnly;

  @override
  ConsumerState<TransferScreen> createState() => _TransferScreenState();
}

class _TransferScreenState extends ConsumerState<TransferScreen> {
  final _amountController = TextEditingController();
  bool _initialized = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) => _bootstrap());
  }

  Future<void> _bootstrap() async {
    if (_initialized) {
      return;
    }
    _initialized = true;
    await ref.read(transferProvider.notifier).init(
          TransferInitOptions(
            from: widget.initialFrom,
            to: widget.initialTo,
            defaultSymbol: widget.initialSymbol ?? 'USDT',
            preferDefaultSymbol: widget.preferDefaultSymbol,
            spotTradingBridgeOnly: widget.spotTradingBridgeOnly,
          ),
        );
  }

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

  @override
  Widget build(BuildContext context) {
    final state = ref.watch(transferProvider);
    final notifier = ref.read(transferProvider.notifier);
    final l10n = AppLocalizations.of(context)!;

    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: const Icon(Icons.chevron_left, size: 28),
          onPressed: () => context.pop(),
        ),
        title: Text(
          l10n.accountTransferTitle,
          style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
        ),
        centerTitle: true,
        actions: [
          IconButton(
            icon: const Icon(Icons.history, size: 22),
            onPressed: () => context.push('/asset/transfer/history'),
          ),
        ],
      ),
      body: _buildBody(context, state, notifier, l10n),
    );
  }

  Widget _buildBody(
    BuildContext context,
    TransferState state,
    TransferNotifier notifier,
    AppLocalizations l10n,
  ) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;

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

    if (state.errorMessage != null && state.legacyBalances.isEmpty) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(state.errorMessage!,
                style: TextStyle(color: cs.onSurface.withAlpha(153))),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: notifier.refresh,
              child: Text(l10n.retry),
            ),
          ],
        ),
      );
    }

    final fromBalance = state.fromBalance;

    return SingleChildScrollView(
      padding: const EdgeInsets.fromLTRB(16, 16, 16, 32),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (state.isSpotCoinTransfer) ...[
            _CoinSelector(
              coins: state.openCoins,
              selectedCoin: state.selectedCoin,
              loading: state.isLoadingCoins,
              onChanged: (coin) {
                notifier.selectCoin(coin);
                _amountController.clear();
                setState(() {});
              },
            ),
            const SizedBox(height: 16),
          ],
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: isDark
                  ? AppColors.darkBgSecondary
                  : AppColors.lightBgSecondary,
              borderRadius: BorderRadius.circular(12),
            ),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Expanded(
                  child: _TransferSide(
                    label: l10n.fromLabel,
                    walletType: state.fromType,
                    otherTypes: state.transferOtherTypes,
                    readonly: state.fromType == kWalletSpot,
                    onChanged: (type) {
                      notifier.setFromType(type);
                      _amountController.clear();
                      setState(() {});
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 28),
                  child: GestureDetector(
                    onTap: () {
                      notifier.swapAccounts();
                      _amountController.clear();
                      setState(() {});
                    },
                    child: Container(
                      width: 36,
                      height: 36,
                      decoration: BoxDecoration(
                        border: Border.all(color: cs.outline.withAlpha(60)),
                        borderRadius: BorderRadius.circular(18),
                      ),
                      child: Icon(Icons.swap_horiz,
                          size: 20, color: cs.onSurface),
                    ),
                  ),
                ),
                Expanded(
                  child: _TransferSide(
                    label: l10n.toLabel,
                    walletType: state.toType,
                    otherTypes: state.transferOtherTypes,
                    readonly: state.fromType == kWalletSwap ||
                        state.fromType == kWalletFollow ||
                        state.fromType == kWalletSpotTrading,
                    onChanged: (type) {
                      notifier.setToType(type);
                      _amountController.clear();
                      setState(() {});
                    },
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 8),
          Text(
            l10n.transferAvailableCoin(
              formatAmount(fromBalance.toDouble()),
              state.displayCoinUnit,
            ),
            style: TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 12),
          ),
          const SizedBox(height: 20),
          Container(
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: isDark
                  ? AppColors.darkBgSecondary
                  : AppColors.lightBgSecondary,
              borderRadius: BorderRadius.circular(12),
            ),
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Text(
                        state.isSpotCoinTransfer
                            ? l10n.transferAmountCoin(state.displayCoinUnit)
                            : l10n.transferAmount,
                        style: TextStyle(
                          color: cs.onSurface.withAlpha(153),
                          fontSize: 13,
                        ),
                      ),
                    ),
                    GestureDetector(
                      onTap: () {
                        _amountController.text = fromBalance.toString();
                        setState(() {});
                      },
                      child: Text(
                        l10n.all,
                        style: const TextStyle(
                          color: AppColors.brand,
                          fontSize: 13,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                TextField(
                  controller: _amountController,
                  keyboardType:
                      const TextInputType.numberWithOptions(decimal: true),
                  inputFormatters: [
                    FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,8}')),
                  ],
                  onChanged: (_) => setState(() {}),
                  style: TextStyle(color: cs.onSurface, fontSize: 16),
                  decoration: InputDecoration(
                    hintText: '0.00',
                    hintStyle: TextStyle(
                      color: cs.onSurface.withAlpha(100),
                      fontSize: 16,
                    ),
                    border: InputBorder.none,
                    enabledBorder: InputBorder.none,
                    focusedBorder: InputBorder.none,
                    filled: false,
                    isDense: true,
                    contentPadding: EdgeInsets.zero,
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 12),
          Text(
            l10n.transferFreeHint,
            style: TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 12),
          ),
          const SizedBox(height: 24),
          SizedBox(
            width: double.infinity,
            height: 50,
            child: ElevatedButton(
              onPressed: _canSubmit(state) ? _submit : null,
              style: ElevatedButton.styleFrom(
                backgroundColor: AppColors.brand,
                disabledBackgroundColor: AppColors.brand.withAlpha(80),
                foregroundColor: Colors.black,
                disabledForegroundColor: Colors.black.withAlpha(80),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(25),
                ),
              ),
              child: state.isSubmitting
                  ? const SizedBox(
                      width: 20,
                      height: 20,
                      child: CircularProgressIndicator(
                        strokeWidth: 2,
                        color: Colors.black,
                      ),
                    )
                  : Text(
                      l10n.confirmTransfer,
                      style: const TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
            ),
          ),
        ],
      ),
    );
  }

  bool _canSubmit(TransferState state) {
    if (state.isSubmitting || state.isLoadingCoins) {
      return false;
    }
    final amount = double.tryParse(_amountController.text.trim()) ?? 0;
    return amount > 0;
  }

  Future<void> _submit() async {
    final l10n = AppLocalizations.of(context)!;
    final amount = _amountController.text.trim();
    if (amount.isEmpty) {
      showTopToast(context, message: l10n.enterTransferAmount);
      return;
    }
    final notifier = ref.read(transferProvider.notifier);
    final success = await notifier.submit(amount);
    if (!mounted) {
      return;
    }
    if (success) {
      showTopToast(
        context,
        message: l10n.transferSuccess,
        backgroundColor: AppColors.success,
      );
      _amountController.clear();
      final activeSymbol = ref.read(futuresActiveSymbolProvider);
      if (activeSymbol.isNotEmpty) {
        ref.read(futuresProvider(activeSymbol).notifier).refreshWallet();
      }
      setState(() {});
      return;
    }
    final err = ref.read(transferProvider).errorMessage;
    if (err != null) {
      showTopToast(context, message: _mapError(err, l10n));
    }
  }

  String _mapError(String err, AppLocalizations l10n) {
    if (err == 'errSameAccount') {
      return l10n.transferSameAccountError;
    }
    if (err == 'errEnterAmount') {
      return l10n.enterTransferAmount;
    }
    if (err == 'errExceedBalance') {
      return l10n.errExceedBalance;
    }
    return err;
  }
}

class _TransferSide extends StatelessWidget {
  const _TransferSide({
    required this.label,
    required this.walletType,
    required this.otherTypes,
    required this.readonly,
    required this.onChanged,
  });

  final String label;
  final String walletType;
  final List<String> otherTypes;
  final bool readonly;
  final ValueChanged<String> onChanged;

  String _name(AppLocalizations l10n, String type) {
    switch (type) {
      case kWalletSpot:
        return l10n.fundAccount;
      case kWalletSwap:
        return l10n.futuresAccount;
      case kWalletFollow:
        return l10n.copyAccount;
      case kWalletSpotTrading:
        return l10n.spotTradingAccount;
      default:
        return type;
    }
  }

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final l10n = AppLocalizations.of(context)!;
    final displayType =
        readonly && walletType != kWalletSpot ? kWalletSpot : walletType;

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(label,
            style: TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 12)),
        const SizedBox(height: 8),
        if (readonly || otherTypes.length <= 1)
          Container(
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
            decoration: BoxDecoration(
              color: cs.surface.withAlpha(20),
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: cs.outline.withAlpha(40)),
            ),
            child: Text(
              _name(l10n, displayType),
              style: TextStyle(color: cs.onSurface.withAlpha(180), fontSize: 14),
            ),
          )
        else
          _WalletPicker(
            value: walletType,
            options: otherTypes,
            labelBuilder: (type) => _name(l10n, type),
            onChanged: onChanged,
          ),
      ],
    );
  }
}

class _WalletPicker extends StatelessWidget {
  const _WalletPicker({
    required this.value,
    required this.options,
    required this.labelBuilder,
    required this.onChanged,
  });

  final String value;
  final List<String> options;
  final String Function(String type) labelBuilder;
  final ValueChanged<String> onChanged;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    return GestureDetector(
      onTap: () => _showPicker(context),
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: cs.outline.withAlpha(60)),
        ),
        child: Row(
          children: [
            Expanded(
              child: Text(
                labelBuilder(value),
                style: TextStyle(color: cs.onSurface, fontSize: 14),
              ),
            ),
            Icon(Icons.keyboard_arrow_down,
                size: 18, color: cs.onSurface.withAlpha(120)),
          ],
        ),
      ),
    );
  }

  void _showPicker(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    showModalBottomSheet<void>(
      context: context,
      useRootNavigator: true,
      backgroundColor: cs.surface,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (sheetCtx) => SafeArea(
        child: LayoutBuilder(
          builder: (ctx, c) {
            const overhead = 8.0 + 4.0 + 16.0 + 8.0;
            final listMax = c.maxHeight.isFinite
                ? math.max(80.0, c.maxHeight - overhead)
                : 320.0;
            return Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const SizedBox(height: 8),
                Container(
                  width: 36,
                  height: 4,
                  decoration: BoxDecoration(
                    color: cs.outline.withAlpha(60),
                    borderRadius: BorderRadius.circular(2),
                  ),
                ),
                const SizedBox(height: 16),
                ConstrainedBox(
                  constraints: BoxConstraints(maxHeight: listMax),
                  child: ListView(
                    shrinkWrap: true,
                    children: options.map((type) {
                      final selected = type == value;
                      return ListTile(
                        title: Text(labelBuilder(type)),
                        trailing: selected
                            ? Icon(Icons.check, color: cs.onSurface)
                            : null,
                        onTap: () {
                          onChanged(type);
                          Navigator.pop(sheetCtx);
                        },
                      );
                    }).toList(),
                  ),
                ),
                const SizedBox(height: 8),
              ],
            );
          },
        ),
      ),
    );
  }
}

class _CoinSelector extends StatelessWidget {
  const _CoinSelector({
    required this.coins,
    required this.selectedCoin,
    required this.loading,
    required this.onChanged,
  });

  final List<String> coins;
  final String selectedCoin;
  final bool loading;
  final ValueChanged<String> onChanged;

  @override
  Widget build(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    final isDark = Theme.of(context).brightness == Brightness.dark;
    final canSelect = coins.length > 1 && !loading;

    return GestureDetector(
      onTap: canSelect ? () => _showPicker(context) : null,
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
        decoration: BoxDecoration(
          color:
              isDark ? AppColors.darkBgSecondary : AppColors.lightBgSecondary,
          borderRadius: BorderRadius.circular(12),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              AppLocalizations.of(context)!.selectTransferCoin,
              style: TextStyle(color: cs.onSurface.withAlpha(120), fontSize: 12),
            ),
            const SizedBox(height: 8),
            Row(
              children: [
                Text(
                  selectedCoin,
                  style: TextStyle(
                    color: cs.onSurface,
                    fontSize: 16,
                    fontWeight: FontWeight.w600,
                  ),
                ),
                const Spacer(),
                if (loading)
                  const SizedBox(
                    width: 16,
                    height: 16,
                    child: CircularProgressIndicator(strokeWidth: 2),
                  )
                else if (canSelect)
                  Icon(Icons.keyboard_arrow_down,
                      size: 20, color: cs.onSurface.withAlpha(120)),
              ],
            ),
          ],
        ),
      ),
    );
  }

  void _showPicker(BuildContext context) {
    final cs = Theme.of(context).colorScheme;
    showModalBottomSheet<void>(
      context: context,
      useRootNavigator: true,
      backgroundColor: cs.surface,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (sheetCtx) => SafeArea(
        child: ListView(
          shrinkWrap: true,
          children: coins.map((coin) {
            final isSelected = coin == selectedCoin;
            return ListTile(
              title: Text(coin),
              trailing:
                  isSelected ? Icon(Icons.check, color: cs.onSurface) : null,
              onTap: () {
                onChanged(coin);
                Navigator.pop(sheetCtx);
              },
            );
          }).toList(),
        ),
      ),
    );
  }
}
