import '../../models/share_account_model.dart';
import '../../models/mining_record_model.dart';
import '../../models/global_state_model.dart';
import '../../models/planting_record_model.dart';
import '../../models/batch_mining_record_model.dart';
import '../../../core/network/api_client.dart';
import '../../../core/network/api_endpoints.dart';
import '../../../core/error/exceptions.dart';
import '../../../domain/repositories/mining_repository.dart';
import '../../../domain/entities/batch_mining_record.dart';

abstract class MiningRemoteDataSource {
  Future<ShareAccountModel> getShareAccount(String accountSequence);
  Future<MiningRecordsPage> getMiningRecords(
    String accountSequence, {
    int page = 1,
    int pageSize = 20,
  });
  Future<GlobalStateModel> getGlobalState();
  Future<PlantingLedgerPageModel> getPlantingLedger(
    String accountSequence, {
    int page = 1,
    int pageSize = 10,
  });
  Future<BatchMiningRecordsPage> getBatchMiningRecords(
    String accountSequence, {
    int page = 1,
    int pageSize = 20,
  });
}

class MiningRemoteDataSourceImpl implements MiningRemoteDataSource {
  final ApiClient client;

  MiningRemoteDataSourceImpl({required this.client});

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

  @override
  Future<MiningRecordsPage> getMiningRecords(
    String accountSequence, {
    int page = 1,
    int pageSize = 20,
  }) async {
    try {
      final response = await client.get(
        ApiEndpoints.miningRecords(accountSequence),
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      final data = response.data;
      // mining-service 返回格式: { data: [...], total: ... }
      final rawItems = data['data'] as List? ?? data['items'] as List? ?? data['records'] as List? ?? [];
      final items = rawItems.map((json) => MiningRecordModel.fromJson({
        'id': json['id']?.toString() ?? '',
        'accountSequence': accountSequence,
        'distributionMinute': json['miningMinute']?.toString() ?? json['distributionMinute'] ?? '',
        'contributionRatio': json['contributionRatio']?.toString() ?? '0',
        'shareAmount': json['minedAmount']?.toString() ?? json['shareAmount'] ?? '0',
        'priceSnapshot': json['secondDistribution']?.toString() ?? json['priceSnapshot'] ?? '0',
        'createdAt': json['createdAt'],
      })).toList();
      final total = data['total'] ?? items.length;
      return MiningRecordsPage(
        items: items,
        total: total,
        page: page,
        pageSize: pageSize,
        totalPages: (total / pageSize).ceil(),
      );
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

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

  @override
  Future<PlantingLedgerPageModel> getPlantingLedger(
    String accountSequence, {
    int page = 1,
    int pageSize = 10,
  }) async {
    try {
      final response = await client.get(
        ApiEndpoints.plantingLedger(accountSequence),
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      return PlantingLedgerPageModel.fromJson(response.data);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }

  @override
  Future<BatchMiningRecordsPage> getBatchMiningRecords(
    String accountSequence, {
    int page = 1,
    int pageSize = 20,
  }) async {
    try {
      final response = await client.get(
        ApiEndpoints.batchMiningRecords(accountSequence),
        queryParameters: {'page': page, 'pageSize': pageSize},
      );
      return BatchMiningRecordsPageModel.fromJson(response.data, page, pageSize);
    } catch (e) {
      throw ServerException(e.toString());
    }
  }
}
