import 'package:injectable/injectable.dart';
import '../../../../../core/constants/api_constants.dart';
import '../../../../../core/network/dio_client.dart';
import '../models/ico_offering_model.dart';
import '../models/ico_portfolio_model.dart';
import '../models/ico_transaction_model.dart';
import '../models/portfolio_performance_point_model.dart';
import '../models/ico_blockchain_model.dart';
import '../models/ico_token_type_model.dart';
import '../models/ico_launch_plan_model.dart';
import '../models/ico_stats_model.dart';

abstract class IcoRemoteDataSource {
  Future<List<IcoOfferingModel>> getFeaturedOfferings();
  Future<List<IcoOfferingModel>> getOfferings({
    String? status,
    int? page,
    int? limit,
    String? search,
    String? sort,
    List<String>? blockchain,
    List<String>? tokenType,
  });
  Future<IcoOfferingModel> getOfferingById(String id);
  Future<IcoPortfolioModel> getPortfolio();
  Future<List<IcoTransactionModel>> getTransactions();
  Future<IcoTransactionModel> createInvestment({
    required String offeringId,
    required double amount,
    required String walletAddress,
  });
  Future<List<PortfolioPerformancePointModel>> getPortfolioPerformance({
    String timeframe = '1M',
  });
  Future<List<IcoBlockchainModel>> getBlockchains();
  Future<List<IcoTokenTypeModel>> getTokenTypes();
  Future<List<IcoLaunchPlanModel>> getLaunchPlans();
  Future<IcoStatsModel> getIcoStats();
}

@Injectable(as: IcoRemoteDataSource)
class IcoRemoteDataSourceImpl implements IcoRemoteDataSource {
  const IcoRemoteDataSourceImpl(this._dioClient);

  final DioClient _dioClient;

  @override
  Future<List<IcoOfferingModel>> getFeaturedOfferings() async {
    final response = await _dioClient.get(ApiConstants.icoFeaturedOffers);

    final List<dynamic> projectsData =
        response.data['projects'] as List<dynamic>;
    return projectsData
        .map((json) => IcoOfferingModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<List<IcoOfferingModel>> getOfferings({
    String? status,
    int? page,
    int? limit,
    String? search,
    String? sort,
    List<String>? blockchain,
    List<String>? tokenType,
  }) async {
    final queryParams = <String, dynamic>{};

    if (status != null) queryParams['status'] = status;
    if (page != null) queryParams['page'] = page;
    if (limit != null) queryParams['limit'] = limit;
    if (search != null) queryParams['search'] = search;
    if (sort != null) queryParams['sort'] = sort;
    if (blockchain != null && blockchain.isNotEmpty) {
      queryParams['blockchain'] = blockchain;
    }
    if (tokenType != null && tokenType.isNotEmpty) {
      queryParams['tokenType'] = tokenType;
    }

    final response = await _dioClient.get(
      ApiConstants.icoOffers,
      queryParameters: queryParams,
    );

    final List<dynamic> offeringsData =
        response.data['offerings'] as List<dynamic>;
    return offeringsData
        .map((json) => IcoOfferingModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<IcoOfferingModel> getOfferingById(String id) async {
    final response = await _dioClient.get('${ApiConstants.icoOfferById}/$id');
    return IcoOfferingModel.fromJson(response.data as Map<String, dynamic>);
  }

  @override
  Future<IcoPortfolioModel> getPortfolio() async {
    final response = await _dioClient.get(ApiConstants.icoPortfolio);
    return IcoPortfolioModel.fromJson(response.data as Map<String, dynamic>);
  }

  @override
  Future<List<IcoTransactionModel>> getTransactions() async {
    final response = await _dioClient.get(ApiConstants.icoTransactions);

    final List<dynamic> transactionsData =
        response.data['data'] as List<dynamic>;
    return transactionsData
        .map((json) =>
            IcoTransactionModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<IcoTransactionModel> createInvestment({
    required String offeringId,
    required double amount,
    required String walletAddress,
  }) async {
    final response = await _dioClient.post(
      ApiConstants.icoCreateInvestment,
      data: {
        'offeringId': offeringId,
        'amount': amount,
        'walletAddress': walletAddress,
      },
    );

    return IcoTransactionModel.fromJson(response.data as Map<String, dynamic>);
  }

  @override
  Future<List<PortfolioPerformancePointModel>> getPortfolioPerformance({
    String timeframe = '1M',
  }) async {
    final response = await _dioClient.get(
      ApiConstants.icoPortfolioPerformance,
      queryParameters: {'timeframe': timeframe},
    );

    final List<dynamic> data =
        response.data['performanceData'] as List<dynamic>;
    return data
        .map((json) => PortfolioPerformancePointModel.fromJson(
            json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<List<IcoBlockchainModel>> getBlockchains() async {
    final response = await _dioClient.get(ApiConstants.icoBlockchains);

    final List<dynamic> data = response.data['blockchains'] as List<dynamic>;
    return data
        .map(
            (json) => IcoBlockchainModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<List<IcoTokenTypeModel>> getTokenTypes() async {
    final response = await _dioClient.get(ApiConstants.icoTokenTypes);

    final List<dynamic> data = response.data['tokenTypes'] as List<dynamic>;
    return data
        .map((json) => IcoTokenTypeModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<List<IcoLaunchPlanModel>> getLaunchPlans() async {
    final response = await _dioClient.get(ApiConstants.icoLaunchPlans);

    final List<dynamic> data = response.data['plans'] as List<dynamic>;
    return data
        .map(
            (json) => IcoLaunchPlanModel.fromJson(json as Map<String, dynamic>))
        .toList();
  }

  @override
  Future<IcoStatsModel> getIcoStats() async {
    final response = await _dioClient.get(ApiConstants.icoStats);

    return IcoStatsModel.fromJson(response.data as Map<String, dynamic>);
  }
}
