import '../../models/trade_order_model.dart';
import '../../models/price_info_model.dart';
import '../../models/trading_account_model.dart';
import '../../models/market_overview_model.dart';
import '../../models/asset_display_model.dart';
import '../../models/kline_model.dart';
import '../../models/p2p_transfer_model.dart';
import '../../models/p2p_transfer_fee_config_model.dart';
import 'package:dio/dio.dart';
import '../../models/c2c_order_model.dart';
import '../../../core/network/api_client.dart';
import '../../../core/network/api_endpoints.dart';
import '../../../core/error/exceptions.dart';

abstract class TradingRemoteDataSource {
  /// 获取买入功能开关状态
  Future<bool> getBuyEnabled();

  /// 获取当前价格信息
  Future<PriceInfoModel> getCurrentPrice();

  /// 获取市场概览
  Future<MarketOverviewModel> getMarketOverview();

  /// 获取交易账户信息
  Future<TradingAccountModel> getTradingAccount(String accountSequence);

  /// 创建订单
  Future<Map<String, dynamic>> createOrder({
    required String type,
    required String price,
    required String quantity,
  });

  /// 取消订单
  Future<void> cancelOrder(String orderNo);

  /// 获取用户订单列表
  Future<OrdersPageModel> getOrders({
    int page = 1,
    int pageSize = 50,
  });

  /// 获取用户成交记录（含手续费明细）
  Future<TradesPageModel> getTrades({
    int page = 1,
    int pageSize = 50,
  });

  /// 预估卖出收益
  Future<Map<String, dynamic>> estimateSell(String quantity);

  /// 划入积分股 (从挖矿账户到交易账户)
  Future<Map<String, dynamic>> transferIn(String amount);

  /// 划出积分股 (从交易账户到挖矿账户)
  Future<Map<String, dynamic>> transferOut(String amount);

  /// 获取划转历史记录
  Future<List<dynamic>> getTransferHistory({int page = 1, int pageSize = 50});

  /// 获取我的资产显示信息
  Future<AssetDisplayModel> getMyAsset({String? dailyAllocation});

  /// 获取指定账户资产显示信息
  Future<AssetDisplayModel> getAccountAsset(String accountSequence, {String? dailyAllocation});

  /// 获取K线数据
  /// [before] 获取此时间之前的K线数据（用于加载更多历史）
  Future<List<KlineModel>> getKlines({String period = '1h', int limit = 100, DateTime? before});

  /// P2P转账 - 发送积分股给其他用户
  Future<P2pTransferModel> p2pTransfer({
    required String toPhone,
    required String amount,
    String? memo,
  });

  /// 查询账户信息（通过手机号）
  Future<AccountLookupModel> lookupAccount(String phone);

  /// 获取P2P转账历史
  Future<List<P2pTransferModel>> getP2pTransferHistory(String accountSequence);

  /// 获取P2P转账手续费配置
  Future<P2pTransferFeeConfigModel> getP2pTransferFeeConfig();

  // ============ C2C交易接口 ============

  /// 获取C2C订单列表（市场广告）
  Future<C2cOrdersPageModel> getC2cOrders({
    String? type, // BUY/SELL
    int page = 1,
    int pageSize = 20,
  });

  /// 获取我的C2C订单
  Future<C2cOrdersPageModel> getMyC2cOrders({
    String? status,
    int page = 1,
    int pageSize = 20,
  });

  /// 创建C2C订单（发布广告）
  Future<C2cOrderModel> createC2cOrder({
    required String type, // BUY/SELL
    required String price,
    required String quantity,
    String? minAmount,
    String? maxAmount,
    // 收款信息（卖单必填）
    String? paymentMethod,
    String? paymentAccount,
    String? paymentQrCode,
    String? paymentRealName,
    String? remark,
  });

  /// 获取C2C订单详情
  Future<C2cOrderModel> getC2cOrderDetail(String orderNo);

  /// 接单（吃单）
  Future<C2cOrderModel> takeC2cOrder(
    String orderNo, {
    String? quantity,
    // 收款信息（接买单时由taker提供）
    String? paymentMethod,
    String? paymentAccount,
    String? paymentQrCode,
    String? paymentRealName,
  });

  /// 取消C2C订单
  Future<void> cancelC2cOrder(String orderNo);

  /// 确认付款（买方操作）
  Future<C2cOrderModel> confirmC2cPayment(String orderNo);

  /// 确认收款（卖方操作）
  Future<C2cOrderModel> confirmC2cReceived(String orderNo);

  /// 上传付款水单（买方操作）
  Future<C2cOrderModel> uploadC2cPaymentProof(String orderNo, String filePath);

  /// 查询当前用户预种卖出限制状态（fail-open：接口异常时返回 false 允许卖出）
  Future<bool> getSellRestriction();
}

class TradingRemoteDataSourceImpl implements TradingRemoteDataSource {
  final ApiClient client;

  TradingRemoteDataSourceImpl({required this.client});

  @override
  Future<bool> getBuyEnabled() async {
    try {
      final response = await client.get(ApiEndpoints.buyEnabled);
      return response.data['enabled'] ?? false;
    } catch (e) {
      // 如果获取失败，默认返回false（关闭状态）
      return false;
    }
  }

  @override
  Future<PriceInfoModel> getCurrentPrice() async {
    try {
      final response = await client.get(ApiEndpoints.currentPrice);
      return PriceInfoModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<MarketOverviewModel> getMarketOverview() async {
    try {
      final response = await client.get(ApiEndpoints.marketOverview);
      return MarketOverviewModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<TradingAccountModel> getTradingAccount(String accountSequence) async {
    try {
      final response = await client.get(ApiEndpoints.tradingAccount(accountSequence));
      return TradingAccountModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<Map<String, dynamic>> createOrder({
    required String type,
    required String price,
    required String quantity,
  }) async {
    try {
      final response = await client.post(
        ApiEndpoints.createOrder,
        data: {
          'type': type,
          'price': price,
          'quantity': quantity,
        },
      );
      return response.data;
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<void> cancelOrder(String orderNo) async {
    try {
      await client.post(ApiEndpoints.cancelOrder(orderNo));
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<OrdersPageModel> getOrders({
    int page = 1,
    int pageSize = 50,
  }) async {
    try {
      final response = await client.get(
        ApiEndpoints.orders,
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      return OrdersPageModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<TradesPageModel> getTrades({
    int page = 1,
    int pageSize = 50,
  }) async {
    try {
      final response = await client.get(
        ApiEndpoints.trades,
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      return TradesPageModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<Map<String, dynamic>> estimateSell(String quantity) async {
    try {
      final response = await client.get(
        ApiEndpoints.estimateSell,
        queryParameters: {'quantity': quantity},
      );
      return response.data;
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<Map<String, dynamic>> transferIn(String amount) async {
    try {
      final response = await client.post(
        ApiEndpoints.transferIn,
        data: {'amount': amount},
      );
      return response.data;
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<Map<String, dynamic>> transferOut(String amount) async {
    try {
      final response = await client.post(
        ApiEndpoints.transferOut,
        data: {'amount': amount},
      );
      return response.data;
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<List<dynamic>> getTransferHistory({int page = 1, int pageSize = 50}) async {
    try {
      final response = await client.get(
        ApiEndpoints.transferHistory,
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      return response.data['data'] ?? [];
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<AssetDisplayModel> getMyAsset({String? dailyAllocation}) async {
    try {
      final queryParams = <String, dynamic>{};
      if (dailyAllocation != null) {
        queryParams['dailyAllocation'] = dailyAllocation;
      }
      final response = await client.get(
        ApiEndpoints.myAsset,
        queryParameters: queryParams.isNotEmpty ? queryParams : null,
      );
      return AssetDisplayModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<AssetDisplayModel> getAccountAsset(String accountSequence, {String? dailyAllocation}) async {
    try {
      final queryParams = <String, dynamic>{};
      if (dailyAllocation != null) {
        queryParams['dailyAllocation'] = dailyAllocation;
      }
      final response = await client.get(
        ApiEndpoints.accountAsset(accountSequence),
        queryParameters: queryParams.isNotEmpty ? queryParams : null,
      );
      return AssetDisplayModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<List<KlineModel>> getKlines({
    String period = '1h',
    int limit = 100,
    DateTime? before,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'period': period,
        'limit': limit,
      };
      if (before != null) {
        queryParams['before'] = before.toUtc().toIso8601String();
      }
      final response = await client.get(
        ApiEndpoints.priceKlines,
        queryParameters: queryParams,
      );
      final List<dynamic> data = response.data;
      return data.map((json) => KlineModel.fromJson(json)).toList();
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<P2pTransferModel> p2pTransfer({
    required String toPhone,
    required String amount,
    String? memo,
  }) async {
    try {
      final data = <String, dynamic>{
        'toPhone': toPhone,
        'amount': amount,
      };
      if (memo != null && memo.isNotEmpty) {
        data['memo'] = memo;
      }
      final response = await client.post(
        ApiEndpoints.p2pTransfer,
        data: data,
      );
      return P2pTransferModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<AccountLookupModel> lookupAccount(String phone) async {
    try {
      final response = await client.get(
        ApiEndpoints.lookupAccount,
        queryParameters: {'phone': phone},
      );
      return AccountLookupModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<List<P2pTransferModel>> getP2pTransferHistory(String accountSequence) async {
    try {
      final response = await client.get(
        ApiEndpoints.p2pTransferHistory(accountSequence),
      );
      final List<dynamic> data = response.data is List ? response.data : [];
      return data.map((json) => P2pTransferModel.fromJson(json)).toList();
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<P2pTransferFeeConfigModel> getP2pTransferFeeConfig() async {
    try {
      final response = await client.get(ApiEndpoints.p2pTransferFeeConfig);
      return P2pTransferFeeConfigModel.fromJson(response.data);
    } catch (e) {
      // 失败时返回默认值
      return P2pTransferFeeConfigModel(fee: '5', minTransferAmount: '6');
    }
  }

  // ============ C2C交易实现 ============

  @override
  Future<C2cOrdersPageModel> getC2cOrders({
    String? type,
    int page = 1,
    int pageSize = 20,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'page': page,
        'pageSize': pageSize,
      };
      if (type != null) {
        queryParams['type'] = type;
      }
      final response = await client.get(
        ApiEndpoints.c2cOrders,
        queryParameters: queryParams,
      );
      return C2cOrdersPageModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrdersPageModel> getMyC2cOrders({
    String? status,
    int page = 1,
    int pageSize = 20,
  }) async {
    try {
      final queryParams = <String, dynamic>{
        'page': page,
        'pageSize': pageSize,
      };
      if (status != null) {
        queryParams['status'] = status;
      }
      final response = await client.get(
        ApiEndpoints.c2cMyOrders,
        queryParameters: queryParams,
      );
      return C2cOrdersPageModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> createC2cOrder({
    required String type,
    required String price,
    required String quantity,
    String? minAmount,
    String? maxAmount,
    // 收款信息（卖单必填）
    String? paymentMethod,
    String? paymentAccount,
    String? paymentQrCode,
    String? paymentRealName,
    String? remark,
  }) async {
    try {
      final data = <String, dynamic>{
        'type': type,
        'price': price,
        'quantity': quantity,
      };
      if (minAmount != null) data['minAmount'] = minAmount;
      if (maxAmount != null) data['maxAmount'] = maxAmount;
      // 收款信息
      if (paymentMethod != null) data['paymentMethod'] = paymentMethod;
      if (paymentAccount != null) data['paymentAccount'] = paymentAccount;
      if (paymentQrCode != null) data['paymentQrCode'] = paymentQrCode;
      if (paymentRealName != null) data['paymentRealName'] = paymentRealName;
      if (remark != null && remark.isNotEmpty) data['remark'] = remark;

      final response = await client.post(
        ApiEndpoints.c2cOrders,
        data: data,
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> getC2cOrderDetail(String orderNo) async {
    try {
      final response = await client.get(
        ApiEndpoints.c2cOrderDetail(orderNo),
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> takeC2cOrder(
    String orderNo, {
    String? quantity,
    // 收款信息（接买单时由taker提供）
    String? paymentMethod,
    String? paymentAccount,
    String? paymentQrCode,
    String? paymentRealName,
  }) async {
    try {
      final data = <String, dynamic>{};
      if (quantity != null) data['quantity'] = quantity;
      // 收款信息
      if (paymentMethod != null) data['paymentMethod'] = paymentMethod;
      if (paymentAccount != null) data['paymentAccount'] = paymentAccount;
      if (paymentQrCode != null) data['paymentQrCode'] = paymentQrCode;
      if (paymentRealName != null) data['paymentRealName'] = paymentRealName;

      final response = await client.post(
        ApiEndpoints.c2cTakeOrder(orderNo),
        data: data.isNotEmpty ? data : null,
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<void> cancelC2cOrder(String orderNo) async {
    try {
      await client.post(ApiEndpoints.c2cCancelOrder(orderNo));
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> confirmC2cPayment(String orderNo) async {
    try {
      final response = await client.post(
        ApiEndpoints.c2cConfirmPayment(orderNo),
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> confirmC2cReceived(String orderNo) async {
    try {
      final response = await client.post(
        ApiEndpoints.c2cConfirmReceived(orderNo),
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<C2cOrderModel> uploadC2cPaymentProof(String orderNo, String filePath) async {
    try {
      final formData = FormData.fromMap({
        'file': await MultipartFile.fromFile(filePath),
      });
      final response = await client.post(
        ApiEndpoints.c2cUploadProof(orderNo),
        data: formData,
      );
      return C2cOrderModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<bool> getSellRestriction() async {
    try {
      final response = await client.get(ApiEndpoints.sellRestriction);
      return response.data['isRestricted'] == true;
    } catch (e) {
      // fail-open：接口异常时允许卖出，避免误封正常用户
      return false;
    }
  }
}
