import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../../core/errors/failures.dart';
import '../../../../../core/errors/exceptions.dart';
import '../../../../../core/network/network_info.dart';
import '../../domain/entities/p2p_activity_entity.dart';
import '../../domain/repositories/p2p_dashboard_repository.dart';
import '../../domain/usecases/dashboard/get_dashboard_data_usecase.dart';
import '../../domain/usecases/dashboard/get_dashboard_stats_usecase.dart';
import '../../domain/usecases/dashboard/get_portfolio_data_usecase.dart';
import '../datasources/p2p_remote_datasource.dart';
import '../datasources/p2p_local_datasource.dart';

/// Repository implementation for P2P dashboard operations
@Injectable(as: P2PDashboardRepository)
class P2PDashboardRepositoryImpl implements P2PDashboardRepository {
  const P2PDashboardRepositoryImpl(
    this._remoteDataSource,
    this._localDataSource,
    this._networkInfo,
  );

  final P2PRemoteDataSource _remoteDataSource;
  final P2PLocalDataSource _localDataSource;
  final NetworkInfo _networkInfo;

  @override
  Future<Either<Failure, P2PDashboardResponse>> getDashboardData() async {
    try {
      // Check network connectivity
      if (!await _networkInfo.isConnected) {
        // Try to get cached data
        final cachedData = await _localDataSource.getCachedDashboardData();
        if (cachedData != null) {
          return Right(_convertJsonToDashboardResponse(cachedData));
        }
        return Left(NetworkFailure('No internet connection'));
      }

      final response = await _remoteDataSource.getDashboardData();

      // Cache the results
      await _localDataSource.cacheDashboardData(response);

      return Right(_convertJsonToDashboardResponse(response));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException catch (e) {
      return Left(NetworkFailure(e.message));
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, DashboardStatsResponse>> getDashboardStats() async {
    try {
      // Check network connectivity
      if (!await _networkInfo.isConnected) {
        return Left(NetworkFailure('No internet connection'));
      }

      final response = await _remoteDataSource.getDashboardStats();

      return Right(_convertJsonToStatsResponse(response));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException catch (e) {
      return Left(NetworkFailure(e.message));
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, List<P2PActivityEntity>>> getTradingActivity({
    int limit = 10,
    int offset = 0,
    String? type,
  }) async {
    try {
      // Check network connectivity
      if (!await _networkInfo.isConnected) {
        return Left(NetworkFailure('No internet connection'));
      }

      final response = await _remoteDataSource.getTradingActivity(
        limit: limit,
        offset: offset,
        type: type,
      );

      final activities = (response as List)
          .map((json) =>
              _convertJsonToActivityEntity(json as Map<String, dynamic>))
          .toList();

      return Right(activities);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException catch (e) {
      return Left(NetworkFailure(e.message));
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  @override
  Future<Either<Failure, PortfolioDataResponse>> getPortfolioData() async {
    try {
      // Check network connectivity
      if (!await _networkInfo.isConnected) {
        return Left(NetworkFailure('No internet connection'));
      }

      final response = await _remoteDataSource.getPortfolioData();

      return Right(_convertJsonToPortfolioResponse(response));
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException catch (e) {
      return Left(NetworkFailure(e.message));
    } catch (e) {
      return Left(UnknownFailure(e.toString()));
    }
  }

  // Helper methods
  P2PDashboardResponse _convertJsonToDashboardResponse(
      Map<String, dynamic> json) {
    final portfolio = json['portfolio'] as Map<String, dynamic>? ?? {};
    final stats = json['stats'] as Map<String, dynamic>? ?? {};
    final tradingActivity = json['tradingActivity'] as List? ?? [];
    final transactions = json['transactions'] as List? ?? [];
    final summary = json['summary'] as Map<String, dynamic>? ?? {};

    return P2PDashboardResponse(
      notifications: json['notifications'] as int? ?? 0,
      portfolio: PortfolioData(
        totalValue: (portfolio['totalValue'] as num?)?.toDouble() ?? 0.0,
        totalTrades: portfolio['totalTrades'] as int? ?? 0,
        profitLoss: (portfolio['profitLoss'] as num?)?.toDouble() ?? 0.0,
        monthlyVolume: (portfolio['monthlyVolume'] as num?)?.toDouble() ?? 0.0,
      ),
      stats: DashboardStats(
        totalTrades: (stats['totalTrades'] as int?) ?? 0,
        activeTrades: stats['activeTrades'] as int? ?? 0,
        completedTrades: stats['completedTrades'] as int? ?? 0,
        successRate: (stats['successRate'] as num?)?.toDouble() ?? 0.0,
        totalVolume: (stats['totalVolume'] as num?)?.toDouble() ?? 0.0,
        avgTradeSize: (stats['avgTradeSize'] as num?)?.toDouble() ?? 0.0,
      ),
      tradingActivity: tradingActivity
          .map((json) =>
              _convertJsonToActivityEntity(json as Map<String, dynamic>))
          .toList(),
      transactions: [], // Would be converted from transactions data
      summary: DashboardSummary(
        todayTrades: (summary['todayTrades'] as int?) ?? 0,
        weeklyTrades: (summary['weeklyTrades'] as int?) ?? 0,
        monthlyTrades: (summary['monthlyTrades'] as int?) ?? 0,
        pendingActions: (summary['pendingActions'] as int?) ?? 0,
        alerts: (summary['alerts'] as int?) ?? 0,
      ),
    );
  }

  DashboardStatsResponse _convertJsonToStatsResponse(
      Map<String, dynamic> json) {
    return DashboardStatsResponse(
      totalTrades: json['totalTrades'] as int? ?? 0,
      activeTrades: json['activeTrades'] as int? ?? 0,
      completedTrades: json['completedTrades'] as int? ?? 0,
      disputedTrades: json['disputedTrades'] as int? ?? 0,
      cancelledTrades: json['cancelledTrades'] as int? ?? 0,
      successRate: (json['successRate'] as num?)?.toDouble() ?? 0.0,
      totalVolume: (json['totalVolume'] as num?)?.toDouble() ?? 0.0,
      monthlyVolume: (json['monthlyVolume'] as num?)?.toDouble() ?? 0.0,
      averageTradeSize: (json['averageTradeSize'] as num?)?.toDouble() ?? 0.0,
      averageCompletionTime:
          (json['averageCompletionTime'] as num?)?.toDouble(),
    );
  }

  PortfolioDataResponse _convertJsonToPortfolioResponse(
      Map<String, dynamic> json) {
    final topCurrencies = json['topCurrencies'] as List? ?? [];
    final recentPerformance = json['recentPerformance'] as List? ?? [];

    return PortfolioDataResponse(
      totalValue: (json['totalValue'] as num?)?.toDouble() ?? 0.0,
      totalTrades: json['totalTrades'] as int? ?? 0,
      monthlyVolume: (json['monthlyVolume'] as num?)?.toDouble() ?? 0.0,
      profitLoss: (json['profitLoss'] as num?)?.toDouble() ?? 0.0,
      profitLossPercentage:
          (json['profitLossPercentage'] as num?)?.toDouble() ?? 0.0,
      topCurrencies: topCurrencies
          .map((json) => CurrencyData(
                currency: json['currency']?.toString() ?? '',
                volume: (json['volume'] as num?)?.toDouble() ?? 0.0,
                trades: json['trades'] as int? ?? 0,
                percentage: (json['percentage'] as num?)?.toDouble() ?? 0.0,
              ))
          .toList(),
      recentPerformance: recentPerformance
          .map((json) => PerformanceData(
                date: DateTime.parse(
                    json['date'] ?? DateTime.now().toIso8601String()),
                volume: (json['volume'] as num?)?.toDouble() ?? 0.0,
                trades: json['trades'] as int? ?? 0,
                profit: (json['profit'] as num?)?.toDouble() ?? 0.0,
              ))
          .toList(),
    );
  }

  P2PActivityEntity _convertJsonToActivityEntity(Map<String, dynamic> json) {
    // Convert the activity type string to P2PActivityType
    P2PActivityType _parseActivityType(String type) {
      try {
        return P2PActivityType.values.firstWhere(
          (e) => e.toString().split('.').last == type,
          orElse: () => P2PActivityType.other,
        );
      } catch (e) {
        return P2PActivityType.other;
      }
    }

    return P2PActivityEntity(
      id: json['id']?.toString() ?? '',
      userId: json['userId']?.toString() ?? '',
      type: _parseActivityType(json['type']?.toString() ?? ''),
      message:
          json['message']?.toString() ?? json['description']?.toString() ?? '',
      tradeId: json['tradeId']?.toString(),
      offerId: json['offerId']?.toString(),
      details: {
        'amount': (json['amount'] as num?)?.toDouble(),
        'currency': json['currency']?.toString(),
        'status': json['status']?.toString(),
        ...?json['metadata'] as Map<String, dynamic>?,
      },
      createdAt: DateTime.tryParse(json['timestamp']?.toString() ?? '') ??
          DateTime.now(),
    );
  }
}
