import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../core/network/dio_client.dart';
import '../data/models/asset/recharge_order.dart';
import '../data/models/asset/recharge_record.dart';
import '../data/services/asset_service.dart';
import '../data/services/recharge_service.dart';

// ── On-chain deposit (order flow + WalletConnect) ───────────────────

class DepositState {
  final List<RechargeParentCoin> parentCoins;
  final List<RechargeFlatNetworkOption> flatNetworks;
  final int selectedParentIndex;
  final int selectedFlatIndex;
  final RechargeOrderDetail? currentOrder;
  final bool loadingParents;
  final bool childrenLoading;
  final bool orderSubmitting;
  final bool hashSubmitting;
  final bool walletPayBusy;
  final String? errorMessage;

  const DepositState({
    this.parentCoins = const [],
    this.flatNetworks = const [],
    this.selectedParentIndex = 0,
    this.selectedFlatIndex = 0,
    this.currentOrder,
    this.loadingParents = false,
    this.childrenLoading = false,
    this.orderSubmitting = false,
    this.hashSubmitting = false,
    this.walletPayBusy = false,
    this.errorMessage,
  });

  RechargeParentCoin? get selectedParent =>
      parentCoins.isNotEmpty && selectedParentIndex < parentCoins.length
          ? parentCoins[selectedParentIndex]
          : null;

  RechargeFlatNetworkOption? get selectedNetwork =>
      flatNetworks.isNotEmpty && selectedFlatIndex < flatNetworks.length
          ? flatNetworks[selectedFlatIndex]
          : null;

  DepositState copyWith({
    List<RechargeParentCoin>? parentCoins,
    List<RechargeFlatNetworkOption>? flatNetworks,
    int? selectedParentIndex,
    int? selectedFlatIndex,
    RechargeOrderDetail? currentOrder,
    bool? loadingParents,
    bool? childrenLoading,
    bool? orderSubmitting,
    bool? hashSubmitting,
    bool? walletPayBusy,
    String? errorMessage,
    bool clearError = false,
    bool clearOrder = false,
  }) {
    return DepositState(
      parentCoins: parentCoins ?? this.parentCoins,
      flatNetworks: flatNetworks ?? this.flatNetworks,
      selectedParentIndex: selectedParentIndex ?? this.selectedParentIndex,
      selectedFlatIndex: selectedFlatIndex ?? this.selectedFlatIndex,
      currentOrder: clearOrder ? null : (currentOrder ?? this.currentOrder),
      loadingParents: loadingParents ?? this.loadingParents,
      childrenLoading: childrenLoading ?? this.childrenLoading,
      orderSubmitting: orderSubmitting ?? this.orderSubmitting,
      hashSubmitting: hashSubmitting ?? this.hashSubmitting,
      walletPayBusy: walletPayBusy ?? this.walletPayBusy,
      errorMessage: clearError ? null : (errorMessage ?? this.errorMessage),
    );
  }
}

class DepositNotifier extends Notifier<DepositState> {
  @override
  DepositState build() {
    Future.microtask(loadParentCoins);
    return const DepositState(loadingParents: true);
  }

  Future<void> loadParentCoins() async {
    state = state.copyWith(loadingParents: true, clearError: true);
    try {
      final dio = ref.read(dioClientProvider);
      final list = await RechargeService(dio).getRechargeParents();
      var idx = state.selectedParentIndex;
      if (idx >= list.length) {
        idx = 0;
      }
      state = state.copyWith(
        parentCoins: list,
        selectedParentIndex: idx,
        loadingParents: false,
        clearError: true,
      );
      if (list.isNotEmpty) {
        await loadChildrenForParent(list[idx].name);
      } else {
        state = state.copyWith(flatNetworks: [], selectedFlatIndex: 0);
      }
    } catch (e) {
      state = state.copyWith(
        loadingParents: false,
        errorMessage: e.toString(),
        parentCoins: [],
        flatNetworks: [],
      );
    }
  }

  Future<void> loadChildrenForParent(String coinName) async {
    state = state.copyWith(childrenLoading: true, clearError: true);
    try {
      final dio = ref.read(dioClientProvider);
      final nets =
          await RechargeService(dio).getChildrenWithNetwork(coinName: coinName);
      state = state.copyWith(
        flatNetworks: nets,
        selectedFlatIndex: 0,
        childrenLoading: false,
        clearError: true,
      );
    } catch (e) {
      state = state.copyWith(
        childrenLoading: false,
        errorMessage: e.toString(),
        flatNetworks: [],
      );
    }
  }

  Future<void> selectParent(int index) async {
    if (index < 0 || index >= state.parentCoins.length) {
      return;
    }
    state = state.copyWith(selectedParentIndex: index);
    final p = state.parentCoins[index];
    await loadChildrenForParent(p.name);
  }

  void selectFlatNetwork(int index) {
    if (index >= 0 && index < state.flatNetworks.length) {
      state = state.copyWith(selectedFlatIndex: index);
    }
  }

  Future<void> createRechargeOrder(String amount) async {
    final opt = state.selectedNetwork;
    if (opt == null) {
      state = state.copyWith(errorMessage: '请先选择充值网络');
      return;
    }
    state = state.copyWith(orderSubmitting: true, clearError: true);
    try {
      final dio = ref.read(dioClientProvider);
      final order = await RechargeService(dio).createRechargeOrder(
        coinName: opt.coinName,
        networkConfigId: opt.networkConfigId,
        amount: amount,
      );
      state = state.copyWith(
        currentOrder: order,
        orderSubmitting: false,
        clearError: true,
      );
    } catch (e) {
      state = state.copyWith(
        orderSubmitting: false,
        errorMessage: e.toString(),
      );
    }
  }

  Future<void> submitTxHash(String txHash) async {
    final o = state.currentOrder;
    if (o == null || o.orderNo.isEmpty) {
      return;
    }
    state = state.copyWith(hashSubmitting: true, clearError: true);
    try {
      final dio = ref.read(dioClientProvider);
      final updated = await RechargeService(dio).submitTxHash(
        orderNo: o.orderNo,
        txHash: txHash,
      );
      state = state.copyWith(
        currentOrder: updated,
        hashSubmitting: false,
        clearError: true,
      );
    } catch (e) {
      state = state.copyWith(
        hashSubmitting: false,
        errorMessage: e.toString(),
      );
    }
  }

  void clearCurrentOrder() {
    state = state.copyWith(clearOrder: true);
  }

  void setWalletPayBusy(bool v) {
    state = state.copyWith(walletPayBusy: v);
  }

  void clearError() {
    state = state.copyWith(clearError: true);
  }

  Future<void> refresh() => loadParentCoins();
}

final depositProvider =
    NotifierProvider<DepositNotifier, DepositState>(DepositNotifier.new);

// ── Recharge History (legacy list API) ──────────────────────────────

class RechargeHistoryState {
  final List<RechargeRecord> records;
  final bool isLoading;
  final bool hasMore;
  final int currentPage;
  final String? errorMessage;

  const RechargeHistoryState({
    this.records = const [],
    this.isLoading = false,
    this.hasMore = true,
    this.currentPage = 1,
    this.errorMessage,
  });

  RechargeHistoryState copyWith({
    List<RechargeRecord>? records,
    bool? isLoading,
    bool? hasMore,
    int? currentPage,
    String? errorMessage,
  }) =>
      RechargeHistoryState(
        records: records ?? this.records,
        isLoading: isLoading ?? this.isLoading,
        hasMore: hasMore ?? this.hasMore,
        currentPage: currentPage ?? this.currentPage,
        errorMessage: errorMessage,
      );
}

class RechargeHistoryNotifier extends Notifier<RechargeHistoryState> {
  static const _pageSize = 10;

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

  Future<void> _loadFirst() async {
    state = state.copyWith(isLoading: true, errorMessage: null);
    try {
      final dio = ref.read(dioClientProvider);
      final records =
          await AssetService(dio).getRechargeList(pageNo: 1, pageSize: _pageSize);
      state = state.copyWith(
        records: records,
        isLoading: false,
        currentPage: 1,
        hasMore: records.length >= _pageSize,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, errorMessage: e.toString());
    }
  }

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

  Future<void> loadMore() async {
    if (state.isLoading || !state.hasMore) {
      return;
    }
    state = state.copyWith(isLoading: true);
    try {
      final nextPage = state.currentPage + 1;
      final dio = ref.read(dioClientProvider);
      final records = await AssetService(dio)
          .getRechargeList(pageNo: nextPage, pageSize: _pageSize);
      state = state.copyWith(
        records: [...state.records, ...records],
        isLoading: false,
        currentPage: nextPage,
        hasMore: records.length >= _pageSize,
      );
    } catch (e) {
      state = state.copyWith(isLoading: false, errorMessage: e.toString());
    }
  }
}

final rechargeHistoryProvider =
    NotifierProvider<RechargeHistoryNotifier, RechargeHistoryState>(
  RechargeHistoryNotifier.new,
);