import 'package:flutter/material.dart';

import '../../core.dart';

/// Handles global API requests management with CancelToken.
class ApiHandler {
  // Global CancelToken for all requests.
  static CancelToken _globalCancelToken = CancelToken();

  /// Returns the current global CancelToken.
  static CancelToken get globalCancelToken => _globalCancelToken;

  /// Resets the global CancelToken to a new one.
  static Future<void> reset() async {
    _globalCancelToken = CancelToken();
  }

  /// Cancels all ongoing requests and resets the CancelToken.
  /// [reason] is optional text explaining why requests are canceled.
  static void cancelAllRequests(String reason) {
    if (!_globalCancelToken.isCancelled) {
      _globalCancelToken.cancel(reason);
    }
    reset();
  }
}

typedef AppAsyncCallback<T> = Future<T> Function();
typedef ErrorCallback = Function(dynamic error, StackTrace? stackTrace);
typedef VoidCallback = void Function();

Future<T?> gSafeCall<T>({
  required AppAsyncCallback<T> call,
  Function(T result)? onSuccess,
  ErrorCallback? onError,
  VoidCallback? onComplete,
  bool showLoading = false,
  bool showError = true,
  bool showSuccess = false,
  Function()? onShowLoading,
  Function()? onHideLoading,
  Function(String message)? onShowErrorMessage,
  Function(String message)? onShowSuccessMessage,
  int maxRetries = 0,
  Duration retryDelay = const Duration(seconds: 1),
}) async {
  int retryCount = 0;

  while (retryCount <= maxRetries) {
    try {
      if (showLoading && retryCount == 0) {
        (onShowLoading ?? _defaultShowLoading)();
      }

      final result = await call();

      if (showSuccess) {
        (onShowSuccessMessage ?? defaultShowSuccessMessage)('عملیات با موفقیت انجام شد');
      }

      onSuccess?.call(result);
      return result;
    } catch (error, stackTrace) {
      retryCount++;

      eLog('Error in gSafeCall: $error, retryCount: $retryCount , stackTrace : $stackTrace ');

      if (error is DioException && error.response?.statusCode == 401) {
        if (showError) {
          (onShowErrorMessage ?? _defaultShowErrorMessage)('خطا در احراز هویت');
        }
        onError?.call(error, stackTrace);
        return null;
      }

      if (retryCount > maxRetries || !_isRetryableError(error)) {
        if (showError) {
          final message = _getErrorMessage(error);
          (onShowErrorMessage ?? _defaultShowErrorMessage)(message);
        }
        onError?.call(error, stackTrace);
        return null;
      }

      if (retryCount <= maxRetries) {
        await Future.delayed(retryDelay);
      }
    } finally {
      if (showLoading && retryCount > maxRetries) {
        (onHideLoading ?? _defaultHideLoading)();
      }
      if (retryCount > maxRetries) {
        onComplete?.call();
      }
    }
  }

  return null;
}

bool _isRetryableError(dynamic error) {
  if (error is DioException) {
    // خطاهای قابل retry
    return error.type == DioExceptionType.connectionTimeout ||
        error.type == DioExceptionType.receiveTimeout ||
        error.type == DioExceptionType.sendTimeout ||
        (error.response?.statusCode != null && error.response!.statusCode! >= 500);
  }
  return false;
}

String _getErrorMessage(dynamic error) {
  if (error is DioException) {
    final responseData = error.response?.data;
    if (responseData is Map<String, dynamic> && responseData['result'] != null) {
      return responseData['result'].toString();
    }

    switch (error.type) {
      case DioExceptionType.connectionTimeout:
        return 'خطا در اتصال - زمان اتصال تمام شد';
      case DioExceptionType.receiveTimeout:
        return 'خطا در دریافت پاسخ';
      case DioExceptionType.sendTimeout:
        return 'خطا در ارسال درخواست';
      case DioExceptionType.badCertificate:
        return 'خطا در گواهی امنیتی';
      case DioExceptionType.connectionError:
        return 'خطا در اتصال به سرور';
      case DioExceptionType.unknown:
        return 'خطای نامشخص';
      default:
        if (error.response?.statusCode != null) {
          return 'خطا: ${error.response!.statusCode}';
        }
        return 'خطای نامشخص';
    }
  }
  return error.toString();
}

void _defaultShowLoading() {
  // نمایش loading
  Get.dialog(Center(child: CircularProgressIndicator()), barrierDismissible: false);
}

void _defaultHideLoading() {
  // مخفی کردن loading
  if (Get.isDialogOpen == true) {
    Get.back();
  }
}

void defaultShowSuccessMessage(
  String message, {
  int durationInSeconds = 2,
  VoidCallback? onDismissed,
}) {
  Get.snackbar(
    'موفقیت',
    message,
    duration: Duration(seconds: durationInSeconds),
    snackPosition: SnackPosition.TOP,
    backgroundColor: Colors.green,
    snackbarStatus: (status) {
      if (status == SnackbarStatus.CLOSED) {
        onDismissed?.call();
      }
    },
    colorText: Colors.white,
  );
}

void _defaultShowErrorMessage(String message) {
  Get.snackbar(
    'خطا',
    message,
    snackPosition: SnackPosition.TOP,
    backgroundColor: Colors.red,
    colorText: Colors.white,
  );
}
