const KST_OFFSET_MS = 9 * 60 * 60 * 1000;

export const BILLING_GRACE_RETRY_DAYS = 3;
export const BILLING_GRACE_RETRY_HOURS_KST = [9, 12, 15] as const;
export const BILLING_GRACE_RETRY_LIMIT =
  BILLING_GRACE_RETRY_DAYS * BILLING_GRACE_RETRY_HOURS_KST.length;

function toKstDate(year: number, month: number, day: number, hour: number) {
  return new Date(Date.UTC(year, month, day, hour) - KST_OFFSET_MS);
}

function getKstCalendarParts(value: Date) {
  const shifted = new Date(value.getTime() + KST_OFFSET_MS);

  return {
    day: shifted.getUTCDate(),
    month: shifted.getUTCMonth(),
    year: shifted.getUTCFullYear(),
  };
}

export function createBillingGraceRetrySlots(failedAt: Date) {
  const { day, month, year } = getKstCalendarParts(failedAt);
  const firstRetryDay = new Date(Date.UTC(year, month, day + 1));
  const slots: Date[] = [];

  for (let dayOffset = 0; dayOffset < BILLING_GRACE_RETRY_DAYS; dayOffset += 1) {
    for (const hour of BILLING_GRACE_RETRY_HOURS_KST) {
      slots.push(
        toKstDate(
          firstRetryDay.getUTCFullYear(),
          firstRetryDay.getUTCMonth(),
          firstRetryDay.getUTCDate() + dayOffset,
          hour,
        ),
      );
    }
  }

  return slots;
}

export function getBillingGraceRetrySlot(failedAt: Date, retryIndex: number) {
  return createBillingGraceRetrySlots(failedAt)[retryIndex] ?? null;
}

export function isLastBillingRetryOfKstDay(value: Date | null | undefined) {
  if (!value) return false;

  const shifted = new Date(value.getTime() + KST_OFFSET_MS);
  return shifted.getUTCHours() === BILLING_GRACE_RETRY_HOURS_KST.at(-1);
}

export function formatKstDate(value: Date) {
  const shifted = new Date(value.getTime() + KST_OFFSET_MS);
  const year = shifted.getUTCFullYear();
  const month = String(shifted.getUTCMonth() + 1).padStart(2, "0");
  const day = String(shifted.getUTCDate()).padStart(2, "0");

  return `${year}-${month}-${day}`;
}

export function formatKstDateTime(value: Date) {
  const shifted = new Date(value.getTime() + KST_OFFSET_MS);
  const date = formatKstDate(value).replaceAll("-", ". ");
  const hour = String(shifted.getUTCHours()).padStart(2, "0");
  const minute = String(shifted.getUTCMinutes()).padStart(2, "0");

  return `${date}. ${hour}:${minute}`;
}
