import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

import '../../core/utils/spot_transfer_asset.dart';
import '../models/finance/airdrop_eligibility.dart';
import '../models/finance/airdrop_record_item.dart';
import '../models/finance/staking_config.dart';
import '../models/finance/staking_order_item.dart';
import '../models/finance/staking_team_overview.dart';
import '../models/finance/staking_wallet_balance.dart';

class StakingService {
  const StakingService(this._dio);

  final Dio _dio;

  void _log(String message) {
    if (kDebugMode) {
      debugPrint('[Airdrop][Service] $message');
    }
  }

  /// 与 Web `STAKING_COIN_UNIT` / `stakingCoinUnit()` 默认币种一致
  static const stakingCoinUnit = 'IBIT';

  Future<List<StakingConfig>> getConfigs() async {
    final resp =
        await _dio.post<Map<String, dynamic>>('uc/staking/config/list');
    final raw = resp.data?['data'];
    if (raw is List) {
      return raw
          .whereType<Map<String, dynamic>>()
          .map(StakingConfig.fromJson)
          .toList();
    }
    return const [];
  }

  Future<StakingConfig?> getMinOpenConfig() async {
    final resp =
        await _dio.post<Map<String, dynamic>>('uc/staking/config/min-open');
    final raw = resp.data?['data'];
    if (raw is Map<String, dynamic>) {
      return StakingConfig.fromJson(raw);
    }
    return null;
  }

  Future<void> submitStake({
    required int configId,
    required String amount,
  }) async {
    await _dio.post<dynamic>(
      'uc/staking/stake',
      data: {'configId': configId, 'amount': amount},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
  }

  /// 分页查询我的质押订单（对齐 Web fetchStakingOrders）
  Future<StakingOrderPage> getStakingOrders({
    required int pageNo,
    int pageSize = 5,
    String? status,
  }) async {
    final data = <String, dynamic>{
      'pageNo': pageNo,
      'pageSize': pageSize,
    };
    if (status != null && status.isNotEmpty) {
      data['status'] = status;
    }
    final resp = await _dio.post<Map<String, dynamic>>(
      'uc/staking/orders',
      data: data,
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
    final raw = resp.data?['data'];
    if (raw is! Map<String, dynamic>) {
      return const StakingOrderPage(content: [], totalPages: 0, pageNo: 1);
    }
    final contentRaw = raw['content'];
    final content = contentRaw is List
        ? contentRaw
            .whereType<Map<String, dynamic>>()
            .map(StakingOrderItem.fromJson)
            .toList()
        : <StakingOrderItem>[];
    final totalPages = int.tryParse('${raw['totalPages'] ?? 0}') ?? 0;
    final rawPageNo = int.tryParse('${raw['pageNo'] ?? ''}');
    final rawNumber = int.tryParse('${raw['number'] ?? ''}');
    final parsedPageNo = rawPageNo ?? ((rawNumber ?? (pageNo - 1)) + 1);
    return StakingOrderPage(
      content: content,
      totalPages: totalPages,
      pageNo: parsedPageNo,
    );
  }

  /// 查询质押团队总览（对齐 Web `fetchStakingTeamOverview`）
  Future<StakingTeamOverview> getTeamOverview() async {
    final resp = await _dio.post<Map<String, dynamic>>(
      'uc/staking/team',
      data: <String, dynamic>{},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
    final raw = resp.data?['data'];
    if (raw is Map<String, dynamic>) {
      return StakingTeamOverview.fromJson(raw);
    }
    return const StakingTeamOverview();
  }

  /// 分页查询直推列表（对齐 Web `fetchStakingDirectList`）
  Future<StakingDirectListPage> getDirectList({
    int pageNo = 1,
    int pageSize = 20,
  }) async {
    final resp = await _dio.post<Map<String, dynamic>>(
      'uc/staking/direct/list',
      data: {'pageNo': pageNo, 'pageSize': pageSize},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
    final raw = resp.data?['data'];
    if (raw is! Map<String, dynamic>) {
      return const StakingDirectListPage(
        content: [],
        totalPages: 0,
        pageNo: 1,
        hasMore: false,
      );
    }
    final contentRaw = raw['content'];
    final content = contentRaw is List
        ? contentRaw
            .whereType<Map<String, dynamic>>()
            .map(StakingDirectMember.fromJson)
            .toList()
        : <StakingDirectMember>[];
    final totalPages = int.tryParse('${raw['totalPages'] ?? 0}') ?? 0;
    final rawPageNo = int.tryParse('${raw['pageNo'] ?? ''}');
    final rawNumber = int.tryParse('${raw['number'] ?? ''}');
    final parsedPageNo = rawPageNo ?? ((rawNumber ?? (pageNo - 1)) + 1);
    final last = raw['last'];
    final hasMore = last is bool ? !last : parsedPageNo < totalPages;
    return StakingDirectListPage(
      content: content,
      totalPages: totalPages,
      pageNo: parsedPageNo,
      hasMore: hasMore,
    );
  }

  Future<StakingWalletBalance> getStakingWalletBalance(String coinUnit) async {
    final resp = await _dio.post<Map<String, dynamic>>(
      'uc/staking/wallet',
      data: {'coinUnit': coinUnit},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
    final raw = resp.data?['data'];
    if (raw is Map<String, dynamic>) {
      return StakingWalletBalance.fromJson(raw);
    }
    return StakingWalletBalance.empty(coinUnit);
  }

  /// 可提现账户指定币种可用余额（对齐 Web `loadFundCoinBalance`）
  ///
  /// POST `/uc/asset/wallet`，解析逻辑同 `parseFundWalletBalances`。
  Future<String> getFundingWalletAvailable(String coinUnit) async {
    try {
      final resp = await _dio.post<Map<String, dynamic>>(
        'uc/asset/wallet',
        data: <String, dynamic>{},
      );
      final map = parseFundWalletBalances(resp.data);
      return map[coinUnit.toUpperCase()] ?? '0';
    } catch (_) {
      return '0';
    }
  }

  Future<AirdropEligibility> getAirdropEligibility() async {
    final resp =
        await _dio.post<Map<String, dynamic>>('uc/airdrop/eligibility');
    final raw = resp.data?['data'];
    _log(
      'eligibility response dataType=${raw.runtimeType} keys=${raw is Map<String, dynamic> ? raw.keys.toList() : 'n/a'}',
    );
    if (raw is Map<String, dynamic>) {
      return AirdropEligibility.fromJson(raw);
    }
    _log('eligibility fallback to empty because data is not map');
    return AirdropEligibility.empty();
  }

  Future<void> claimAirdrop() async {
    await _dio.post<Map<String, dynamic>>('uc/airdrop/claim');
  }

  Future<AirdropRecordPage> getAirdropRecords({
    required int pageNo,
    int pageSize = 10,
  }) async {
    final resp = await _dio.post<Map<String, dynamic>>(
      'uc/airdrop/records',
      data: {'pageNo': pageNo, 'pageSize': pageSize},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );
    final raw = resp.data?['data'];
    _log(
        'records response pageNo=$pageNo pageSize=$pageSize dataType=${raw.runtimeType}');
    if (raw is! Map<String, dynamic>) {
      _log('records fallback empty: data is not map');
      return const AirdropRecordPage(content: [], totalPages: 0, pageNo: 1);
    }
    final contentRaw = raw['content'];
    final content = contentRaw is List
        ? contentRaw
            .whereType<Map<String, dynamic>>()
            .map(AirdropRecordItem.fromJson)
            .toList()
        : <AirdropRecordItem>[];
    final totalPages = int.tryParse('${raw['totalPages'] ?? 0}') ?? 0;
    // 后端常见两种分页字段：
    // 1) pageNo: 1 基页码
    // 2) number: 0 基页码（Spring Pageable）
    final rawPageNo = int.tryParse('${raw['pageNo'] ?? ''}');
    final rawNumber = int.tryParse('${raw['number'] ?? ''}');
    final parsedPageNo = rawPageNo ?? ((rawNumber ?? (pageNo - 1)) + 1);
    _log(
      'records parsed pageNo=$parsedPageNo(totalPages=$totalPages, rawPageNo=$rawPageNo, rawNumber=$rawNumber) contentRawType=${contentRaw.runtimeType} contentCount=${content.length}',
    );
    return AirdropRecordPage(
      content: content,
      totalPages: totalPages,
      pageNo: parsedPageNo,
    );
  }
}
