import 'dart:io';
import 'package:cheminova/utils/constants.dart';
import 'package:cheminova/utils/show_snackbar.dart';
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

Future<BodyType?> commonApiService<BodyType>({
  required String url,
  required String method,
  Map<String, dynamic> body = const {},
  File? imageFile,
  bool isFormData = false,
  Map<String, String>? additionalHeaders,
  required BodyType Function(Map<String, dynamic>) fromJson,
}) async {
  try {
    final dio = Dio();

    // Add PrettyDioLogger
    dio.interceptors.add(PrettyDioLogger(
      requestHeader: true,
      requestBody: true,
      responseBody: true,
      responseHeader: false,
      error: true,
      compact: true,
      maxWidth: 90,
    ));

    final prefs = await SharedPreferences.getInstance();
    final token = prefs.getString('token');

    final headers = <String, String>{
      'Content-Type': isFormData ? 'multipart/form-data' : 'application/json',
      if (token != null) 'Authorization': 'Bearer $token',
      ...?additionalHeaders,
    };

    final options = Options(headers: headers);

    dynamic requestData = isFormData ? FormData.fromMap(body) : body;

    if (imageFile != null && isFormData) {
      final fileName = imageFile.path.split('/').last;
      (requestData as FormData).files.add(MapEntry(
        "image",
        await MultipartFile.fromFile(imageFile.path, filename: fileName),
      ));
    }

    final Response response;
    switch (method.toUpperCase()) {
      case "POST":
        response = await dio.post("$baseUrl$url", data: requestData, options: options);
        break;
      case "PUT":
        response = await dio.put("$baseUrl$url", data: requestData, options: options);
        break;
      case "DELETE":
        response = await dio.delete("$baseUrl$url", options: options);
        break;
      case "PATCH":
        response = await dio.patch("$baseUrl$url", data: requestData, options: options);
        break;
      case "GET":
        response = await dio.get("$baseUrl$url", options: options);
        break;
      default:
        throw Exception("Unsupported HTTP method: $method");
    }

    if (url == "/api/rd-login" && response.data['token'] != null) {
      await prefs.setString('token', response.data['token']);
    }

    if (url == "/api/rd-get-me" && response.data['myData'] != null) {
      return fromJson(response.data['myData']);
    }

    return fromJson(response.data);
  } on DioException catch (e) {
    String errorMessage = "An error occurred";
    if (e.response?.data is Map<String, dynamic>) {
      errorMessage = e.response?.data['message'] ?? errorMessage;
    } else if (e.response?.data is String) {
      errorMessage = e.response?.data;
    }

    showSnackbar(errorMessage);
    return null;
  } catch (e) {
    print("Unexpected error for $url: $e");
    showSnackbar("An unexpected error occurred");
    return null;
  }
}