import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; // For cache storage import 'package:sheetless/utility.dart'; import 'sheet.dart'; class ApiClient { final log = Logger("ApiClient"); final String baseUrl; String? token; ApiClient({required this.baseUrl, this.token}); Future> login(String username, String password) async { log.info("Logging in..."); try { final url = '$baseUrl/login'; final response = await http.post( Uri.parse(url), headers: {'Content-Type': 'application/json'}, body: jsonEncode({'email': username, 'password': password}), ); if (response.statusCode == 200) { token = jsonDecode(response.body); log.info('Login successful'); return Result.ok(null); } else { log.warning('Login failed: ${response.statusCode}, ${response.body}'); return Result.error( Exception( "Response code ${response.statusCode}\nResponse: ${response.body}", ), ); } } on Exception catch (e) { log.warning('Error during login', e); return Result.error(e); } } void logout() { token = null; log.info('Logged out successfully.'); } Future get(String endpoint, {bool isBinary = false}) async { try { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', if (!isBinary) 'Content-Type': 'application/json', }; final response = await http.get(Uri.parse(url), headers: headers); if (response.statusCode == 200) { return response; } else { log.warning( 'GET request failed: ${response.statusCode} ${response.body}', ); } } catch (e) { log.warning('Error during GET request', e); } return null; } Future post( String endpoint, Map body, ) async { try { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }; final response = await http.post( Uri.parse(url), headers: headers, body: jsonEncode(body), ); if (response.statusCode == 200 || response.statusCode == 201) { return response; } else { log.info( 'POST request failed: ${response.statusCode} ${response.body}', ); } } catch (e) { log.info('Error during POST request: $e'); } return null; } Future postFormData(String endpoint, String body) async { try { final url = '$baseUrl$endpoint'; final headers = { 'Authorization': 'Bearer $token', 'Content-Type': 'application/x-www-form-urlencoded', }; final response = await http.post( Uri.parse(url), headers: headers, body: body, ); if (response.statusCode == 200 || response.statusCode == 201) { return response; } else { log.info( 'POST Form Data request failed: ${response.statusCode} ${response.body}', ); } } catch (e) { log.info('Error during POST Form Data request: $e'); } return null; } Future> fetchSheets() async { try { final response = await get("/list/sheets"); if (response == null) { return List.empty(); } if (response.statusCode == 200) { final data = jsonDecode(response.body); return (data as List) .map((sheet) => Sheet.fromJson(sheet as Map)) .toList(); } else { log.warning( 'Failed to fetch sheets with status: ${response.statusCode}', ); log.info('Response: ${response.body}'); } } catch (e) { log.warning('Error during fetching sheets', e); } return List.empty(); } Future fetchPdfFileData(String sheetUuid) async { try { final response = await get('/sheet/pdf/$sheetUuid', isBinary: true); if (response != null && response.statusCode == 200) { log.info("PDF downloaded"); return response.bodyBytes; } else { log.warning( "Failed to fetch PDF from API. Status: ${response?.statusCode}", ); } } catch (e) { log.warning("Error fetching PDF", e); } return null; } Future getPdfFileCached(String sheetUuid) async { try { final cacheDir = await getTemporaryDirectory(); final cachedPdfPath = '${cacheDir.path}/$sheetUuid.pdf'; final cachedFile = File(cachedPdfPath); if (await cachedFile.exists()) { log.info("PDF found in cache: $cachedPdfPath"); return cachedFile; } final pdfFileData = await fetchPdfFileData(sheetUuid); await cachedFile.writeAsBytes( pdfFileData!, ); // TODO: proper error handling log.info("PDF cached at: $cachedPdfPath"); return cachedFile; } catch (e) { log.warning("Error fetching PDF", e); } return null; } }