import 'package:dio/dio.dart';
import 'package:networks_sdk/src/data/datasources/http/interceptor/auth_interceptor.dart';
import 'package:networks_sdk/src/data/datasources/http/interceptor/encryption_interceptor.dart';
import 'package:networks_sdk/src/data/datasources/http/interceptor/logging_interceptor.dart';
import 'package:networks_sdk/src/data/datasources/http/interceptor/retry_interceptor.dart';
import 'package:networks_sdk/src/domain/entities/api_error.dart';
import 'package:networks_sdk/src/presentation/wiring/api_config.dart';

/// REST API 客户端
/// 基于 Dio，提供请求执行入口
///
/// 拦截器链顺序（onRequest）：Auth → 自定义 → Retry → Logging → Encryption
///
/// Dio 的 onResponse / onError 按 **逆序** 执行，因此实际响应处理为：
/// `Encryption(解密) → Logging → Retry(业务码判断) → 自定义 → Auth`
///
/// EncryptionInterceptor 放最后，保证：
/// - onRequest 最后加密（其他拦截器操作明文）
/// - onResponse 最先解密（其他拦截器看到明文，业务码判断正常工作）
///
/// 使用方式：
/// ```dart
/// final client = ApiClient(config: apiConfig);
/// final data = await client.executeRequest(LoginRequest(...));
/// ```
class ApiClient {
  final ApiConfig config;
  final Dio _dio;

  ApiClient({
    required this.config,
    Dio? dio,
    List<Interceptor>? additionalInterceptors,
  }) : _dio = dio ?? Dio() {
    // 配置默认选项
    _dio.options = BaseOptions(
      connectTimeout: const Duration(seconds: 30),
      receiveTimeout: const Duration(seconds: 60),
    );

    // 挂载拦截器
    // onRequest 顺序：Auth → 自定义 → Retry → Logging → Encryption
    // onResponse 逆序：Encryption(解密) → Logging → Retry(业务码) → 自定义 → Auth
    _dio.interceptors.addAll([
      AuthInterceptor(config),
      if (additionalInterceptors != null) ...additionalInterceptors,
      RetryInterceptor(config: config, dio: _dio),
      LoggingInterceptor(onLog: config.onLog),
      EncryptionInterceptor(config),
    ]);
  }

  /// 暴露 Dio 实例（供需要直接操作的场景，如文件上传）
  Dio get dio => _dio;

  /// DioException → ApiError 映射
  ApiError mapDioError(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.receiveTimeout:
      case DioExceptionType.sendTimeout:
        return const ApiError.timeout();
      case DioExceptionType.connectionError:
        return const ApiError.noNetworkConnection();
      case DioExceptionType.cancel:
        return const ApiError.cancelled();
      default:
        if (e.response != null) {
          return ApiError.apiError(
            code: e.response!.statusCode ?? 0,
            message: e.response!.statusMessage ?? e.message ?? 'Request failed',
          );
        }
        return ApiError.networkError(e.message ?? 'Network error');
    }
  }
}
