// lib/services/receipt_service.dart

import 'package:shared_preferences/shared_preferences.dart';
import 'package:cashumit/models/firefly_account.dart';
import 'package:cashumit/models/receipt_item.dart';
import 'package:cashumit/services/firefly_api_service.dart';

class ReceiptService {
  /// Memuat kredensial dari shared preferences.
  ///
  /// Mengembalikan Map dengan key 'url' dan 'token' jika kredensial ada dan valid,
  /// atau null jika tidak ditemukan atau tidak valid.
  static Future<Map<String, String>?> loadCredentials() async {
    final prefs = await SharedPreferences.getInstance();
    final url = prefs.getString('firefly_url');
    final token = prefs.getString('firefly_token');

    if (url == null || token == null || url.isEmpty || token.isEmpty) {
      return null;
    }

    return {'url': url, 'token': token};
  }

  /// Memuat daftar akun sumber (revenue) dan tujuan (asset) dari API.
  ///
  /// Mengembalikan daftar akun yang berisi akun revenue dan asset.
  /// Melempar exception jika terjadi kesalahan saat memuat akun.
  static Future<List<Map<String, dynamic>>> loadAccounts({
    required String baseUrl,
    required String accessToken,
  }) async {
    // Mengambil akun revenue
    final revenueAccounts = await FireflyApiService.fetchAccounts(
      baseUrl: baseUrl,
      accessToken: accessToken,
      type: 'revenue',
    );

    // Mengambil akun asset
    final assetAccounts = await FireflyApiService.fetchAccounts(
      baseUrl: baseUrl,
      accessToken: accessToken,
      type: 'asset',
    );

    // Menggabungkan akun revenue dan asset untuk dropdown
    final allAccounts = <Map<String, dynamic>>[];
    for (var account in revenueAccounts) {
      allAccounts.add({
        'id': account.id,
        'name': account.name,
        'type': account.type,
      });
    }
    for (var account in assetAccounts) {
      allAccounts.add({
        'id': account.id,
        'name': account.name,
        'type': account.type,
      });
    }

    return allAccounts;
  }

  /// Mencari ID akun berdasarkan nama dan tipe akun.
  static String? findAccountIdByName({
    required String name,
    required String expectedType,
    required List<Map<String, dynamic>> accounts,
  }) {
    if (name.isEmpty) return null;

    try {
      // Cari akun dengan nama yang cocok dan tipe yang diharapkan
      final account = accounts.firstWhere(
        (account) =>
            account['name'].toString().toLowerCase() == name.toLowerCase() &&
            account['type'] == expectedType,
      );

      return account['id'] as String?;
    } catch (e) {
      // Jika tidak ditemukan, coba pencarian yang lebih fleksibel
      for (var account in accounts) {
        if (account['type'] == expectedType &&
            account['name']
                .toString()
                .toLowerCase()
                .contains(name.toLowerCase())) {
          return account['id'] as String?;
        }
      }

      // Jika masih tidak ditemukan, kembalikan null
      return null;
    }
  }

  /// Generates a transaction description based on item names
  static String generateTransactionDescription(List<ReceiptItem> items) {
    if (items.isEmpty) {
      return 'Transaksi Struk Belanja';
    }

    // Take the first 5 item descriptions
    final itemNames = items.take(5).map((item) => item.description).toList();

    // If there are more than 5 items, append ', dll' to the last item
    if (items.length > 5) {
      itemNames[4] += ', dll';
    }

    // Join the item names with ', '
    return itemNames.join(', ');
  }

  /// Mengirim transaksi ke Firefly III.
  ///
  /// Sebelum mengirim transaksi, metode ini melakukan beberapa validasi:
  /// 1. Memastikan ada item yang akan dikirim
  /// 2. Memastikan akun sumber dan tujuan telah dipilih atau dimasukkan
  /// 3. Memastikan akun sumber dan tujuan berbeda
  /// 4. Memastikan akun sumber dan tujuan ada di daftar akun yang dimuat
  /// 5. Memastikan tipe akun sesuai (sumber: revenue, tujuan: asset)
  ///
  /// Mengembalikan transactionId jika berhasil, atau null jika gagal.
  /// Melempar exception jika ada error validasi.
  static Future<String?> submitTransaction({
    required List<ReceiptItem> items,
    required DateTime transactionDate,
    required String sourceAccountId,
    required String destinationAccountId,
    required List<Map<String, dynamic>> accounts, // Daftar akun yang dimuat
    required String baseUrl,
    required String accessToken,
  }) async {
    if (items.isEmpty) {
      throw Exception('Tidak ada item untuk dikirim');
    }

    // Validasi apakah akun benar-benar ada di Firefly III
    bool sourceAccountExists = false;
    bool destinationAccountExists = false;

    // Cari detail akun untuk validasi tipe akun
    Map<String, dynamic>? sourceAccountDetails;
    Map<String, dynamic>? destinationAccountDetails;

    for (var account in accounts) {
      if (account['id'].toString() == sourceAccountId) {
        sourceAccountExists = true;
        sourceAccountDetails = account;
      }
      if (account['id'].toString() == destinationAccountId) {
        destinationAccountExists = true;
        destinationAccountDetails = account;
      }
    }

    if (!sourceAccountExists) {
      throw Exception(
          'Akun sumber tidak ditemukan di daftar akun yang dimuat. Klik "Muat Ulang Akun" dan coba lagi.');
    }

    if (!destinationAccountExists) {
      throw Exception(
          'Akun tujuan tidak ditemukan di daftar akun yang dimuat. Klik "Muat Ulang Akun" dan coba lagi.');
    }

    // Validasi tipe akun (sumber harus revenue, tujuan harus asset)
    if (sourceAccountDetails != null &&
        sourceAccountDetails['type'] != 'revenue') {
      // Tampilkan peringatan, tapi tidak menghentikan proses
      print(
          'Peringatan: Akun sumber sebaiknya bertipe revenue, tetapi akun ini bertipe ${sourceAccountDetails['type']}.');
    }

    if (destinationAccountDetails != null &&
        destinationAccountDetails['type'] != 'asset') {
      // Tampilkan peringatan, tapi tidak menghentikan proses
      print(
          'Peringatan: Akun tujuan sebaiknya bertipe asset, tetapi akun ini bertipe ${destinationAccountDetails['type']}.');
    }

    if (sourceAccountId == destinationAccountId) {
      throw Exception('Akun sumber dan tujuan tidak boleh sama');
    }

    final total = _calculateTotal(items);

    // Generate transaction description
    final transactionDescription = generateTransactionDescription(items);

    final transactionId = await FireflyApiService.submitDummyTransaction(
      baseUrl: baseUrl,
      accessToken: accessToken,
      sourceId: sourceAccountId,
      destinationId: destinationAccountId,
      type: 'deposit',
      description: transactionDescription,
      date:
          '${transactionDate.year}-${transactionDate.month.toString().padLeft(2, '0')}-${transactionDate.day.toString().padLeft(2, '0')}',
      amount: total.toStringAsFixed(2),
    );

    return transactionId;
  }

  /// Menghitung total harga semua item
  static double _calculateTotal(List<ReceiptItem> items) {
    return items.fold(0.0, (sum, item) => sum + item.total);
  }
}