import 'package:dio/dio.dart';
import '../constants/app_constants.dart';
import '../storage/secure_storage.dart';

class ApiClient {
  late Dio _dio;
  final SecureStorage _secureStorage;
  String? _baseUrl;

  ApiClient(this._secureStorage);

  Future<void> init(String serverUrl) async {
    _baseUrl = AppConstants.buildApiUrl(serverUrl);
    _dio = Dio(BaseOptions(
      baseUrl: _baseUrl!,
      connectTimeout: AppConstants.connectTimeout,
      sendTimeout: AppConstants.connectTimeout,
      receiveTimeout: AppConstants.receiveTimeout,
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    ));
    _dio.interceptors.addAll([
      _AuthInterceptor(_secureStorage, _dio),
      _ErrorInterceptor(),
      LogInterceptor(requestBody: true, responseBody: true),
    ]);
  }

  Dio get dio => _dio;

  String? get baseUrl => _baseUrl;
}

// ── Auth Interceptor: inject token & auto-refresh on 401 ──────────────────────
class _AuthInterceptor extends Interceptor {
  final SecureStorage _storage;
  final Dio _dio;
  bool _refreshing = false;

  _AuthInterceptor(this._storage, this._dio);

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
    final token = await _storage.getAccessToken();
    if (token != null) {
      options.headers['Authorization'] = 'Bearer $token';
    }
    handler.next(options);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) async {
    if (err.response?.statusCode == 401 && !_refreshing) {
      _refreshing = true;
      try {
        final refresh = await _storage.getRefreshToken();
        if (refresh == null) {
          _refreshing = false;
          handler.next(err);
          return;
        }
        final res = await _dio.post('/auth/refresh',
            data: {'refreshToken': refresh},
            options: Options(headers: {'Authorization': null}));

        if (res.statusCode == 200 && res.data['success'] == true) {
          final data = res.data['data'];
          await _storage.saveTokens(
            accessToken: data['accessToken'],
            refreshToken: data['refreshToken'] ?? refresh,
            role: data['role'],
            userId: data['userId'].toString(),
            displayName: data['displayName'],
            uniqueUserId: data['uniqueUserId'],
          );
          // Retry original request
          err.requestOptions.headers['Authorization'] =
              'Bearer ${data['accessToken']}';
          final retryRes = await _dio.fetch(err.requestOptions);
          _refreshing = false;
          handler.resolve(retryRes);
          return;
        }
      } catch (_) {}
      _refreshing = false;
      await _storage.clearAll();
    }
    handler.next(err);
  }
}

// ── Error Interceptor: normalize errors ───────────────────────────────────────
class _ErrorInterceptor extends Interceptor {
  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    // Let the calling code handle it — just pass through
    handler.next(err);
  }
}
