import 'package:dio/dio.dart';
import '../error/exceptions.dart';

class ErrorInterceptor extends Interceptor {
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    final data = response.data;
    if (data is Map && data['rate_limited'] == true) {
      final waitSeconds = (data['wait_seconds'] as num?)?.toInt() ?? 30;
      handler.reject(
        DioException(
          requestOptions: response.requestOptions,
          error: RateLimitException(waitSeconds: waitSeconds),
          type: DioExceptionType.unknown,
        ),
      );
      return;
    }
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    // Already typed by onResponse — pass through
    final existing = err.error;
    if (existing is RateLimitException ||
        existing is AuthException ||
        existing is NotFoundException ||
        existing is ConflictException ||
        existing is NetworkException ||
        existing is ServerException) {
      handler.next(err);
      return;
    }

    final statusCode = err.response?.statusCode;

    switch (statusCode) {
      case 401:
        handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            error: const AuthException('Session expired. Please log in again.'),
            type: DioExceptionType.unknown,
          ),
        );
        return;
      case 404:
        handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            error: NotFoundException(_extractDetail(err)),
            type: DioExceptionType.unknown,
          ),
        );
        return;
      case 409:
        handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            error: ConflictException(_extractDetail(err)),
            type: DioExceptionType.unknown,
          ),
        );
        return;
      case 429:
        final retryAfter = err.response?.headers.value('retry-after');
        final waitSeconds =
            retryAfter != null ? int.tryParse(retryAfter) ?? 30 : 30;
        handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            error: RateLimitException(waitSeconds: waitSeconds),
            type: DioExceptionType.unknown,
          ),
        );
        return;
    }

    if (err.type == DioExceptionType.connectionTimeout ||
        err.type == DioExceptionType.receiveTimeout ||
        err.type == DioExceptionType.sendTimeout) {
      handler.reject(
        DioException(
          requestOptions: err.requestOptions,
          error: const NetworkException('Connection timed out. Please try again.'),
          type: DioExceptionType.unknown,
        ),
      );
      return;
    }

    if (err.type == DioExceptionType.connectionError) {
      handler.reject(
        DioException(
          requestOptions: err.requestOptions,
          error: const NetworkException('No internet connection.'),
          type: DioExceptionType.unknown,
        ),
      );
      return;
    }

    handler.reject(
      DioException(
        requestOptions: err.requestOptions,
        error: ServerException(_extractDetail(err)),
        type: DioExceptionType.unknown,
      ),
    );
  }

  String _extractDetail(DioException err) {
    final data = err.response?.data;
    if (data is Map && data.containsKey('detail')) {
      return data['detail'].toString();
    }
    return err.message ?? 'An unknown error occurred.';
  }
}