import 'dart:convert';
import 'dart:io';

import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:logger/logger.dart';

import '../common/SharedPreferencesUtil.dart';
//import 'custom_interceptors.dart';

class DioClient {
  static final DioClient _instance = DioClient._internal();
  late Dio _dio;

  factory DioClient() => _instance;
  final Logger _logger = Logger();

  DioClient._internal() {
    _dio = Dio(BaseOptions(
      baseUrl: 'https://api.androidrj01.top', // 你的API地址
      connectTimeout: 5000,
      receiveTimeout: 3000,
    ));

    // 仅在调试模式下添加日志拦截器
    assert(() {
      _dio.interceptors.add(LogInterceptor(
        request: true,
        requestBody: true,
        responseBody: true,
        error: true,
        logPrint: _logger.d, // 使用 Logger 插件打印日志
      ));
      return true;
    }());

    //token
    _dio.interceptors.add(TokenInterceptor());
    // 添加拦截器
    _dio.interceptors.add(CustomInterceptors());

    // 添加响应拦截器
    _dio.interceptors.add(InterceptorsWrapper(
      onResponse: (Response<dynamic> response, ResponseInterceptorHandler handler) {
        final responseData = response.data as Map<String, dynamic>;
        if (responseData['ret'] == 1) {
          handler.next(
            Response<dynamic>(
              data: responseData['data'],
              headers: response.headers,
              requestOptions: response.requestOptions,
              statusCode: response.statusCode,
            ),
          );
        } else {
          handler.reject(
            DioError(
              requestOptions: response.requestOptions,
              error: AppException(message: responseData['msg'] ?? 'Unknown Error'),
            ),
          );
        }
      },
    ));


  }

  Dio get dio => _dio;
}

class TokenInterceptor extends Interceptor {
  // 这里假设您有一个方法来从安全存储中获取Token
  Future<String?> getToken() async {
    // 从您存储Token的地方获取Token，例如从SharedPreferences或SecureStorage
    String? token = await SharedPreferencesUtil().getString("token");
    return token;
    //return "Your_Token";
  }

  @override
  Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    final token = await getToken();
    if (token != null) {
      options.headers["Authorization"] = "Bearer $token";
    }
    return super.onRequest(options, handler);
  }
}

class CustomInterceptors extends Interceptor {
  int _retryCount = 0;
  final List<String> _backupUrls = ['https://api.androidrj03.top', 'https://api.androidrj88.com'];

  Future<bool> isConnected() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    return connectivityResult != ConnectivityResult.none;
  }

  @override
  Future<void> onError(DioError err, ErrorInterceptorHandler handler) async {
    // 检查网络连接状态
    bool isConnectNetWork = await isConnected();

    if (!isConnectNetWork) {
      // 无网络连接，设置友好的错误消息
      err.error = AppException(message: "当前网络不可用，请检查您的网络");
      return handler.next(err);
    } else if (err.error is SocketException || err.type == DioErrorType.other) {
      if (_retryCount < _backupUrls.length) {
        // 有网络连接但请求失败，尝试使用备用地址
        err.requestOptions.baseUrl = _backupUrls[_retryCount];
        _retryCount++;
        try {
          final Dio dio = Dio();
          final Response response = await dio.request<dynamic>(
            err.requestOptions.path,
            cancelToken: err.requestOptions.cancelToken,
            data: err.requestOptions.data,
            onReceiveProgress: err.requestOptions.onReceiveProgress,
            onSendProgress: err.requestOptions.onSendProgress,
            queryParameters: err.requestOptions.queryParameters,
            options: Options(
              method: err.requestOptions.method,
              headers: err.requestOptions.headers,
              contentType: err.requestOptions.contentType,
              responseType: err.requestOptions.responseType,
            ),
          );
          return handler.resolve(response);
        } catch (e) {
          return handler.next(err);
        }
      }
    }

    // 其他错误，统一处理
    AppException appException = AppException.create(err);
    debugPrint('DioError===: ${appException.toString()}');
    err.error = appException;
    return handler.next(err);
  }
}

class AppException implements Exception {
  final String message;
  AppException({required this.message});

  static AppException create(DioError err) {
    switch (err.type) {
      case DioErrorType.cancel:
        return AppException(message: '请求被取消');

      case DioErrorType.connectTimeout:
        return AppException(message: '连接超时');

      case DioErrorType.sendTimeout:
        return AppException(message: '请求超时');

      case DioErrorType.receiveTimeout:
        return AppException(message: '响应超时');

      case DioErrorType.response:
        return AppException(
          message: '服务器返回异常，状态码：${err.response?.statusCode}',
        );

      case DioErrorType.other:
        return AppException(
          message: '未知错误: ${err.message}',
        );

      default:
        return AppException(
          message: err.message,
        );
    }
  }

  @override
  String toString() {
    return message;
  }
}
extension DioClientExtension on DioClient {
  Future<dynamic> get(String path, {Map<String, dynamic>? queryParameters}) async {
    final response = await _dio.get(path, queryParameters: queryParameters);
    return _handleResponse(response);
  }

  Future<dynamic> post(String path, {Map<String, dynamic>? data}) async {
    final response = await _dio.post(path, data: data);
    return _handleResponse(response);
  }

  Future<dynamic> put(String path, {Map<String, dynamic>? data}) async {
    final response = await _dio.put(path, data: data);
    return _handleResponse(response);
  }

  Future<void> download(String urlPath, String savePath) async {
    await _dio.download(urlPath, savePath);
  }

  dynamic _handleResponse(Response response) {
    if (response.data is List) {
      return response.data as List<dynamic>;
    } else if (response.data is Map) {
      return response.data as Map<String, dynamic>;
    } else {
      throw Exception('Unsupported data type');
    }
  }

}
