import 'package:dio/dio.dart';

abstract class ApiException implements Exception {
  final String message;
  final int? statusCode;

  const ApiException(this.message, {this.statusCode});

  factory ApiException.fromDioError(Object error) {
    if (error is ApiException) return error;
    if (error is DioException) {
      final response = error.response;
      final statusCode = response?.statusCode;
      final data = response?.data;

      String detail;
      if (data is Map<String, dynamic>) {
        detail =
            (data['detail'] ?? data['message'] ?? data['error'])?.toString() ??
            '请求失败';
      } else {
        detail = '请求失败';
      }

      final localized = _localizeError(detail, statusCode);

      if (statusCode == 401) {
        return UnauthorizedException(localized);
      }
      if (statusCode == 422) {
        return ValidationException(
          localized,
          errors: data,
          statusCode: statusCode,
        );
      }
      return ServerException(localized, statusCode: statusCode);
    }
    return const ServerException('网络错误');
  }

  static String _localizeError(String detail, int? statusCode) {
    if (statusCode == 403) {
      return '没有权限执行此操作';
    }
    if (statusCode == 404) {
      return '请求的资源不存在';
    }
    if (statusCode == 429) {
      return '请求过于频繁，请稍后再试';
    }
    if (statusCode != null && statusCode >= 500) {
      return '服务器错误，请稍后再试';
    }
    return detail;
  }
}

class ServerException extends ApiException {
  const ServerException(super.message, {super.statusCode});
}

class UnauthorizedException extends ApiException {
  const UnauthorizedException([super.message = '请重新登录'])
    : super(statusCode: 401);
}

class ValidationException extends ApiException {
  final Map<String, dynamic>? errors;
  const ValidationException(super.message, {this.errors, super.statusCode});
}
