import 'package:dio/dio.dart';
import '../../core/error/exceptions.dart';
import '../../core/network/api_client.dart';
import '../dto/vacation_request_dto.dart';
import '../dto/vacation_response_dto.dart';
import '../dto/vacation_type_dto.dart';
import '../dto/vacations_list_response_dto.dart';

abstract class VacationRemoteDataSource {
  Future<VacationResponseDto> createVacation(VacationRequestDto request);
  Future<VacationTypesResponseDto> getVacationTypes();
  Future<VacationsListResponseDto> getVacations();
}

class VacationRemoteDataSourceImpl implements VacationRemoteDataSource {
  final ApiClient apiClient;

  VacationRemoteDataSourceImpl({required this.apiClient});

  @override
  Future<VacationResponseDto> createVacation(VacationRequestDto request) async {
    try {
      final response = await apiClient.post(
        '/Vacation',
        data: request.toJson(),
      );

      if (response.statusCode == 200 || response.statusCode == 201) {
        final responseData = response.data;

        if (responseData is Map<String, dynamic>) {
          return VacationResponseDto.fromJson(responseData);
        } else {
          throw ServerException(
            message: 'استجابة غير صحيحة من الخادم',
            statusCode: response.statusCode,
          );
        }
      } else {
        throw ServerException(
          message: 'فشل إنشاء طلب الإجازة',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.receiveTimeout) {
        throw NetworkException(message: 'انتهت مهلة الاتصال');
      } else if (e.type == DioExceptionType.connectionError) {
        throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
      } else if (e.response?.statusCode == 500) {
        throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
      } else if (e.response != null) {
        final message =
            e.response?.data?['message'] ??
            e.response?.data?['error'] ??
            'فشل إنشاء طلب الإجازة';

        throw ServerException(
          message: message.toString(),
          statusCode: e.response?.statusCode,
        );
      } else {
        throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
      }
    } catch (e) {
      if (e is ServerException || e is NetworkException) {
        rethrow;
      }
      print('خطأ غير متوقع: $e');
      throw ServerException(message: 'خطأ غير متوقع');
    }
  }

  @override
  Future<VacationTypesResponseDto> getVacationTypes() async {
    try {
      final response = await apiClient.get('/enums/vacation-types');

      if (response.statusCode == 200) {
        final responseData = response.data;

        if (responseData is Map<String, dynamic>) {
          return VacationTypesResponseDto.fromJson(responseData);
        } else {
          throw ServerException(
            message: 'استجابة غير صحيحة من الخادم',
            statusCode: response.statusCode,
          );
        }
      } else {
        throw ServerException(
          message: 'فشل جلب أنواع الإجازات',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.receiveTimeout) {
        throw NetworkException(message: 'انتهت مهلة الاتصال');
      } else if (e.type == DioExceptionType.connectionError) {
        throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
      } else if (e.response?.statusCode == 500) {
        throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
      } else if (e.response != null) {
        final message =
            e.response?.data?['message'] ??
            e.response?.data?['error'] ??
            'فشل جلب أنواع الإجازات';

        throw ServerException(
          message: message.toString(),
          statusCode: e.response?.statusCode,
        );
      } else {
        throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
      }
    } catch (e) {
      if (e is ServerException || e is NetworkException) {
        rethrow;
      }
      print('خطأ غير متوقع: $e');
      throw ServerException(message: 'خطأ غير متوقع');
    }
  }

  @override
  Future<VacationsListResponseDto> getVacations() async {
    try {
      final response = await apiClient.get('/Vacation');

      if (response.statusCode == 200) {
        final responseData = response.data;

        if (responseData is Map<String, dynamic>) {
          return VacationsListResponseDto.fromJson(responseData);
        } else {
          throw ServerException(
            message: 'استجابة غير صحيحة من الخادم',
            statusCode: response.statusCode,
          );
        }
      } else {
        throw ServerException(
          message: 'فشل جلب قائمة الإجازات',
          statusCode: response.statusCode,
        );
      }
    } on DioException catch (e) {
      if (e.type == DioExceptionType.connectionTimeout ||
          e.type == DioExceptionType.receiveTimeout) {
        throw NetworkException(message: 'انتهت مهلة الاتصال');
      } else if (e.type == DioExceptionType.connectionError) {
        throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
      } else if (e.response?.statusCode == 500) {
        throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
      } else if (e.response != null) {
        final message =
            e.response?.data?['message'] ??
            e.response?.data?['error'] ??
            'فشل جلب قائمة الإجازات';

        throw ServerException(
          message: message.toString(),
          statusCode: e.response?.statusCode,
        );
      } else {
        throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
      }
    } catch (e) {
      if (e is ServerException || e is NetworkException) {
        rethrow;
      }
      print('خطأ غير متوقع: $e');
      throw ServerException(message: 'خطأ غير متوقع');
    }
  }
}
