import 'package:dio/dio.dart'; import '../core/app_config.dart'; import '../models/drive_models.dart'; import '../models/user_profile.dart'; import 'token_store.dart'; class ApiClient { ApiClient(this._tokens) { dio = Dio( BaseOptions( baseUrl: AppConfig.apiBaseUrl, connectTimeout: const Duration(seconds: 20), receiveTimeout: const Duration(minutes: 5), ), ); dio.interceptors.add( InterceptorsWrapper( onRequest: (options, handler) async { final token = await _tokens.read(); if (token != null) { options.headers['Authorization'] = 'Bearer $token'; } final organizationId = await _tokens.readOrganization(); if (organizationId != null) { options.headers['X-Organization-Id'] = organizationId; } handler.next(options); }, ), ); } final TokenStore _tokens; late final Dio dio; String messageFrom(Object error) { if (error is DioException) { final data = error.response?.data; if (data is Map && data['error'] is String) { return data['error'] as String; } if (error.type == DioExceptionType.connectionError) { return 'Cannot reach the server. Check the API address and network.'; } } return 'Something went wrong. Please try again.'; } Future<({String token, UserProfile user})> login( String username, String password, ) async { final response = await dio.post( '/auth/login', data: {'username': username, 'password': password}, ); return ( token: response.data['token'] as String, user: UserProfile.fromJson(response.data['user']), ); } Future register(Map input) async { final response = await dio.post('/auth/register', data: input); return response.data['message'] as String; } Future me() async { final response = await dio.get('/auth/me'); return UserProfile.fromJson(response.data['user']); } Future deleteAccount(String password) => dio.delete('/retention/account', data: {'password': password}); Future lookupOrganization(String code) async { final response = await dio.get( '/organizations/lookup/${Uri.encodeComponent(code)}', ); return OrganizationSummary.fromJson(response.data['organization']); } Future joinOrganization(String code) async { final response = await dio.post( '/auth/join', data: {'organizationCode': code}, ); return response.data['message'] as String; } Future> folders(String? parentId) async { final response = await dio.get( '/folders', queryParameters: parentId == null ? null : {'parentId': parentId}, ); return (response.data['folders'] as List) .map((item) => DriveFolder.fromJson(item)) .toList(); } Future> files(String? folderId) async { final response = await dio.get( '/files', queryParameters: folderId == null ? null : {'folderId': folderId}, ); return (response.data['files'] as List) .map((item) => DriveFile.fromJson(item)) .toList(); } Future createFolder(String name, String? parentId) => dio.post('/folders', data: {'name': name, 'parentId': parentId}); Future deleteFolder(String id) => dio.delete('/folders/$id'); Future deleteFile(String id) => dio.delete('/files/$id'); String contentUrl(String id) => '${AppConfig.apiBaseUrl}/files/$id/content'; }