import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../constants/app_constants.dart';
import '../error/exceptions.dart';

class ApiClient {
  final Dio dio;

  // 缓存 SharedPreferences 实例，避免每次请求都阻塞读取
  static SharedPreferences? _prefsCache;
  static Future<SharedPreferences>? _prefsFuture;

  // 全局回调，用于处理 401 跳转登录
  static void Function()? onUnauthorized;
  // 全局回调，用于处理 403 LOGIN 被禁用（强制下线）
  static void Function(String message)? onLoginDisabled;

  ApiClient({required this.dio}) {
    dio.options = BaseOptions(
      baseUrl: AppConstants.baseUrl,
      connectTimeout: AppConstants.connectionTimeout,
      receiveTimeout: AppConstants.receiveTimeout,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    );

    // 添加请求拦截器，自动注入 token
    dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        // 使用缓存的 SharedPreferences 实例，避免阻塞
        final prefs = await _getPrefs();
        final token = prefs.getString('access_token');
        if (token != null && token.isNotEmpty) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        handler.next(options);
      },
      onError: (error, handler) {
        // 全局处理 401 错误
        if (error.response?.statusCode == 401) {
          onUnauthorized?.call();
        }
        // 全局处理 403 LOGIN 禁用 — 强制下线
        if (error.response?.statusCode == 403) {
          final data = error.response?.data;
          final errorObj = data is Map ? data['error'] : null;
          final errorMsg = errorObj is Map ? errorObj['message'] : null;
          if (errorMsg is String && errorMsg.contains('限制登录')) {
            onLoginDisabled?.call(errorMsg);
          }
        }
        handler.next(error);
      },
    ));
  }

  // 获取缓存的 SharedPreferences 实例
  static Future<SharedPreferences> _getPrefs() async {
    if (_prefsCache != null) return _prefsCache!;
    _prefsFuture ??= SharedPreferences.getInstance();
    _prefsCache = await _prefsFuture;
    return _prefsCache!;
  }

  // 清除缓存（登录/登出时调用）
  static void clearPrefsCache() {
    _prefsCache = null;
    _prefsFuture = null;
  }

  Future<Response> get(
    String path, {
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final response = await dio.get(path, queryParameters: queryParameters);
      return _handleResponse(response);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Future<Response> post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final response = await dio.post(path, data: data, queryParameters: queryParameters);
      return _handleResponse(response);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Future<Response> put(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final response = await dio.put(path, data: data, queryParameters: queryParameters);
      return _handleResponse(response);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Future<Response> delete(
    String path, {
    Map<String, dynamic>? queryParameters,
  }) async {
    try {
      final response = await dio.delete(path, queryParameters: queryParameters);
      return _handleResponse(response);
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Response _handleResponse(Response response) {
    if (response.statusCode != null && response.statusCode! >= 200 && response.statusCode! < 300) {
      final data = response.data;
      if (data is Map && data['success'] == true) {
        return Response(
          requestOptions: response.requestOptions,
          data: data['data'],
          statusCode: response.statusCode,
        );
      }
      return response;
    }
    throw ServerException('请求失败', statusCode: response.statusCode);
  }

  Exception _handleError(DioException e) {
    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        return NetworkException('连接超时');
      case DioExceptionType.connectionError:
        return NetworkException('网络连接失败');
      case DioExceptionType.badResponse:
        final statusCode = e.response?.statusCode;
        if (statusCode == 401) {
          return UnauthorizedException();
        }
        if (statusCode == 403) {
          final data = e.response?.data;
          // 后端 ExceptionFilter 统一包装为 { success, error: { code, message }, ... }
          final error = data is Map ? data['error'] : null;
          final rawMsg = error is Map ? error['message'] : null;
          final msg = rawMsg is String
              ? rawMsg
              : (rawMsg is List && rawMsg.isNotEmpty)
                  ? rawMsg[0].toString()
                  : '功能已被限制';
          return ForbiddenException(msg);
        }
        final messages = e.response?.data?['error']?['message'];
        final message = (messages is List && messages.isNotEmpty) ? messages[0].toString() : '服务器错误';
        return ServerException(message, statusCode: statusCode);
      default:
        return ServerException(e.message ?? '未知错误');
    }
  }
}
