// lib/services/firefly_api_service.dart import 'dart:convert'; import 'package:http/http.dart' as http; import '../models/firefly_account.dart'; class FireflyApiService { /// Mengambil daftar akun dari Firefly III API. /// /// [baseUrl] adalah URL dasar instance Firefly III (e.g., https://firefly.yourdomain.com). /// [accessToken] adalah Personal Access Token pengguna. /// [type] adalah filter opsional untuk tipe akun (e.g., 'asset', 'revenue'). static Future> fetchAccounts({ required String baseUrl, required String accessToken, String? type, }) async { final uri = type != null ? Uri.parse('$baseUrl/api/v1/accounts?type=$type') : Uri.parse('$baseUrl/api/v1/accounts'); print('DEBUG: Memanggil API untuk mengambil akun. URL: $uri'); final response = await http.get( uri, headers: { 'Authorization': 'Bearer $accessToken', 'Accept': 'application/json', }, ); print('DEBUG: Respons API diterima. Status Code: ${response.statusCode}'); if (response.statusCode == 200) { final dynamic responseBody = json.decode(response.body); print('DEBUG: Isi respons (data): ${responseBody['data']}'); if (responseBody is Map && responseBody.containsKey('data')) { final List accountsJson = responseBody['data'] as List; print('DEBUG: Jumlah akun ditemukan: ${accountsJson.length}'); final List accounts = accountsJson .map((accountJson) => FireflyAccount.fromJson(accountJson)) .toList(); print('DEBUG: Akun berhasil diparsing. Jumlah akun: ${accounts.length}'); return accounts; } else { print('DEBUG: Format respons tidak sesuai harapan. Isi lengkap: $responseBody'); throw Exception('Format respons API tidak sesuai'); } } else { // Handle error - misalnya, lempar exception print('Gagal mengambil akun: ${response.statusCode} - ${response.body}'); throw Exception('Gagal mengambil akun: ${response.statusCode}'); } } /// Mengirim transaksi dummy ke Firefly III API. /// /// [baseUrl] adalah URL dasar instance Firefly III. /// [accessToken] adalah Personal Access Token pengguna. /// [sourceId] dan [destinationId] adalah ID akun yang valid. /// [type] adalah tipe transaksi (default 'deposit'). static Future submitDummyTransaction({ required String baseUrl, required String accessToken, required String sourceId, required String destinationId, String type = 'deposit', String description = 'Pengeluaran Dummy via Flutter App', String date = '2025-08-19', // Gunakan format ISO 8601 String amount = '50.00', }) async { final uri = Uri.parse('$baseUrl/api/v1/transactions'); final payload = jsonEncode({ "transactions": [ { "type": type, "date": date, "amount": amount, "description": description, "source_id": sourceId, "destination_id": destinationId, } ] }); print('DEBUG: Mengirim transaksi. URL: $uri, Payload: $payload'); final response = await http.post( uri, headers: { 'Authorization': 'Bearer $accessToken', 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: payload, ); print('DEBUG: Respons API transaksi diterima. Status Code: ${response.statusCode}'); if (response.statusCode == 200 || response.statusCode == 201) { print('Transaksi berhasil dikirim!'); return true; } else { print('Gagal mengirim transaksi: ${response.statusCode} - ${response.body}'); return false; } } /// Menguji koneksi ke Firefly III. static Future testConnection({required String baseUrl}) async { try { final response = await http.get(Uri.parse('$baseUrl/api/v1/about')); return response.statusCode == 200; } catch (e) { return false; } } /// Menguji autentikasi dengan token. static Future testAuthentication({required String baseUrl, required String accessToken}) async { try { final response = await http.get( Uri.parse('$baseUrl/api/v1/about/user'), headers: { 'Authorization': 'Bearer $accessToken', 'Accept': 'application/json', }, ); return response.statusCode == 200; } catch (e) { return false; } } }