import 'package:meta/meta.dart';

enum PaymentMethod {
  bankTransfer,
  cash,
  creditCard,
  cheque,
  other,
}

extension PaymentMethodX on PaymentMethod {
  String get displayName {
    switch (this) {
      case PaymentMethod.bankTransfer:
        return '銀行振込';
      case PaymentMethod.cash:
        return '現金';
      case PaymentMethod.creditCard:
        return 'クレジット';
      case PaymentMethod.cheque:
        return '小切手';
      case PaymentMethod.other:
        return 'その他';
    }
  }
}

@immutable
class ReceivableInvoiceSummary {
  const ReceivableInvoiceSummary({
    required this.invoiceId,
    required this.invoiceNumber,
    required this.customerName,
    required this.invoiceDate,
    required this.totalAmount,
    required this.paidAmount,
    required this.dueDate,
  });

  final String invoiceId;
  final String invoiceNumber;
  final String customerName;
  final DateTime invoiceDate;
  final DateTime dueDate;
  final int totalAmount;
  final int paidAmount;

  int get outstandingAmount => totalAmount - paidAmount;
  bool get isSettled => outstandingAmount <= 0;
  bool get isOverdue => !isSettled && DateTime.now().isAfter(dueDate);
  double get collectionProgress => totalAmount == 0 ? 1.0 : paidAmount.clamp(0, totalAmount) / totalAmount;
}

@immutable
class ReceivablePayment {
  const ReceivablePayment({
    required this.id,
    required this.invoiceId,
    required this.amount,
    required this.paymentDate,
    required this.method,
    required this.createdAt,
    this.notes,
  });

  final String id;
  final String invoiceId;
  final int amount;
  final DateTime paymentDate;
  final PaymentMethod method;
  final String? notes;
  final DateTime createdAt;

  Map<String, dynamic> toMap() => {
        'id': id,
        'invoice_id': invoiceId,
        'amount': amount,
        'payment_date': paymentDate.toIso8601String(),
        'method': method.name,
        'notes': notes,
        'created_at': createdAt.toIso8601String(),
      };

  factory ReceivablePayment.fromMap(Map<String, dynamic> map) {
    PaymentMethod parseMethod(String? value) {
      return PaymentMethod.values.firstWhere(
        (method) => method.name == value,
        orElse: () => PaymentMethod.other,
      );
    }

    return ReceivablePayment(
      id: map['id'] as String,
      invoiceId: map['invoice_id'] as String,
      amount: map['amount'] as int? ?? 0,
      paymentDate: DateTime.parse(map['payment_date'] as String),
      method: parseMethod(map['method'] as String?),
      notes: map['notes'] as String?,
      createdAt: DateTime.parse(map['created_at'] as String),
    );
  }
}
