/**
 * Milliseconds from `now` until the next occurrence of local time hour:minute.
 * If the target is now or already passed today, rolls to tomorrow.
 */
export function msUntilNextRun(now: Date, hour: number, minute: number): number {
  const target = new Date(now);
  target.setHours(hour, minute, 0, 0);
  if (target.getTime() <= now.getTime()) {
    target.setDate(target.getDate() + 1);
  }
  return target.getTime() - now.getTime();
}

function localDate(d: Date): string {
  const p = (n: number) => String(n).padStart(2, '0');
  return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`;
}

/**
 * Decide whether a daily collection should run right now, given the last date
 * (local `YYYY-MM-DD`) it ran. Drives both catch-up-on-launch and the
 * sleep-resilient periodic check:
 * - already collected today → no
 * - never collected → yes (seed a baseline)
 * - a full prior day was missed → yes immediately (minimize the gap)
 * - collected yesterday → only once today's scheduled hour has arrived
 */
export function shouldCollectNow(now: Date, hour: number, lastDate: string | null): boolean {
  const today = localDate(now);
  if (lastDate === today) return false;
  if (lastDate === null) return true;
  const yesterday = new Date(now);
  yesterday.setDate(yesterday.getDate() - 1);
  if (lastDate < localDate(yesterday)) return true;
  return now.getHours() >= hour;
}

/**
 * First-open-of-the-day trigger: when the user actually opens the app window,
 * collect today's point immediately if it hasn't run yet — ignore the scheduled
 * hour. (The periodic background tick keeps using shouldCollectNow, so an app that
 * only sits minimized in the tray still collects at the set time, not on every tick.)
 */
export function shouldCollectOnOpen(now: Date, lastDate: string | null): boolean {
  return lastDate !== localDate(now);
}
