import 'dart:async';

import 'package:decimal/decimal.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../core/network/dio_client.dart';
import '../core/utils/dialog_utils.dart' show extractErrorMessage;
import '../data/models/asset/account_auth.dart';
import '../data/models/asset/deposit_wallet.dart';
import '../data/models/asset/withdraw_balance.dart';
import '../data/models/asset/withdraw_record.dart';
import '../data/services/asset_service.dart';
import '../data/services/withdraw_service.dart';

// ══════════════════════════════════════════════════════════════
// Withdraw State
// ══════════════════════════════════════════════════════════════

class WithdrawState {
  /// 0=链上提币, 1=内部转账
  final int tabIndex;

  /// 钱包列表（含网络信息，复用充币的 DepositWallet）
  final List<DepositWallet> usdtWallets;

  /// 当前选中的网络索引
  final int selectedNetworkIndex;

  /// 可用余额
  final WithdrawBalance? balance;

  /// 认证信息
  final AccountAuth? auth;

  /// 验证码倒计时秒数（0=可发送）
  final int codeCountdown;

  /// 提交中
  final bool isSubmitting;

  final bool isLoading;
  final String? errorMessage;

  /// 内部转账最小金额（USDT 基础配置，null 表示未加载）
  final Decimal? _transferMinAmount;

  const WithdrawState({
    this.tabIndex = 0,
    this.usdtWallets = const [],
    this.selectedNetworkIndex = -1,
    this.balance,
    this.auth,
    Decimal? transferMinAmount,
    this.codeCountdown = 0,
    this.isSubmitting = false,
    this.isLoading = false,
    this.errorMessage,
  }) : _transferMinAmount = transferMinAmount;

  /// 当前选中的钱包（链上提币模式下使用）
  DepositWallet? get selectedWallet =>
      selectedNetworkIndex >= 0 && usdtWallets.isNotEmpty && selectedNetworkIndex < usdtWallets.length
          ? usdtWallets[selectedNetworkIndex]
          : null;

  /// 当前币种信息
  WalletCoin? get currentCoin => selectedWallet?.coin;

  /// 网络名称列表
  List<String> get networkNames =>
      usdtWallets.map((w) => w.coin?.networkName ?? '').toList();

  /// 链上提币的 unit（币种代号）
  String get onChainUnit => currentCoin?.code ?? 'TUSDT';

  /// 手续费（withdrawFeeValue）
  Decimal get fee => currentCoin?.fee ?? Decimal.zero;

  /// 链上提币最小额
  Decimal get minWithdrawAmount => currentCoin?.minWithdrawAmount ?? Decimal.zero;

  /// 内部转账最小额（USDT 基础配置）
  Decimal get transferMinAmount => _transferMinAmount ?? Decimal.zero;

  /// 当前模式下的最小额（链上 or 内部转账）
  Decimal get currentMinAmount => tabIndex == 0 ? minWithdrawAmount : transferMinAmount;

  /// 可提现余额（链上提币）
  Decimal get withdrawableBalance => balance?.withdrawableBalance ?? Decimal.zero;

  /// 可转账余额（内部转账）
  Decimal get transferableBalance => balance?.transferableBalance ?? Decimal.zero;

  /// 当前可用余额（根据 Tab 决定）
  Decimal get availableBalance =>
      tabIndex == 0 ? withdrawableBalance : transferableBalance;

  /// 是否已绑定 Google 验证
  bool get isGoogleBound => auth?.isGoogleVerified ?? false;

  WithdrawState copyWith({
    int? tabIndex,
    List<DepositWallet>? usdtWallets,
    int? selectedNetworkIndex,
    WithdrawBalance? balance,
    AccountAuth? auth,
    Decimal? transferMinAmount,
    int? codeCountdown,
    bool? isSubmitting,
    bool? isLoading,
    String? errorMessage,
  }) =>
      WithdrawState(
        tabIndex: tabIndex ?? this.tabIndex,
        usdtWallets: usdtWallets ?? this.usdtWallets,
        selectedNetworkIndex: selectedNetworkIndex ?? this.selectedNetworkIndex,
        balance: balance ?? this.balance,
        auth: auth ?? this.auth,
        transferMinAmount: transferMinAmount ?? _transferMinAmount,
        codeCountdown: codeCountdown ?? this.codeCountdown,
        isSubmitting: isSubmitting ?? this.isSubmitting,
        isLoading: isLoading ?? this.isLoading,
        errorMessage: errorMessage,
      );
}

// ══════════════════════════════════════════════════════════════
// Withdraw Notifier
// ══════════════════════════════════════════════════════════════

class WithdrawNotifier extends Notifier<WithdrawState> {
  Timer? _countdownTimer;

  @override
  WithdrawState build() {
    ref.onDispose(() => _countdownTimer?.cancel());
    Future.microtask(_load);
    return const WithdrawState(isLoading: true);
  }

  Future<void> _load() async {
    state = state.copyWith(isLoading: true, errorMessage: null, selectedNetworkIndex: -1);
    try {
      final dio = ref.read(dioClientProvider);
      final assetService = AssetService(dio);
      final withdrawService = WithdrawService(dio);

      // 并发请求：钱包地址 + 可用余额 + 认证信息 + 内部转账最小额
      final results = await Future.wait([
        assetService.getWalletAddresses(),
        withdrawService.getBalance('usdt'),
        withdrawService.getSecuritySetting(),
        withdrawService.getTransferMinAmount(),
      ]);

      final wallets = results[0] as List<DepositWallet>;
      final balance = results[1] as WithdrawBalance;
      final auth = results[2] as AccountAuth;
      final transferMinAmount = results[3] as Decimal;

      // 过滤 USDT 钱包，TRC20 排最前
      const networkOrder = {'TRC20': 0, 'ERC20': 1, 'BEP20': 2};
      final usdtWallets = wallets
          .where((w) => w.coin != null && w.coin!.code.contains('USDT'))
          .toList()
        ..sort((a, b) {
          final oa = networkOrder[a.coin!.networkName] ?? 99;
          final ob = networkOrder[b.coin!.networkName] ?? 99;
          return oa.compareTo(ob);
        });

      state = state.copyWith(
        usdtWallets: usdtWallets,
        balance: balance,
        auth: auth,
        transferMinAmount: transferMinAmount,
        selectedNetworkIndex: -1,
        isLoading: false,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, errorMessage: extractErrorMessage(e));
    }
  }

  Future<void> refresh() => _load();

  void setTab(int index) {
    state = state.copyWith(tabIndex: index);
  }

  void selectNetwork(int index) {
    state = state.copyWith(selectedNetworkIndex: index);
  }

  /// 发送邮箱验证码，返回错误信息（null 表示成功）
  Future<String?> sendEmailCode({
    required String address,
    required String amount,
  }) async {
    if (state.tabIndex == 0 && state.selectedNetworkIndex < 0) return 'errSelectNetwork';
    if (address.isEmpty) return 'errEnterAddress';
    if (amount.isEmpty) return 'errEnterAmount';
    try {
      final dio = ref.read(dioClientProvider);
      await WithdrawService(dio).sendWithdrawEmailCode(
        unit: state.tabIndex == 1 ? 'USDT' : state.onChainUnit,
        address: address,
        amount: amount,
      );
      // 启动 60 秒倒计时
      state = state.copyWith(codeCountdown: 60);
      _countdownTimer?.cancel();
      _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
        final remaining = state.codeCountdown - 1;
        if (remaining <= 0) {
          timer.cancel();
          state = state.copyWith(codeCountdown: 0);
        } else {
          state = state.copyWith(codeCountdown: remaining);
        }
      });
      return null;
    } catch (e) {
      return extractErrorMessage(e);
    }
  }

  /// 链上提币提交
  Future<bool> submitOnChainWithdraw({
    required String address,
    required String amount,
    required String jyPassword,
    required String vcode,
    required String vcode2,
  }) async {
    state = state.copyWith(isSubmitting: true, errorMessage: null);
    try {
      final dio = ref.read(dioClientProvider);
      await WithdrawService(dio).withdrawApply(
        unit: state.onChainUnit,
        amount: amount,
        address: address,
        fee: state.fee.toString(),
        vcode: vcode,
        jyPassword: jyPassword,
        vcode2: vcode2,
      );
      state = state.copyWith(isSubmitting: false);
      // 刷新余额
      _load();
      return true;
    } catch (e) {
      state = state.copyWith(isSubmitting: false, errorMessage: extractErrorMessage(e));
      return false;
    }
  }

  /// 内部转账提交
  Future<bool> submitInternalTransfer({
    required String address,
    required String amount,
    required String jyPassword,
    required String vcode,
    required String vcode2,
  }) async {
    state = state.copyWith(isSubmitting: true, errorMessage: null);
    try {
      final dio = ref.read(dioClientProvider);
      await WithdrawService(dio).internalTransfer(
        unit: 'USDT', // 内部转账用币种名
        amount: amount,
        address: address,
        vcode: vcode,
        jyPassword: jyPassword,
        vcode2: vcode2,
      );
      state = state.copyWith(isSubmitting: false);
      _load();
      return true;
    } catch (e) {
      state = state.copyWith(isSubmitting: false, errorMessage: extractErrorMessage(e));
      return false;
    }
  }

  /// 表单校验
  String? validate({
    required String address,
    required String amount,
    required String jyPassword,
    required String vcode,
    required String vcode2,
  }) {
    if (state.tabIndex == 0 && state.selectedNetworkIndex < 0) return 'errSelectNetwork';
    if (address.isEmpty) return 'errEnterAddress';
    if (amount.isEmpty) return 'errEnterAmount';
    if (jyPassword.isEmpty) return 'errEnterFundPassword';
    if (vcode.isEmpty) return 'errEnterVerifyCode';
    if (!state.isGoogleBound) return 'errBindGoogleFirst';
    if (vcode2.isEmpty) return 'errEnterGoogleCode';

    final amountDecimal = Decimal.tryParse(amount);
    if (amountDecimal == null) return 'errAmountFormat';
    if (amountDecimal < state.currentMinAmount) {
      return state.tabIndex == 0
          ? 'errMinWithdraw:${state.currentMinAmount}'
          : 'errMinTransfer:${state.currentMinAmount}';
    }
    if (amountDecimal > state.availableBalance) {
      return 'errExceedBalance';
    }
    return null;
  }
}

final withdrawProvider = NotifierProvider<WithdrawNotifier, WithdrawState>(
  WithdrawNotifier.new,
);

// ══════════════════════════════════════════════════════════════
// Withdraw History
// ══════════════════════════════════════════════════════════════

class WithdrawHistoryState {
  final List<WithdrawRecord> records;
  final bool isLoading;
  final bool hasMore;
  /// 链上提币当前页（后端 page 从 0 开始）
  final int withdrawPage;
  /// 内部转账当前页（后端 pageNo 从 0 开始）
  final int transferPage;
  final String? errorMessage;

  const WithdrawHistoryState({
    this.records = const [],
    this.isLoading = false,
    this.hasMore = true,
    this.withdrawPage = 0,
    this.transferPage = 0,
    this.errorMessage,
  });

  WithdrawHistoryState copyWith({
    List<WithdrawRecord>? records,
    bool? isLoading,
    bool? hasMore,
    int? withdrawPage,
    int? transferPage,
    String? errorMessage,
  }) =>
      WithdrawHistoryState(
        records: records ?? this.records,
        isLoading: isLoading ?? this.isLoading,
        hasMore: hasMore ?? this.hasMore,
        withdrawPage: withdrawPage ?? this.withdrawPage,
        transferPage: transferPage ?? this.transferPage,
        errorMessage: errorMessage,
      );
}

class WithdrawHistoryNotifier extends Notifier<WithdrawHistoryState> {
  static const _pageSize = 10;

  @override
  WithdrawHistoryState build() {
    Future.microtask(_loadFirst);
    return const WithdrawHistoryState(isLoading: true);
  }

  Future<void> _loadFirst() async {
    state = state.copyWith(isLoading: true, errorMessage: null);
    try {
      final service = WithdrawService(ref.read(dioClientProvider));
      final results = await Future.wait([
        service.getWithdrawRecords(page: 0, pageSize: _pageSize),
        service.getTransferRecords(pageNo: 0, pageSize: _pageSize),
      ]);
      final withdrawRecords = results[0] as List<WithdrawRecord>;
      final transferRecords = (results[1] as List<WithdrawRecord>)
          .map((r) => r.copyWith(isTransfer: true))
          .toList();
      final all = _merge(withdrawRecords, transferRecords);
      state = state.copyWith(
        records: all,
        isLoading: false,
        withdrawPage: 0,
        transferPage: 0,
        hasMore: withdrawRecords.length >= _pageSize ||
            transferRecords.length >= _pageSize,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, errorMessage: extractErrorMessage(e));
    }
  }

  Future<void> refresh() => _loadFirst();

  Future<void> loadMore() async {
    if (state.isLoading || !state.hasMore) return;
    state = state.copyWith(isLoading: true);
    try {
      final service = WithdrawService(ref.read(dioClientProvider));
      final nextW = state.withdrawPage + 1;
      final nextT = state.transferPage + 1;
      final results = await Future.wait([
        service.getWithdrawRecords(page: nextW, pageSize: _pageSize),
        service.getTransferRecords(pageNo: nextT, pageSize: _pageSize),
      ]);
      final withdrawRecords = results[0] as List<WithdrawRecord>;
      final transferRecords = (results[1] as List<WithdrawRecord>)
          .map((r) => r.copyWith(isTransfer: true))
          .toList();
      final appended = _merge(withdrawRecords, transferRecords);
      state = state.copyWith(
        records: [...state.records, ...appended],
        isLoading: false,
        withdrawPage: nextW,
        transferPage: nextT,
        hasMore: withdrawRecords.length >= _pageSize ||
            transferRecords.length >= _pageSize,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, errorMessage: extractErrorMessage(e));
    }
  }

  /// 合并两类记录，按 createTime 倒序
  List<WithdrawRecord> _merge(
    List<WithdrawRecord> withdrawRecords,
    List<WithdrawRecord> transferRecords,
  ) {
    final all = [...withdrawRecords, ...transferRecords];
    all.sort((a, b) => b.createTime.compareTo(a.createTime));
    return all;
  }

  /// 取消链上提现
  Future<bool> cancelWithdraw(String id) async {
    try {
      final dio = ref.read(dioClientProvider);
      await WithdrawService(dio).cancelWithdraw(id);
      await refresh();
      return true;
    } catch (e) {
      state = state.copyWith(errorMessage: extractErrorMessage(e));
      return false;
    }
  }
}

final withdrawHistoryProvider =
    NotifierProvider<WithdrawHistoryNotifier, WithdrawHistoryState>(
  WithdrawHistoryNotifier.new,
);
