import 'dart:io';
import 'package:be_happy/data/exceptions/auth_block_exception.dart';
import 'package:be_happy/data/exceptions/route_history_not_found_exception.dart';
import 'package:be_happy/data/exceptions/scooter_not_found_exception.dart';
import 'package:be_happy/data/exceptions/unauthorized_exception.dart';
import 'package:be_happy/data/exceptions/wrong_zone_exception.dart';
import 'package:be_happy/domain/entities/point.dart';
import 'package:be_happy/domain/repositories/scooter_repository.dart';

import '../../core/failures.dart';
import '../../core/result.dart';
import '../../domain/entities/active_scooter_order.dart';
import '../../domain/entities/client_subscription.dart';
import '../../domain/entities/scooter.dart';
import '../../domain/entities/tariff.dart';
import '../../domain/entities/subscription.dart';
import '../../domain/entities/scooter_order.dart';
import '../exceptions/auth_exception.dart';
import '../network/api_service.dart';

class ScooterRepositoryImpl extends ScooterRepository {
  final ApiService _apiService;

  final scooter = Scooter(
    id: 123,
    title: "Unnamed",
    status: "Available",
    latitude: 55.178960,
    longitude: 30.222316,
    batteryLevel: 89,
    isOnline: true,
    maxSpeed: 25,
    number: "Unnamed",
  );

  ScooterRepositoryImpl(this._apiService);

  @override
  Future<List<Scooter>> getScooters(
    List<double> area,
    int page,
    int pageSize,
  ) async {
    final responce = await _apiService.getScooters(
      area: area,
      page: page,
      pageSize: pageSize,
    );

    final List<Scooter>? list = responce?.scooters;
    // list?.add(scooter);

    // print("Scooters: ${list?.first.status}");

    if (responce != null) {
      return list ?? List.empty();
    }

    return List.empty();
  }

  @override
  Future<Result<Scooter?>> getScooter(int id) async {
    late final Result<Scooter> result;
    try {
      final scooter = await _apiService.getScooterById(id: id);
      if (scooter != null) {
        result = Success(scooter);
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<Tariff>>> getAvailableTariffs(int scooterId) async {
    late final Result<List<Tariff>> result;
    try {
      final response = await _apiService.getAvailableTariffs(
        scooterId: scooterId,
      );
      if (response != null) {
        result = Success(response.tariffs);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<Subscription>>> getAvailableSubscriptions() async {
    late final Result<List<Subscription>> result;
    try {
      final response = await _apiService.getAvailableSubscriptions();
      if (response != null) {
        result = Success(response.subscriptions);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<Subscription>> getSubscriptionById(int id) async {
    late final Result<Subscription> result;
    try {
      final subscription = await _apiService.getSubscriptionById(id: id);
      if (subscription != null) {
        result = Success(subscription);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<ClientSubscription>>> getClientSubscriptions() async {
    late final Result<List<ClientSubscription>> result;
    try {
      final subscriptions = await _apiService.getClientSubscriptions();
      result = Success(subscriptions);
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> bookScooter({
    required int scooterId,
    required int planId,
    int? subscriptionId,
    int? cardId,
    required bool isBalance,
    required bool isInsurance,
  }) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.bookScooter(
        scooterId: scooterId,
        planId: planId,
        subscriptionId: subscriptionId,
        cardId: cardId,
        isBalance: isBalance,
        isInsurance: isInsurance,
      );
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } on WrongZoneException catch (e) {
      result = Failure(WrongZoneFailure(e.message));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> startRide(int orderId) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.startRide(orderId);
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> cancelRide(int orderId) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.cancelRide(orderId);
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> pauseRide(int orderId) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.pauseRide(orderId);
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> resumeRide(int orderId) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.resumeRide(orderId);
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> finishRide(int orderId, List<int> files) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.finishRide(
        orderId: orderId,
        filesId: files,
      );
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } on WrongZoneException catch (e) {
      result = Failure(WrongZoneFailure(e.message));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<void>> payRide(int orderId) async {
    late final Result<void> result;
    try {
      await _apiService.payRide(orderId);
      result = Success(null);

    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<ScooterOrder>>> getClientOrders() async {
    late final Result<List<ScooterOrder>> result;
    try {
      final orders = await _apiService.getClientOrders();
      result = Success(orders);
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<int>>> uploadScooterPhotos(List<File> images) async {
    late final Result<List<int>> result;
    try {
      final filesId = await _apiService.uploadScooterPhotos(images);
      result = Success(filesId);
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ActiveScooterOrder>> updateScooterOrderData({
    required int orderId,
  }) async {
    late final Result<ActiveScooterOrder> result;
    try {
      final order = await _apiService.updateScooterOrderData(orderId: orderId);
      if (order != null) {
        print("ORDER DATA FROM REPOSITORY: $order");
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<void>> payScooterOrderWithPhotos({
    required int orderId,
    required int? cardId,
    required bool isBalance,
  }) async {
    late final Result<void> result;
    try {
      final order = await _apiService.payScooterOrderWithPhotos(
        orderId: orderId,
        cardId: cardId,
        isBalance: isBalance,
      );
        result = Success(null);
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<ScooterOrder>> getScooterOrderById(int id) async {
    late final Result<ScooterOrder> result;
    try {
      final order = await _apiService.getScooterOrderById(id: id);
      if (order != null) {
        result = Success(order);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<ScooterOrder>>> getScooterOrderHistory({
    int page = 1,
    int pageSize = 20,
  }) async {
    late final Result<List<ScooterOrder>> result;
    try {
      final response = await _apiService.getScooterOrderHistory(
        page: page,
        pageSize: pageSize,
      );
      final List<dynamic> data = response['data'] ?? [];
      final orders = data.map((json) => ScooterOrder.fromJson(json)).toList();
      result = Success(orders);
    } on AuthException catch (e) {
      result = Failure(AuthFailure(e.attemptsLeft));
    } catch (e) {
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<Scooter?>> getScooterByTitle(String title) async {
    late final Result<Scooter?> result;
    try {
      final scooter = await _apiService.getScooterByTitle(title: title);
      if (scooter != null) {
        result = Success(scooter);
      } else {
        result = Failure(UnknownFailure("Неизвестная ошибка"));
      }
    } on ScooterNotFoundException catch (e) {
      result = Failure(ScooterNotFoundFailure(e.message));
    } on UnauthorizedException catch (e) {
      result = Failure(AuthFailure(0, message: e.toString()));
    } on AuthBlockException catch (e) {
      result = Failure(AuthBlockFailure(e.toString()));
    } catch (e, stacktrace) {
      print("REPOSITORY ERROR: $e");
      print("STACKTRACE: $stacktrace");
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }

  @override
  Future<Result<List<Point>>> getScooterOrderRouteHistory(int id) async {
    late final Result<List<Point>> result;
    try {
      final route = await _apiService.getScooterOrderRouteHistory(id: id);
      result = Success(route);
    } on RouteHistoryNotFoundException catch (e) {
      result = Failure(RouteHistoryNotFoundFailure(e.message));
    } on UnauthorizedException catch (e) {
      result = Failure(AuthFailure(0, message: e.toString()));
    } on AuthBlockException catch (e) {
      result = Failure(AuthBlockFailure(e.toString()));
    } catch (e, stacktrace) {
      print("REPOSITORY ERROR: $e");
      print("STACKTRACE: $stacktrace");
      result = Failure(UnknownFailure("Неизвестная ошибка"));
    }
    return result;
  }
}
