import 'dart:convert'; import 'package:dio/dio.dart'; import '../../core/constants/app_constants.dart'; import '../../core/errors/exceptions.dart'; import '../../domain/entities/contenedor.dart'; import '../../domain/entities/destino.dart'; class BackendApi { final Dio _dio; BackendApi() : _dio = Dio() { _dio.options.connectTimeout = AppConstants.httpTimeout; _dio.options.receiveTimeout = AppConstants.httpTimeout; } Future> enviarContenedor( Contenedor contenedor, Destino destino, ) async { try { final archivosJson = contenedor.archivos.map((a) => { 'nombre': a.nombre, 'tipo': a.mimeType, 'contenido': base64Encode(a.bytes), }).toList(); final response = await _dio.post( '${destino.url}/ingest', options: Options( headers: { 'X-Auth-Key': destino.hash, 'Content-Type': 'application/json', }, ), data: { 'hash': contenedor.hash, if (contenedor.titulo != null) 'titulo': contenedor.titulo, if (contenedor.descripcion != null) 'descripcion': contenedor.descripcion, 'etiquetas': contenedor.etiquetas, if (contenedor.gps != null) 'gps': contenedor.gps!.toJson(), 'archivos': archivosJson, }, ); return response.data as Map; } on DioException catch (e) { if (e.response?.statusCode == 409) { throw HashExistsException(); } throw NetworkException( e.message ?? 'Network error', code: e.response?.statusCode?.toString(), ); } } Future initChunkUpload( String hash, int totalChunks, String fileName, Destino destino, ) async { try { final response = await _dio.post( '${destino.url}/upload/init', options: Options( headers: {'X-Auth-Key': destino.hash}, ), data: { 'hash': hash, 'total_chunks': totalChunks, 'file_name': fileName, }, ); return response.data['upload_id'] as String; } on DioException catch (e) { throw NetworkException(e.message ?? 'Failed to init upload'); } } Future uploadChunk( String uploadId, int chunkNumber, List bytes, Destino destino, ) async { try { await _dio.post( '${destino.url}/upload/chunk/$uploadId/$chunkNumber', options: Options( headers: { 'X-Auth-Key': destino.hash, 'Content-Type': 'application/octet-stream', }, ), data: bytes, ); } on DioException catch (e) { throw NetworkException(e.message ?? 'Failed to upload chunk'); } } Future> completeUpload( String uploadId, Destino destino, ) async { try { final response = await _dio.post( '${destino.url}/upload/complete/$uploadId', options: Options( headers: {'X-Auth-Key': destino.hash}, ), ); return response.data as Map; } on DioException catch (e) { throw NetworkException(e.message ?? 'Failed to complete upload'); } } }