/// Client HTTP Dio configuré pour l'API UnionFlow
library dio_client;

import 'package:dio/dio.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

/// Configuration du client HTTP Dio
class DioClient {
  static const String _baseUrl = 'http://192.168.1.11:8080'; // URL du backend UnionFlow
  static const int _connectTimeout = 30000; // 30 secondes
  static const int _receiveTimeout = 30000; // 30 secondes
  static const int _sendTimeout = 30000; // 30 secondes

  late final Dio _dio;
  final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();

  DioClient() {
    _dio = Dio();
    _configureDio();
  }

  /// Configuration du client Dio
  void _configureDio() {
    // Configuration de base
    _dio.options = BaseOptions(
      baseUrl: _baseUrl,
      connectTimeout: const Duration(milliseconds: _connectTimeout),
      receiveTimeout: const Duration(milliseconds: _receiveTimeout),
      sendTimeout: const Duration(milliseconds: _sendTimeout),
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    );

    // Intercepteur d'authentification
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        // Ajouter le token d'authentification si disponible
        final token = await _secureStorage.read(key: 'keycloak_webview_access_token');
        print('🔑 Token: ${token != null ? "EXISTS (${token.length} chars)" : "NULL"}');
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
          print('✅ Authorization header added');
        } else {
          print('❌ No token available');
        }
        handler.next(options);
      },
      onError: (error, handler) async {
        // Gestion des erreurs d'authentification
        if (error.response?.statusCode == 401) {
          // Token expiré, essayer de le rafraîchir
          final refreshed = await _refreshToken();
          if (refreshed) {
            // Réessayer la requête avec le nouveau token
            final token = await _secureStorage.read(key: 'keycloak_webview_access_token');
            if (token != null) {
              error.requestOptions.headers['Authorization'] = 'Bearer $token';
              final response = await _dio.fetch(error.requestOptions);
              handler.resolve(response);
              return;
            }
          }
        }
        handler.next(error);
      },
    ));

    // Logger pour le développement
    _dio.interceptors.add(
      LogInterceptor(
        requestHeader: true,
        requestBody: true,
        responseBody: true,
        responseHeader: false,
        error: true,
        logPrint: (obj) => print('🔵 DIO: $obj'),
      ),
    );
  }

  /// Rafraîchit le token d'authentification
  Future<bool> _refreshToken() async {
    try {
      final refreshToken = await _secureStorage.read(key: 'keycloak_webview_refresh_token');
      if (refreshToken == null) return false;

      final response = await Dio().post(
        'http://192.168.1.11:8180/realms/unionflow/protocol/openid-connect/token',
        data: {
          'grant_type': 'refresh_token',
          'refresh_token': refreshToken,
          'client_id': 'unionflow-mobile',
        },
        options: Options(
          headers: {'Content-Type': 'application/x-www-form-urlencoded'},
        ),
      );

      if (response.statusCode == 200) {
        final data = response.data;
        await _secureStorage.write(key: 'keycloak_webview_access_token', value: data['access_token']);
        if (data['refresh_token'] != null) {
          await _secureStorage.write(key: 'keycloak_webview_refresh_token', value: data['refresh_token']);
        }
        return true;
      }
    } catch (e) {
      // Erreur lors du rafraîchissement, l'utilisateur devra se reconnecter
    }
    return false;
  }

  /// Obtient l'instance Dio configurée
  Dio get dio => _dio;

  /// Méthodes de convenance pour les requêtes HTTP

  /// GET request
  Future<Response<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onReceiveProgress,
  }) {
    return _dio.get<T>(
      path,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
      onReceiveProgress: onReceiveProgress,
    );
  }

  /// POST request
  Future<Response<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return _dio.post<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
  }

  /// PUT request
  Future<Response<T>> put<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return _dio.put<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
  }

  /// DELETE request
  Future<Response<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) {
    return _dio.delete<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
    );
  }

  /// PATCH request
  Future<Response<T>> patch<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    ProgressCallback? onSendProgress,
    ProgressCallback? onReceiveProgress,
  }) {
    return _dio.patch<T>(
      path,
      data: data,
      queryParameters: queryParameters,
      options: options,
      cancelToken: cancelToken,
      onSendProgress: onSendProgress,
      onReceiveProgress: onReceiveProgress,
    );
  }
}
