// 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<List<FireflyAccount>> 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');

    final response = await http.get(
      uri,
      headers: {
        'Authorization': 'Bearer $accessToken',
        'Accept': 'application/json',
      },
    );

    if (response.statusCode == 200) {
      final dynamic responseBody = json.decode(response.body);

      if (responseBody is Map<String, dynamic> &&
          responseBody.containsKey('data')) {
        final List accountsJson = responseBody['data'] as List;

        final List<FireflyAccount> accounts = accountsJson
            .map((accountJson) => FireflyAccount.fromJson(accountJson))
            .toList();

        return accounts;
      } else {
        throw Exception('Format respons API tidak sesuai');
      }
    } else {
      // Handle error - misalnya, lempar exception
      throw Exception('Gagal mengambil akun: ${response.statusCode}');
    }
  }

  /// Menguji koneksi ke server Firefly III
  static Future<bool> testServerConnection({required String baseUrl}) async {
    try {
      final response = await http.get(Uri.parse(baseUrl));
      return response.statusCode == 200;
    } catch (e) {
      print('Gagal menguji koneksi: $e');
      return false;
    }
  }

  /// 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<String?> 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,
        }
      ]
    });

    try {
      final response = await http.post(
        uri,
        headers: {
          'Authorization': 'Bearer $accessToken',
          'Accept': 'application/json',
          'Content-Type': 'application/json',
        },
        body: payload,
      );

      if (response.statusCode == 200 || response.statusCode == 201) {
        // Parse response to get transaction ID
        try {
          final dynamic responseBody = json.decode(response.body);

          if (responseBody is Map<String, dynamic> &&
              responseBody.containsKey('data')) {
            final dynamic data = responseBody['data'];

            // Handle case where data is a single object with an 'id' field
            if (data is Map<String, dynamic> && data.containsKey('id')) {
              final transactionId = data['id'].toString();
              return transactionId;
            }

            // Handle case where data is a list with at least one object
            if (data is List && data.isNotEmpty) {
              final firstItem = data[0];
              if (firstItem is Map<String, dynamic>) {
                if (firstItem.containsKey('id')) {
                  final transactionId = firstItem['id'].toString();
                  return transactionId;
                } else if (firstItem.containsKey('transaction_id')) {
                  final transactionId = firstItem['transaction_id'].toString();
                  return transactionId;
                }
              }
            }
          }
        } catch (e) {
          // Don't crash if parsing fails, just return success
        }

        // If we can't parse the ID, return a default success indicator
        return "success";
      } else {
        return null;
      }
    } catch (e) {
      return null;
    }
  }

  /// Mengunggah lampiran langsung ke transaksi di Firefly III.
  ///
  /// [baseUrl] adalah URL dasar instance Firefly III.
  /// [accessToken] adalah Personal Access Token pengguna.
  /// [transactionId] adalah ID transaksi yang akan dilampiri.
  /// [fileBytes] adalah byte data dari file lampiran.
  static Future<bool> uploadAttachment({
    required String baseUrl,
    required String accessToken,
    required String transactionId,
    required List<int> fileBytes,
  }) async {
    final uri = Uri.parse('$baseUrl/api/v1/attachments/$transactionId/upload');

    try {
      // Kirim file sebagai raw binary data dengan Content-Type: application/octet-stream
      final response = await http.post(
        uri,
        headers: {
          'Authorization': 'Bearer $accessToken',
          'Accept': 'application/json',
          'Content-Type': 'application/octet-stream',
        },
        body: fileBytes, // Kirim byte array langsung sebagai body
      );

      if (response.statusCode == 200 || response.statusCode == 204) {
        return true;
      } else {
        print('Upload attachment failed with status: ${response.statusCode}');
        print('Response body: ${response.body}');
        return false;
      }
    } catch (e) {
      print('Upload attachment failed with exception: $e');
      return false;
    }
  }

  /// Menguji koneksi ke Firefly III.
  static Future<bool> testConnection({required String baseUrl}) async {
    try {
      final response = await http.get(Uri.parse(baseUrl));
      return response.statusCode == 200;
    } catch (e) {
      return false;
    }
  }

  /// Menguji autentikasi dengan token.
  static Future<bool> 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;
    }
  }
}
