import 'package:json_annotation/json_annotation.dart';
import 'package:decimal/decimal.dart';

part 'transaction_model.g.dart';

/// JsonConverter for [Decimal] values — reads from [num] (int or double)
/// in JSON and writes back as [num].
class DecimalJsonConverter implements JsonConverter<Decimal, num> {
  const DecimalJsonConverter();

  @override
  Decimal fromJson(num json) => Decimal.parse(json.toString());

  @override
  num toJson(Decimal object) => object.toDouble();
}

/// JsonConverter for [DateTime] values — reads from ISO‑8601 [String]
/// and writes back as ISO‑8601 [String].
class DateTimeJsonConverter implements JsonConverter<DateTime, String> {
  const DateTimeJsonConverter();

  @override
  DateTime fromJson(String json) => DateTime.parse(json);

  @override
  String toJson(DateTime object) => object.toIso8601String();
}

/// JsonConverter for a list of key-value entries (additionalData).
class AdditionalDataJsonConverter
    implements JsonConverter<List<Map<String, dynamic>>?, List<dynamic>?> {
  const AdditionalDataJsonConverter();

  @override
  List<Map<String, dynamic>>? fromJson(List<dynamic>? json) {
    return json?.map((e) => Map<String, dynamic>.from(e as Map)).toList();
  }

  @override
  List<dynamic>? toJson(List<Map<String, dynamic>>? object) {
    return object?.map((e) => e as dynamic).toList();
  }
}

@DecimalJsonConverter()
@DateTimeJsonConverter()
@AdditionalDataJsonConverter()
@JsonSerializable(explicitToJson: true)
class TransactionModel {
  final String? id;
  final DateTime? createdAt;
  final String userId;
  final String workspaceId;
  final String? batchId;
  final String trace;
  final Decimal amount;
  final Decimal charge;
  final Decimal gatewayCharge;
  final Decimal tax;
  final Decimal totalAmount;
  final String reference;
  final String paymentProcessorLabel;
  final String? integrationProcessorLabel;
  final String? confirmationProcessorLabel;
  final String? providerLabel;
  final String debitPhone;
  final String debitCurrency;
  final String? debitRef;
  final String? creditPhone;
  final String? creditAccount;
  final String? creditRef;
  final String? billClientId;
  final String? billName;
  final String paymentProcessorName;
  final String? providerImage;
  final String? paymentProcessorImage;
  final String confirmationStatus;
  final String? paymentStatus;
  final String? integrationStatus;
  final String? pollingStatus;
  final String? orderId;
  final String? orderTrace;
  final String? orderTransactionTrace;
  final String? erpSalesRef;
  final String? erpSalesPaymentRef;
  final int workflowId;
  final String? type;
  final String? authType;
  final String? responseCode;
  final String? status;
  final String? errorMessage;
  final String? billProductName;
  final String? creditName;
  final String? creditEmail;
  final String? productUid;
  final String? targetUrl;
  final List<Map<String, dynamic>>? additionalData;

  const TransactionModel({
    this.id,
    this.createdAt,
    required this.userId,
    required this.workspaceId,
    this.batchId,
    required this.trace,
    required this.amount,
    required this.charge,
    required this.gatewayCharge,
    required this.tax,
    required this.totalAmount,
    required this.reference,
    required this.paymentProcessorLabel,
    this.integrationProcessorLabel,
    this.confirmationProcessorLabel,
    this.providerLabel,
    required this.debitPhone,
    required this.debitCurrency,
    this.debitRef,
    this.creditPhone,
    this.creditAccount,
    this.creditRef,
    this.billClientId,
    this.billName,
    required this.paymentProcessorName,
    this.providerImage,
    this.paymentProcessorImage,
    required this.confirmationStatus,
    this.paymentStatus,
    this.integrationStatus,
    this.pollingStatus,
    this.orderId,
    this.orderTrace,
    this.orderTransactionTrace,
    this.erpSalesRef,
    this.erpSalesPaymentRef,
    required this.workflowId,
    this.type,
    this.authType,
    this.responseCode,
    this.status,
    this.errorMessage,
    this.billProductName,
    this.creditName,
    this.creditEmail,
    this.productUid,
    this.targetUrl,
    this.additionalData,
  });

  factory TransactionModel.fromJson(Map<String, dynamic> json) =>
      _$TransactionModelFromJson(json);

  Map<String, dynamic> toJson() => _$TransactionModelToJson(this);
}
