import 'dart:io';
import 'package:dio/dio.dart';
import '../../logger.dart';
import '../../event_bus.dart';
import '../exceptions/app_exception.dart';
import '../exceptions/business_exception.dart';
import '../exceptions/cancel_exception.dart';
import '../exceptions/network_exception.dart';
import '../exceptions/server_exception.dart';

class ErrorInterceptor extends Interceptor {
  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    final uuid = err.requestOptions.extra['uuid'] as String? ?? '';
    final AppException exception = _handleError(err, uuid);

    // 如果是 401，发送 Token 过期事件
    if (err.response?.statusCode == 401) {
      eventBus.emit(TokenExpiredEvent());
    }

    _printErrorLog(err, uuid, exception);

    handler.next(DioException(
      requestOptions: err.requestOptions,
      error: exception,
      type: err.type,
      response: err.response,
    ));
  }

  AppException _handleError(DioException err, String uuid) {
    switch (err.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        return NetworkException(
          message: '网络连接超时，请检查网络后重试',
          code: -1,
          uuid: uuid,
        );

      case DioExceptionType.badResponse:
        final statusCode = err.response?.statusCode;
        final data = err.response?.data;
        String message = '服务器异常，请稍后重试';

        if (data is Map<String, dynamic>) {
          message = data['msg'] as String? ?? message;
        }

        if (statusCode == null) {
          return ServerException(
            message: message,
            code: statusCode,
            uuid: uuid,
          );
        }

        switch (statusCode) {
          case 400:
            return BusinessException(
              message: message,
              code: statusCode,
              uuid: uuid,
            );
          case 401:
            return BusinessException(
              message: '登录已过期，请重新登录',
              code: statusCode,
              uuid: uuid,
            );
          case 403:
            return BusinessException(
              message: '没有权限访问',
              code: statusCode,
              uuid: uuid,
            );
          case 404:
            return ServerException(
              message: '请求的资源不存在',
              code: statusCode,
              uuid: uuid,
            );
          case >= 500:
            return ServerException(
              message: message,
              code: statusCode,
              uuid: uuid,
            );
          default:
            return BusinessException(
              message: message,
              code: statusCode,
              uuid: uuid,
            );
        }

      case DioExceptionType.cancel:
        return CancelException(uuid: uuid);

      case DioExceptionType.unknown:
        if (err.error is SocketException) {
          return NetworkException(
            message: '网络连接失败，请检查网络后重试',
            uuid: uuid,
          );
        }
        return AppException(
          message: err.message ?? '未知错误',
          code: -1,
          uuid: uuid,
        );

      case DioExceptionType.badCertificate:
        return NetworkException(
          message: '安全证书验证失败',
          uuid: uuid,
        );

      case DioExceptionType.connectionError:
        return NetworkException(
          message: '网络连接失败，请检查网络后重试',
          uuid: uuid,
        );
    }
  }

  void _printErrorLog(DioException err, String uuid, AppException exception) {
    Log.error('========== Error START ==========');
    Log.error('UUID: $uuid');
    Log.error('Error Type: ${err.type}');
    Log.error('Error Message: ${err.message}');
    Log.error('Exception: $exception');
    if (err.response != null) {
      Log.error('Status Code: ${err.response?.statusCode}');
      Log.error('Response Data: ${err.response?.data}');
    }
    Log.error('========== Error END ==========');
  }
}