import 'package:flutter/foundation.dart';
import 'package:rasadyar_core/core.dart';


class DioRemote implements IHttpClient {
  String? baseUrl;
  late final Dio _dio;
  final List<Interceptor> interceptors;

  DioRemote({this.baseUrl, this.interceptors = const []});

  @override
  Future<void> init() async {
    final dio = Dio(BaseOptions(baseUrl: baseUrl ?? ''));
    dio.interceptors.addAll(interceptors);
    if (kDebugMode) {
      dio.interceptors.add(
        PrettyDioLogger(
          requestHeader: true,
          responseHeader: true,
          requestBody: true,
        ),
      );
    }
    _dio = dio;
  }

  @override
  Future<DioResponse<T>> get<T>(
      String path, {
        Map<String, dynamic>? queryParameters,
        Map<String, String>? headers,
        ProgressCallback? onReceiveProgress,
        T Function(Map<String, dynamic> json)? fromJson,
        T Function(List<dynamic> json)? fromJsonList,
      }) async {
    final response = await _dio.get(
      path,
      queryParameters: queryParameters,
      options: Options(headers: headers),
      onReceiveProgress: onReceiveProgress,
      cancelToken: ApiHandler.globalCancelToken
    );
    if (fromJsonList != null && response.data is List) {
      response.data = fromJsonList(response.data);
      return DioResponse<T>(response);
    }
    if (fromJson != null && response.data is Map<String, dynamic>) {
      response.data = fromJson(response.data);
      return DioResponse<T>(response);
    }
    return DioResponse<T>(response);
  }

  @override
  Future<DioResponse<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    T Function(Map<String, dynamic> json)? fromJson,
    Map<String, String>? headers,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    final response = await _dio.post(
      path,
      data: data,
      queryParameters: queryParameters,
      options: Options(headers: headers),
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
        cancelToken: ApiHandler.globalCancelToken
    );

    if (fromJson != null) {
      final rawData = response.data;
      final parsedData = rawData is Map<String, dynamic>
          ? fromJson(rawData)
          : null;
      response.data = parsedData;
      return DioResponse<T>(response);
    }

    return DioResponse<T>(response);
  }

  @override
  Future<DioResponse<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Map<String, String>? headers,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) async {
    final response = await _dio.put(
      path,
      data: data,
      queryParameters: queryParameters,
      options: Options(headers: headers),
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
        cancelToken: ApiHandler.globalCancelToken
    );
    return DioResponse<T>(response);
  }

  @override
  Future<DioResponse<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Map<String, String>? headers,
  }) async {
    final response = await _dio.delete<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: Options(headers: headers),
        cancelToken: ApiHandler.globalCancelToken
    );
    return DioResponse<T>(response);
  }

  @override
  Future<DioResponse<Uint8List>> download<Uint8List>(
    String url, {
    ProgressCallback? onReceiveProgress,
  }) async {
    final response = await _dio.get<Uint8List>(
      url,
      options: Options(responseType: ResponseType.bytes),
      onReceiveProgress: onReceiveProgress,
        cancelToken: ApiHandler.globalCancelToken
    );
    return DioResponse(response);
  }

  @override
  Future<DioResponse<T>> upload<T>(
    String path, {
    required IFormData formData,
    Map<String, String>? headers,
    ProgressCallback? onSendProgress,
  }) async {
    final response = await _dio.post(
      path,
      data: (formData as DioFormData).raw,
      options: Options(headers: headers, contentType: 'multipart/form-data'),
      onSendProgress: onSendProgress,
        cancelToken: ApiHandler.globalCancelToken
    );
    return DioResponse<T>(response);
  }
}
