// Turns the raw fields from the submission form into the shape backend/'s
// POST /api/events/publish expects (see backend/src/validateRequest.ts).
// backend/ remains the single source of truth for validation -- these are
// just the conversions that have to happen before a request can be sent.

const MONTH_NAMES = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December",
];
const TERMS = ["winter", "spring", "fall"] as const;
type Term = (typeof TERMS)[number];

const DATETIME_LOCAL_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/;

interface LocalDateTime {
  year: number;
  monthIndex: number; // 0-11
  day: number;
  hour: number;
  minute: number;
}

// Parses a <input type="datetime-local"> value ("YYYY-MM-DDTHH:mm...") by
// reading its digits directly -- deliberately never through `new Date()`.
// This runs on the server now, not in the submitter's browser, so a Date
// object would be interpreted in *this server's* timezone, not the
// submitter's. These values are naive local time in America/Toronto (the
// club's only real use case, same assumption backend/'s parseTorontoDate
// makes later), and parsing them as plain digits keeps it that way
// regardless of what timezone the server process happens to run in.
function parseLocalDateTime(datetimeLocalValue: string): LocalDateTime | null {
  const match = DATETIME_LOCAL_PATTERN.exec(datetimeLocalValue);
  if (!match) return null;
  const [, year, month, day, hour, minute] = match;
  return {
    year: Number(year),
    monthIndex: Number(month) - 1,
    day: Number(day),
    hour: Number(hour),
    minute: Number(minute),
  };
}

function pad2(n: number): string {
  return n.toString().padStart(2, "0");
}

// Produces backend/'s expected "MMMM dd yyyy HH:mm" format. Returns null if
// the input isn't a well-formed datetime-local value.
export function formatEventDate(datetimeLocalValue: string): string | null {
  const parsed = parseLocalDateTime(datetimeLocalValue);
  if (!parsed || !MONTH_NAMES[parsed.monthIndex]) return null;
  return `${MONTH_NAMES[parsed.monthIndex]} ${pad2(parsed.day)} ${parsed.year} ${pad2(parsed.hour)}:${pad2(parsed.minute)}`;
}

export function deriveYearAndTerm(datetimeLocalValue: string): { year: number; term: Term } | null {
  const parsed = parseLocalDateTime(datetimeLocalValue);
  if (!parsed) return null;
  return { year: parsed.year, term: TERMS[Math.trunc(parsed.monthIndex / 4)] };
}

// Matches backend/'s SLUG_PATTERN (^[A-Za-z0-9][A-Za-z0-9-]*$) exactly --
// must start with a letter or digit, so a leading hyphen left over from
// stripping (e.g. an event named "-Kickoff") is trimmed off afterward.
export function slugify(name: string): string {
  const slug = name
    .trim()
    .replace(/[^A-Za-z0-9\s-]/g, "")
    .replace(/\s+/g, "-")
    .replace(/^-+/, "");
  return slug.length > 0 ? slug : "event";
}

export function generateRequestId(slug: string): string {
  return `event-${slug}-${Date.now()}`.toLowerCase();
}
