import { SENT_STALE_MS, type VoiceRecord } from './record'; export interface Located { path: string; record: VoiceRecord; } const time = (iso?: string) => (iso ? Date.parse(iso) : NaN); // Отсутствующее или испорченное время — не повод зависнуть навсегда. export function isStaleSent(r: VoiceRecord, now: Date): boolean { if (r.status !== 'sent') return false; const t = time(r.sentAt); return Number.isNaN(t) || now.getTime() - t > SENT_STALE_MS; } export function due(items: readonly Located[], now: Date, deviceId: string): Located[] { return items .filter(({ record: r }) => { if (r.device !== deviceId) return false; if (r.status === 'saved') return true; if (r.status !== 'retry') return false; const t = time(r.nextAttempt); return Number.isNaN(t) || t <= now.getTime(); }) .sort((a, b) => (a.record.id < b.record.id ? -1 : a.record.id > b.record.id ? 1 : 0)); } export function staleOwn(items: readonly Located[], now: Date, deviceId: string): Located[] { return items.filter(({ record: r }) => r.device === deviceId && isStaleSent(r, now)); } export function claimable(items: readonly Located[], now: Date, deviceId: string): Located[] { return items.filter( ({ record: r }) => r.device !== deviceId && (r.status === 'saved' || r.status === 'retry' || isStaleSent(r, now)), ); }