import 'package:dartz/dartz.dart';
import '../../domain/entities/price_info.dart';
import '../../domain/entities/market_overview.dart';
import '../../domain/entities/trading_account.dart';
import '../../domain/entities/asset_display.dart';
import '../../domain/entities/kline.dart';
import '../../domain/repositories/trading_repository.dart';
import '../../core/error/exceptions.dart';
import '../../core/error/failures.dart';
import '../datasources/remote/trading_remote_datasource.dart';
import '../models/trade_order_model.dart';

class TradingRepositoryImpl implements TradingRepository {
  final TradingRemoteDataSource remoteDataSource;

  TradingRepositoryImpl({required this.remoteDataSource});

  @override
  Future<Either<Failure, bool>> getBuyEnabled() async {
    try {
      final result = await remoteDataSource.getBuyEnabled();
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    } catch (e) {
      return const Right(false);
    }
  }

  @override
  Future<Either<Failure, bool>> getSellRestriction() async {
    try {
      final result = await remoteDataSource.getSellRestriction();
      return Right(result);
    } catch (e) {
      return const Right(false); // fail-open
    }
  }

  @override
  Future<Either<Failure, PriceInfo>> getCurrentPrice() async {
    try {
      final result = await remoteDataSource.getCurrentPrice();
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, MarketOverview>> getMarketOverview() async {
    try {
      final result = await remoteDataSource.getMarketOverview();
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, TradingAccount>> getTradingAccount(String accountSequence) async {
    try {
      final result = await remoteDataSource.getTradingAccount(accountSequence);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, Map<String, dynamic>>> createOrder({
    required String type,
    required String price,
    required String quantity,
  }) async {
    try {
      final result = await remoteDataSource.createOrder(
        type: type,
        price: price,
        quantity: quantity,
      );
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, void>> cancelOrder(String orderNo) async {
    try {
      await remoteDataSource.cancelOrder(orderNo);
      return const Right(null);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, OrdersPageModel>> getOrders({
    int page = 1,
    int pageSize = 50,
  }) async {
    try {
      final result = await remoteDataSource.getOrders(
        page: page,
        pageSize: pageSize,
      );
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, TradesPageModel>> getTrades({
    int page = 1,
    int pageSize = 50,
  }) async {
    try {
      final result = await remoteDataSource.getTrades(
        page: page,
        pageSize: pageSize,
      );
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, Map<String, dynamic>>> estimateSell(String quantity) async {
    try {
      final result = await remoteDataSource.estimateSell(quantity);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, Map<String, dynamic>>> transferIn(String amount) async {
    try {
      final result = await remoteDataSource.transferIn(amount);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, Map<String, dynamic>>> transferOut(String amount) async {
    try {
      final result = await remoteDataSource.transferOut(amount);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, List<dynamic>>> getTransferHistory({int page = 1, int pageSize = 50}) async {
    try {
      final result = await remoteDataSource.getTransferHistory(page: page, pageSize: pageSize);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, AssetDisplay>> getMyAsset({String? dailyAllocation}) async {
    try {
      final result = await remoteDataSource.getMyAsset(dailyAllocation: dailyAllocation);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, AssetDisplay>> getAccountAsset(String accountSequence, {String? dailyAllocation}) async {
    try {
      final result = await remoteDataSource.getAccountAsset(accountSequence, dailyAllocation: dailyAllocation);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }

  @override
  Future<Either<Failure, List<Kline>>> getKlines({String period = '1h', int limit = 100, DateTime? before}) async {
    try {
      final result = await remoteDataSource.getKlines(period: period, limit: limit, before: before);
      return Right(result);
    } on ServerException catch (e) {
      return Left(ServerFailure(e.message));
    } on NetworkException {
      return Left(const NetworkFailure());
    }
  }
}
