/** Backend allows executeAt down to now - 2 minutes. */
export const SCHEDULE_EXECUTE_AT_GRACE_MS = 2 * 60 * 1000;

/** Default offset when rescheduling a past executeAt. */
export const RESCHEDULE_DEFAULT_OFFSET_MS = 5 * 60 * 1000;

export function parseExecuteAtIso(iso: string): Date | null {
  const raw = iso.trim();
  if (!raw) return null;
  const normalized = raw.includes("T") ? raw : raw.replace(" ", "T");
  const d = new Date(normalized);
  return Number.isFinite(d.getTime()) ? d : null;
}

export function formatExecuteAtIso(date: Date): string {
  const y = date.getFullYear();
  const mo = String(date.getMonth() + 1).padStart(2, "0");
  const d = String(date.getDate()).padStart(2, "0");
  const h = String(date.getHours()).padStart(2, "0");
  const mi = String(date.getMinutes()).padStart(2, "0");
  const s = String(date.getSeconds()).padStart(2, "0");
  return `${y}-${mo}-${d}T${h}:${mi}:${s}`;
}

/** Display API timestamps as `yyyy-MM-dd HH:mm:ss` (no `T`). */
export function formatScheduleDisplayDateTime(iso: string): string {
  const raw = iso.trim();
  if (!raw) return raw;
  const tIdx = raw.indexOf("T");
  if (tIdx < 0) return raw;
  const time = raw
    .slice(tIdx + 1)
    .replace(/\.\d+.*$/, "")
    .replace(/Z$/i, "")
    .replace(/[+-]\d{2}:\d{2}$/, "");
  return `${raw.slice(0, tIdx)} ${time}`;
}

export function isExecuteAtTooEarly(
  executeAtIso: string,
  now: Date = new Date(),
): boolean {
  const parsed = parseExecuteAtIso(executeAtIso);
  if (!parsed) return true;
  const min = new Date(now.getTime() - SCHEDULE_EXECUTE_AT_GRACE_MS);
  return parsed.getTime() < min.getTime();
}

export function buildExecuteAtIso(
  date: string,
  time: string,
): string | null {
  const d = date.trim();
  const t = time.trim();
  if (!d || !t) return null;
  return `${d}T${t.length === 5 ? `${t}:00` : t}`;
}

export type RescheduleExecuteAtResult = {
  executeAt: string;
  adjusted: boolean;
};

/**
 * Keeps original executeAt if still valid; otherwise shifts to now + offset.
 */
export function resolveRescheduleExecuteAt(
  originalIso: string,
  now: Date = new Date(),
  offsetMs: number = RESCHEDULE_DEFAULT_OFFSET_MS,
): RescheduleExecuteAtResult {
  if (!isExecuteAtTooEarly(originalIso, now)) {
    return { executeAt: originalIso.trim(), adjusted: false };
  }
  const next = new Date(now.getTime() + offsetMs);
  return { executeAt: formatExecuteAtIso(next), adjusted: true };
}

export function defaultRetryExecuteAt(now: Date = new Date()): string {
  return formatExecuteAtIso(new Date(now.getTime() + 60 * 1000));
}
