import 'dart:io';
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:qhd_prevention/customWidget/toast_util.dart';
import 'package:qhd_prevention/tools/tools.dart';

/// 全局接口异常
class ApiException implements Exception {
  final String result;
  final String message;
  ApiException(this.result, this.message);

  @override
  String toString() => 'ApiException($result): $message';
}

/// HTTP 方法枚举
enum Method { get, post, put, delete }

/// HTTP 管理器 单例
class HttpManager {
  HttpManager._internal() {
    _dio = Dio(BaseOptions(
      connectTimeout: const Duration(milliseconds: 10000),
      receiveTimeout: const Duration(milliseconds: 10000),
      headers: {
        'Content-Type': Headers.formUrlEncodedContentType,
      },
    ));
    _initInterceptors();
  }

  static final HttpManager _instance = HttpManager._internal();
  factory HttpManager() => _instance;
  late final Dio _dio;

  // 添加401处理回调
  static VoidCallback? onUnauthorized;

  void _initInterceptors() {
    _dio.interceptors
      ..add(LogInterceptor(request: true, responseBody: true, error: true))
      ..add(InterceptorsWrapper(onError: (err, handler) {
        // TODO 暂不处理
        // 捕获401错误
        if (err.response?.statusCode == 401) {
          // 触发全局登出回调
          onUnauthorized?.call();
          // 创建自定义异常
          final apiException = ApiException(
              '提示',
              '您的账号已在其他设备登录，已自动下线'
          );
          // 直接抛出业务异常，跳过后续错误处理
          return handler.reject(
            DioException(
              requestOptions: err.requestOptions,
              error: apiException,
              response: err.response,
              type: DioExceptionType.badResponse,
            ),
          );
        }
        handler.next(err);
      }));
  }

  /// 通用请求方法，返回完整后台 JSON
  Future<Map<String, dynamic>> request(
      String baseUrl,
      String path, {
        Method method = Method.post,
        Map<String, dynamic>? data,
        Map<String, dynamic>? params,
        CancelToken? cancelToken,
        bool withToken = false, //  新增可选参数，默认 false
      }) async {
    Response resp;
    final url = baseUrl + path;

    // 动态 headers
    final headers = {
      'Content-Type': Headers.formUrlEncodedContentType,
    };
    if (withToken) {
      final token = SessionService.instance.studyToken;
      if (token != null && token.isNotEmpty) {
        headers['Token'] = token;
      }
    }

    final options = Options(
      method: method.name.toUpperCase(),
      contentType: Headers.formUrlEncodedContentType,
      headers: headers,
    );

    try {
      switch (method) {
        case Method.get:
          resp = await _dio.get(url,
              queryParameters: {...?params, ...?data},
              cancelToken: cancelToken,
              options: options);
          break;
        case Method.post:
          resp = await _dio.post(url,
              data: data,
              queryParameters: params,
              cancelToken: cancelToken,
              options: options);
          break;
        case Method.put:
          resp = await _dio.put(url,
              data: data,
              queryParameters: params,
              cancelToken: cancelToken,
              options: options);
          break;
        case Method.delete:
          resp = await _dio.delete(url,
              queryParameters: params,
              cancelToken: cancelToken,
              options: options);
          break;
      }
    } on DioException catch (e) {
      if (e.error is ApiException) throw e.error as ApiException;
      throw ApiException('network_error', e.message ?? e.toString());
    }

    final json = resp.data is Map<String, dynamic>
        ? resp.data as Map<String, dynamic>
        : <String, dynamic>{};
    return json;
  }
}

/// 上传图片扩展
extension HttpManagerUpload on HttpManager {
  Future<Map<String, dynamic>> uploadFaceImage({
    required String baseUrl,
    required String path,
    required Map<String, dynamic> fromData,
    CancelToken? cancelToken,
  }) async {
    final form = FormData.fromMap(fromData);
    try {
      final resp = await _dio.post(
        baseUrl + path,
        data: form,
        cancelToken: cancelToken,
        options: Options(
          method: Method.post.name.toUpperCase(),
          contentType: 'multipart/form-data',
        ),
      );

      final json = resp.data is Map<String, dynamic>
          ? resp.data as Map<String, dynamic>
          : <String, dynamic>{};

      return json;
    } on DioException catch (e) {
      // 如果已经是ApiException类型（401转换的）
      if (e.error is ApiException) {
        throw e.error as ApiException;
      }
      throw ApiException('network_error', e.message ?? e.toString());
    }
  }
}