import { MatrixClient, MatrixEvent, ReceiptType, Thread } from 'matrix-js-sdk';

// Walks a timeline backwards and returns the latest event that is
// fully sent to the homeserver (not local-echo / pending). Shared by
// the main-room and thread receipt senders so the «which event is
// the read marker pointed at» semantic stays consistent.
//
// Note: deliberately does NOT skip on `evt.getId() === readEventId`.
// SDK's `addLocalEchoReceipt` updates the local read-up-to marker
// synchronously on every `sendReadReceipt` call (read-receipt.js:329-332),
// so a readEventId-match short-circuit would bail on the second
// invocation even when the server failed to process the first one
// (network failure, 5xx, MSC3773-less server) — leaving the unread
// counters stuck. The server is idempotent on duplicate receipts, so
// re-sending costs at most one round-trip; callers gate on
// `document.hasFocus()` to avoid spam from backgrounded tabs.
const pickLatestNonPending = (events: MatrixEvent[]): MatrixEvent | null => {
  for (let i = events.length - 1; i >= 0; i -= 1) {
    const evt = events[i];
    if (evt && !evt.isSending()) {
      return evt;
    }
  }
  return null;
};

const receiptType = (privateReceipt: boolean): ReceiptType =>
  privateReceipt ? ReceiptType.ReadPrivate : ReceiptType.Read;

export async function markAsRead(mx: MatrixClient, roomId: string, privateReceipt: boolean) {
  const room = mx.getRoom(roomId);
  if (!room) return;
  const latestEvent = pickLatestNonPending(room.getLiveTimeline().getEvents());
  if (!latestEvent) return;
  await mx.sendReadReceipt(latestEvent, receiptType(privateReceipt));
}

// Thread-scoped variant. SDK auto-attaches `thread_id: <rootId>` via
// `threadIdForReceipt(event)` (matrix-js-sdk client.js:2655).
export async function markAsThreadRead(
  mx: MatrixClient,
  thread: Thread,
  privateReceipt: boolean
) {
  if (!mx.getUserId()) return;
  const latestEvent = pickLatestNonPending(thread.liveTimeline.getEvents());
  if (!latestEvent) return;
  await mx.sendReadReceipt(latestEvent, receiptType(privateReceipt));
}
