import { parse } from "date-fns";
import { zonedTimeToUtc } from "date-fns-tz";

import { Term, TERMS } from "./types";

export const DATE_FORMAT = "MMMM dd yyyy HH:mm";
const TIME_ZONE = "America/Toronto";

const MONTH_NAMES = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December",
];
const STRICT_FORMAT = new RegExp(
  `^(${MONTH_NAMES.join("|")}) (\\d{2}) (\\d{4}) (\\d{2}):(\\d{2})$`
);

// Mirrors www-new's utils.ts: TERMS[Math.trunc(month / 4)], month is 0-indexed.
export function termForMonth(monthIndex: number): Term {
  return TERMS[Math.trunc(monthIndex / 4)];
}

export interface ParsedDate {
  utcDate: Date;
  year: number;
  monthIndex: number;
}

// Parses a "MMMM dd yyyy HH:mm" string as America/Toronto local time.
// Returns null if the string doesn't match the format exactly.
export function parseTorontoDate(value: string): ParsedDate | null {
  if (!STRICT_FORMAT.test(value)) {
    return null;
  }

  const naive = parse(value, DATE_FORMAT, new Date());
  if (isNaN(naive.getTime())) {
    return null;
  }

  return {
    utcDate: zonedTimeToUtc(naive, TIME_ZONE),
    year: naive.getFullYear(),
    monthIndex: naive.getMonth(),
  };
}
