/// Parsed parts of a Talk push subject text.
///
/// Format verified against nextcloud/spreed `Notifier::parseChatMessage`:
/// with message preview the parsed subject is `"{user}\n{message}"` for 1:1
/// chats and `'{user} in {call}' . "\n{message}"` for groups — header and
/// message are separated by a NEWLINE, and the notifications app forwards the
/// parsed subject unmodified (only shortened). The German translation of
/// `{user} in {call}` is identical (`l10n/de.json`), so the ` in ` separator
/// holds for de_DE. Legacy/other variants using `": "` are kept as fallback;
/// splitting the header at the LAST ` in ` is robust against sender names
/// containing "in" (only a display name literally containing ` in ` in a 1:1
/// chat would still mis-split — accepted heuristic limit).
({String sender, String? roomName, String text}) parseTalkSubject(String raw) {
  String header;
  String text;
  final newline = raw.indexOf('\n');
  if (newline > 0) {
    header = raw.substring(0, newline).trim();
    text = raw.substring(newline + 1);
  } else {
    final colon = raw.indexOf(': ');
    if (colon > 0 && colon < raw.length - 2) {
      header = raw.substring(0, colon);
      text = raw.substring(colon + 2);
    } else {
      return (sender: 'Talk', roomName: null, text: raw);
    }
  }
  final roomSep = header.lastIndexOf(' in ');
  if (roomSep > 0 && roomSep + 4 < header.length) {
    return (
      sender: header.substring(0, roomSep),
      roomName: header.substring(roomSep + 4),
      text: text,
    );
  }
  return (sender: header, roomName: null, text: text);
}

/// The decrypted `subject` JSON of a Nextcloud push-v2 notification.
///
/// Covers the full shape the notifications app emits, including the three
/// delete variants which the neon `DecryptedSubject` helper only partially
/// models (it lacks `delete-multiple`/`nids`).
class PushSubject {
  /// Nextcloud notification id.
  final int? nid;

  /// App that raised the notification (e.g. `spreed` for Talk).
  final String? app;

  /// Human-readable subject line.
  final String? subject;

  /// Notification type (e.g. `chat`, `background`).
  final String? type;

  /// App-specific object id. For Talk this is the chat/room token.
  final String? id;

  final bool delete;
  final bool deleteMultiple;
  final bool deleteAll;

  /// Notification ids to remove for a `delete-multiple` push.
  final List<int> nids;

  const PushSubject({
    this.nid,
    this.app,
    this.subject,
    this.type,
    this.id,
    this.delete = false,
    this.deleteMultiple = false,
    this.deleteAll = false,
    this.nids = const [],
  });

  bool get isAnyDelete => delete || deleteMultiple || deleteAll;

  /// True when this notification originates from Nextcloud Talk.
  bool get isTalk => app == 'spreed';

  factory PushSubject.fromJson(Map<String, dynamic> json) {
    final rawNids = json['nids'];
    return PushSubject(
      nid: (json['nid'] as num?)?.toInt(),
      app: json['app'] as String?,
      subject: json['subject'] as String?,
      type: json['type'] as String?,
      id: json['id'] as String?,
      delete: json['delete'] == true,
      deleteMultiple: json['delete-multiple'] == true,
      deleteAll: json['delete-all'] == true,
      nids: rawNids is List
          ? rawNids
                .whereType<Object>()
                .map((e) => e is num ? e.toInt() : int.tryParse('$e'))
                .whereType<int>()
                .toList()
          : const [],
    );
  }
}
