import 'receipt_item.dart';
import 'receipt_group.dart';

class LocalReceipt {
  final String id;
  final List<ReceiptGroup> groups;
  final String? destinationAccountId;
  final String? destinationAccountName;
  final DateTime transactionDate;
  final String?
      transactionDescription; // Deskripsi transaksi untuk tampilan di daftar
  // ID transaksi tunggal (format lama / fallback). Prefer [fireflyTransactionIds].
  final String? fireflyTransactionId;
  final List<String> fireflyTransactionIds; // ID per grup (format baru)
  final String? fireflyTransactionUrl; // URL utama (format lama)
  final List<String> fireflyTransactionUrls; // URL per grup (format baru)
  final bool isSubmitted;
  final String? submissionError;
  final DateTime? submittedAt;
  final DateTime createdAt;
  final double paymentAmount;
  final String?
      tipSourceAccountId; // Akun sumber untuk transaksi tip (null = bukan tip)
  final String? tipSourceAccountName;

  LocalReceipt({
    required this.id,
    required this.groups,
    this.destinationAccountId,
    this.destinationAccountName,
    required this.transactionDate,
    this.transactionDescription,
    this.fireflyTransactionId,
    this.fireflyTransactionIds = const [],
    this.fireflyTransactionUrl,
    this.fireflyTransactionUrls = const [],
    this.isSubmitted = false,
    this.submissionError,
    this.submittedAt,
    required this.createdAt,
    this.paymentAmount = 0.0,
    this.tipSourceAccountId,
    this.tipSourceAccountName,
  });

  double get total =>
      groups.fold(0.0, (sum, group) => sum + group.total);

  bool get hasTip => tipSourceAccountId != null && paymentAmount > total;

  double get tipAmount => hasTip ? (paymentAmount - total) : 0.0;

  /// Gabungan semua URL transaksi (untuk tampilan daftar link).
  List<String> get allFireflyUrls {
    final urls = <String>[...fireflyTransactionUrls];
    if (fireflyTransactionUrl != null &&
        fireflyTransactionUrl!.isNotEmpty &&
        !urls.contains(fireflyTransactionUrl)) {
      urls.insert(0, fireflyTransactionUrl!);
    }
    return urls;
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'groups': groups.map((group) => group.toJson()).toList(),
      'destinationAccountId': destinationAccountId,
      'destinationAccountName': destinationAccountName,
      'transactionDate': transactionDate.toIso8601String(),
      'transactionDescription': transactionDescription,
      'fireflyTransactionId': fireflyTransactionId,
      'fireflyTransactionIds': fireflyTransactionIds,
      'fireflyTransactionUrl': fireflyTransactionUrl,
      'fireflyTransactionUrls': fireflyTransactionUrls,
      'isSubmitted': isSubmitted,
      'submissionError': submissionError,
      'submittedAt': submittedAt?.toIso8601String(),
      'createdAt': createdAt.toIso8601String(),
      'paymentAmount': paymentAmount,
      'tipSourceAccountId': tipSourceAccountId,
      'tipSourceAccountName': tipSourceAccountName,
    };
  }

  factory LocalReceipt.fromJson(Map<String, dynamic> json) {
    // Migrasi format lama: jika ada key "items" (list tunggal) tapi tidak ada "groups",
    // bungkus menjadi satu grup dengan akun sumber lama.
    List<ReceiptGroup> groups;
    if (json.containsKey('groups') && json['groups'] is List) {
      groups = (json['groups'] as List)
          .map((g) => ReceiptGroup.fromJson(g as Map<String, dynamic>))
          .toList();
    } else {
      // Format lama
      final items = (json['items'] as List? ?? [])
          .map((item) => ReceiptItem.fromJson(item as Map<String, dynamic>))
          .toList();
      groups = [
        ReceiptGroup(
          id: 'legacy_${json['id'] ?? DateTime.now().millisecondsSinceEpoch}',
          items: items,
          sourceAccountId: json['sourceAccountId'] as String?,
          sourceAccountName: json['sourceAccountName'] as String?,
        ),
      ];
    }

    // fireflyTransactionIds (format baru) - fallback ke ID tunggal lama
    final txIds = (json['fireflyTransactionIds'] as List?)
            ?.map((e) => e.toString())
            .toList() ??
        (json['fireflyTransactionId'] != null
            ? [json['fireflyTransactionId'].toString()]
            : <String>[]);

    // fireflyTransactionUrls (format baru) - fallback ke URL tunggal lama
    final txUrls = (json['fireflyTransactionUrls'] as List?)
            ?.map((e) => e.toString())
            .toList() ??
        (json['fireflyTransactionUrl'] != null
            ? [json['fireflyTransactionUrl'].toString()]
            : <String>[]);

    return LocalReceipt(
      id: json['id'],
      groups: groups,
      destinationAccountId: json['destinationAccountId'] as String?,
      destinationAccountName: json['destinationAccountName'] as String?,
      transactionDate: DateTime.parse(json['transactionDate']),
      transactionDescription: json['transactionDescription'],
      fireflyTransactionId: json['fireflyTransactionId'],
      fireflyTransactionIds: txIds,
      fireflyTransactionUrl: json['fireflyTransactionUrl'],
      fireflyTransactionUrls: txUrls,
      isSubmitted: json['isSubmitted'] ?? false,
      submissionError: json['submissionError'],
      submittedAt: json['submittedAt'] != null
          ? DateTime.parse(json['submittedAt'])
          : null,
      createdAt: DateTime.parse(json['createdAt']),
      paymentAmount: json['paymentAmount']?.toDouble() ?? 0.0,
      // Format lama pakai boolean isTip; tidak bisa dipulihkan menjadi akun sumber,
      // jadi tipSourceAccountId tetap null (user dapat set ulang sebelum kirim).
      tipSourceAccountId: json['tipSourceAccountId'] as String?,
      tipSourceAccountName: json['tipSourceAccountName'] as String?,
    );
  }

  LocalReceipt copyWith({
    String? id,
    List<ReceiptGroup>? groups,
    String? destinationAccountId,
    String? destinationAccountName,
    DateTime? transactionDate,
    String? transactionDescription,
    String? fireflyTransactionId,
    List<String>? fireflyTransactionIds,
    String? fireflyTransactionUrl,
    List<String>? fireflyTransactionUrls,
    bool? isSubmitted,
    String? submissionError,
    DateTime? submittedAt,
    DateTime? createdAt,
    double? paymentAmount,
    String? tipSourceAccountId,
    String? tipSourceAccountName,
  }) {
    return LocalReceipt(
      id: id ?? this.id,
      groups: groups ?? this.groups,
      destinationAccountId: destinationAccountId ?? this.destinationAccountId,
      destinationAccountName:
          destinationAccountName ?? this.destinationAccountName,
      transactionDate: transactionDate ?? this.transactionDate,
      transactionDescription:
          transactionDescription ?? this.transactionDescription,
      fireflyTransactionId: fireflyTransactionId ?? this.fireflyTransactionId,
      fireflyTransactionIds:
          fireflyTransactionIds ?? this.fireflyTransactionIds,
      fireflyTransactionUrl: fireflyTransactionUrl ?? this.fireflyTransactionUrl,
      fireflyTransactionUrls:
          fireflyTransactionUrls ?? this.fireflyTransactionUrls,
      isSubmitted: isSubmitted ?? this.isSubmitted,
      submissionError: submissionError ?? this.submissionError,
      submittedAt: submittedAt ?? this.submittedAt,
      createdAt: createdAt ?? this.createdAt,
      paymentAmount: paymentAmount ?? this.paymentAmount,
      tipSourceAccountId: tipSourceAccountId ?? this.tipSourceAccountId,
      tipSourceAccountName: tipSourceAccountName ?? this.tipSourceAccountName,
    );
  }
}
