/// Domain Entity: Payment Reminder
///
/// Represents a payment reminder for an unpaid invoice.
library;

/// Reminder type enum
enum ReminderType {
  /// Initial reminder before due date
  initial,

  /// Reminder on due date
  dueDate,

  /// First reminder after due date
  firstOverdue,

  /// Second reminder after due date
  secondOverdue,

  /// Final warning
  finalWarning;

  /// Get display name for reminder type
  String get displayName {
    switch (this) {
      case ReminderType.initial:
        return 'Initial Reminder';
      case ReminderType.dueDate:
        return 'Due Date Reminder';
      case ReminderType.firstOverdue:
        return 'First Overdue';
      case ReminderType.secondOverdue:
        return 'Second Overdue';
      case ReminderType.finalWarning:
        return 'Final Warning';
    }
  }
}

/// Payment Reminder Entity
///
/// Contains information about a payment reminder:
/// - Invoice reference
/// - Reminder content
/// - Delivery status
/// - Scheduling
class PaymentReminder {
  /// Unique reminder identifier
  final String reminderId;

  /// Invoice ID this reminder is for
  final String invoiceId;

  /// User ID receiving the reminder
  final String userId;

  /// Reminder type
  final ReminderType reminderType;

  /// Reminder subject
  final String subject;

  /// Reminder message
  final String message;

  /// Reminder has been read
  final bool isRead;

  /// Reminder has been sent
  final bool isSent;

  /// Scheduled send timestamp
  final DateTime? scheduledAt;

  /// Actual send timestamp
  final DateTime? sentAt;

  /// Read timestamp
  final DateTime? readAt;

  const PaymentReminder({
    required this.reminderId,
    required this.invoiceId,
    required this.userId,
    required this.reminderType,
    required this.subject,
    required this.message,
    required this.isRead,
    required this.isSent,
    this.scheduledAt,
    this.sentAt,
    this.readAt,
  });

  /// Check if reminder is pending (scheduled but not sent)
  bool get isPending => !isSent && scheduledAt != null;

  /// Check if reminder is overdue to be sent
  bool get isOverdueToSend {
    if (isSent || scheduledAt == null) return false;
    return DateTime.now().isAfter(scheduledAt!);
  }

  /// Check if reminder is unread
  bool get isUnread => !isRead;

  /// Get time until scheduled send
  Duration? get timeUntilSend {
    if (scheduledAt == null || isSent) return null;
    final duration = scheduledAt!.difference(DateTime.now());
    return duration.isNegative ? null : duration;
  }

  /// Get time since sent
  Duration? get timeSinceSent {
    if (sentAt == null) return null;
    return DateTime.now().difference(sentAt!);
  }

  /// Copy with method for immutability
  PaymentReminder copyWith({
    String? reminderId,
    String? invoiceId,
    String? userId,
    ReminderType? reminderType,
    String? subject,
    String? message,
    bool? isRead,
    bool? isSent,
    DateTime? scheduledAt,
    DateTime? sentAt,
    DateTime? readAt,
  }) {
    return PaymentReminder(
      reminderId: reminderId ?? this.reminderId,
      invoiceId: invoiceId ?? this.invoiceId,
      userId: userId ?? this.userId,
      reminderType: reminderType ?? this.reminderType,
      subject: subject ?? this.subject,
      message: message ?? this.message,
      isRead: isRead ?? this.isRead,
      isSent: isSent ?? this.isSent,
      scheduledAt: scheduledAt ?? this.scheduledAt,
      sentAt: sentAt ?? this.sentAt,
      readAt: readAt ?? this.readAt,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;

    return other is PaymentReminder &&
        other.reminderId == reminderId &&
        other.invoiceId == invoiceId &&
        other.userId == userId &&
        other.reminderType == reminderType &&
        other.isRead == isRead &&
        other.isSent == isSent;
  }

  @override
  int get hashCode {
    return Object.hash(
      reminderId,
      invoiceId,
      userId,
      reminderType,
      isRead,
      isSent,
    );
  }

  @override
  String toString() {
    return 'PaymentReminder(reminderId: $reminderId, invoiceId: $invoiceId, '
        'reminderType: $reminderType, isSent: $isSent, isRead: $isRead)';
  }
}
