import 'package:dio/dio.dart';

/// 现货 API 服务 — 对接 /spot/v1/... 接口体系
///
/// 接口对照（全部带 spot/ 前缀）：
///   GET  spot/v1/config/coin/list          已开启币种列表（含图标/精度）
///   GET  spot/v1/config/symbol/list        已开启交易对列表（含精度/手续费/最小量）
///   GET  spot/v1/account/asset/list        用户现货资产列表（含今日盈亏）
///   GET  spot/v1/account/transfer/symbols  可划转币种列表
///   POST spot/v1/account/transfer          资金账户 ↔ 现货账户划转
///   POST spot/v1/order/create              创建订单
///   POST spot/v1/order/cancel              撤单
///   POST spot/v1/order/current             当前委托
///   POST spot/v1/order/history             历史委托
///   POST spot/v1/order/trades              成交记录
///   POST spot/v1/account_records           资金流水
class SpotService {
  const SpotService(this._dio);

  final Dio _dio;

  // ── 配置 ────────────────────────────────────────────

  /// 获取已开启的现货币种列表（含图标/显示精度/标签）
  Future<List<Map<String, dynamic>>> getCoins() async {
    final resp =
        await _dio.get<Map<String, dynamic>>('spot/v1/config/coin/list');
    return _extractList(resp.data);
  }

  /// 获取已开启且已发布的交易对列表（含精度/手续费/最小下单量/排序权重）
  Future<List<Map<String, dynamic>>> getSymbols() async {
    final resp =
        await _dio.get<Map<String, dynamic>>('spot/v1/config/symbol/list');
    return _extractList(resp.data);
  }

  // ── 资产 ────────────────────────────────────────────

  /// 获取用户现货资产列表（含 totalAmount/todayPnl/todayPnlRate）
  ///
  /// [hideZero] 传 true 时服务端过滤 0 余额币种（对齐 Web hideZero 逻辑）
  Future<Map<String, dynamic>> getAssets({bool? hideZero}) async {
    final query = <String, dynamic>{};
    if (hideZero != null) {
      query['hideZero'] = hideZero;
    }
    final resp = await _dio.get<Map<String, dynamic>>(
      'spot/v1/account/asset/list',
      queryParameters: query.isEmpty ? null : query,
    );
    final data = resp.data?['data'];
    if (data is Map<String, dynamic>) return data;
    return {};
  }

  /// 获取可划转的开放币种列表
  Future<List<Map<String, dynamic>>> getTransferSymbols() async {
    final resp = await _dio
        .get<Map<String, dynamic>>('spot/v1/account/transfer/symbols');
    return _extractList(resp.data);
  }

  /// 账户间划转：资金账户 ↔ 现货账户
  ///
  /// [direction] 1=资金账户→现货账户，2=现货账户→资金账户
  Future<void> transfer({
    required String symbol,
    required double amount,
    required int direction,
  }) async {
    await _dio.post<dynamic>(
      'spot/v1/account/transfer',
      data: {'symbol': symbol, 'amount': amount, 'direction': direction},
    );
  }

  // ── 订单 ────────────────────────────────────────────

  /// 创建订单
  ///
  /// [type] 1=限价单，2=市价单
  /// [side] BUY / SELL
  /// [price] 限价单传价格；市价单传 0
  /// [volume] 限价单传基础币数量；市价买传 USDT 金额；市价卖传基础币数量
  Future<Map<String, dynamic>> placeOrder({
    required String symbol,
    required String side,
    required int type,
    required double price,
    required double volume,
  }) async {
    final resp = await _dio.post<Map<String, dynamic>>(
      'spot/v1/order/create',
      data: {
        'symbol': symbol,
        'side': side,
        'type': type,
        'price': price,
        'volume': volume,
        'source': 2,
        'orderType': 1,
      },
    );
    final data = resp.data?['data'];
    if (data is Map<String, dynamic>) return data;
    return {};
  }

  /// 撤单
  Future<void> cancelOrder(int orderId) async {
    await _dio.post<dynamic>(
      'spot/v1/order/cancel',
      data: {'orderId': orderId},
    );
  }

  /// 查询当前委托（未完成挂单）
  Future<Map<String, dynamic>> getCurrentOrders({
    String? symbol,
    String? side,
    int page = 1,
    int size = 50,
    int? ctimeBegin,
    int? ctimeEnd,
  }) async {
    final body = <String, dynamic>{'page': page, 'size': size};
    if (symbol != null && symbol.isNotEmpty) body['symbol'] = symbol;
    if (side != null && side.isNotEmpty) body['side'] = side;
    if (ctimeBegin != null) body['ctimeBegin'] = ctimeBegin;
    if (ctimeEnd != null) body['ctimeEnd'] = ctimeEnd;
    final resp = await _dio.post<Map<String, dynamic>>('spot/v1/order/current',
        data: body);
    return _extractPageData(resp.data);
  }

  /// 查询历史委托（已完成或已撤单）
  Future<Map<String, dynamic>> getHistoryOrders({
    String? symbol,
    String? side,
    int? type,
    int? status,
    int page = 1,
    int size = 20,
    int? ctimeBegin,
    int? ctimeEnd,
  }) async {
    final body = <String, dynamic>{'page': page, 'size': size};
    if (symbol != null && symbol.isNotEmpty) body['symbol'] = symbol;
    if (side != null && side.isNotEmpty) body['side'] = side;
    if (type != null) body['type'] = type;
    if (status != null) body['status'] = status;
    if (ctimeBegin != null) body['ctimeBegin'] = ctimeBegin;
    if (ctimeEnd != null) body['ctimeEnd'] = ctimeEnd;
    final resp = await _dio.post<Map<String, dynamic>>('spot/v1/order/history',
        data: body);
    return _extractPageData(resp.data);
  }

  /// 查询成交记录（有成交量的订单）
  Future<Map<String, dynamic>> getTrades({
    String? symbol,
    String? side,
    int? type,
    int? status,
    int page = 1,
    int size = 20,
    int? ctimeBegin,
    int? ctimeEnd,
  }) async {
    final body = <String, dynamic>{'page': page, 'size': size};
    if (symbol != null && symbol.isNotEmpty) body['symbol'] = symbol;
    if (side != null && side.isNotEmpty) body['side'] = side;
    if (type != null) body['type'] = type;
    if (status != null) body['status'] = status;
    if (ctimeBegin != null) body['ctimeBegin'] = ctimeBegin;
    if (ctimeEnd != null) body['ctimeEnd'] = ctimeEnd;
    final resp = await _dio.post<Map<String, dynamic>>('spot/v1/order/trades',
        data: body);
    return _extractPageData(resp.data);
  }

  // ── 资金流水 ─────────────────────────────────────────

  /// 分页查询资金流水
  ///
  /// [type] 流水类型：1=划转转入，2=划转转出，5=成交，12=手续费
  Future<Map<String, dynamic>> getAccountRecords({
    String? symbol,
    int? type,
    int page = 1,
    int size = 20,
    int? startTime,
    int? endTime,
  }) async {
    final body = <String, dynamic>{'page': page, 'size': size};
    if (symbol != null && symbol.isNotEmpty) body['symbol'] = symbol;
    if (type != null) body['type'] = type;
    if (startTime != null) body['startTime'] = startTime;
    if (endTime != null) body['endTime'] = endTime;
    final resp = await _dio
        .post<Map<String, dynamic>>('spot/v1/account_records', data: body);
    return _extractPageData(resp.data);
  }

  // ── 工具 ────────────────────────────────────────────

  static List<Map<String, dynamic>> _extractList(Map<String, dynamic>? body) {
    final raw = body?['data'];
    if (raw is List) return raw.whereType<Map<String, dynamic>>().toList();
    return [];
  }

  static Map<String, dynamic> _extractPageData(Map<String, dynamic>? body) {
    final raw = body?['data'];
    if (raw is Map<String, dynamic>) return raw;
    return {};
  }
}
