// Minimal hand-rolled iCalendar (RFC 5545) writer — the meal plan only needs
// a handful of all-day-ish VEVENTs, not enough to justify a dependency.

export type IcsEvent = {
  uid: string;
  title: string;
  description?: string;
  start: Date;
  durationMinutes: number;
};

function foldLine(line: string): string {
  // RFC 5545 §3.1: lines over 75 octets should be folded with a leading space
  // on the continuation — not strictly required for readers to work, but
  // keeps long recipe titles/descriptions spec-compliant.
  if (line.length <= 75) return line;
  const chunks: string[] = [];
  let rest = line;
  while (rest.length > 75) {
    chunks.push(rest.slice(0, 75));
    rest = " " + rest.slice(75);
  }
  chunks.push(rest);
  return chunks.join("\r\n");
}

function escapeText(text: string): string {
  return text.replace(/\\/g, "\\\\").replace(/;/g, "\\;").replace(/,/g, "\\,").replace(/\n/g, "\\n");
}

// Floating local time (no trailing "Z", no UTC conversion) — meal times have
// no stored timezone, so this is authored as "7pm wherever you're looking at
// this calendar" rather than pinned to one instant, per RFC 5545 §3.3.5.
function formatDateTime(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}T${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
}

function formatUtcStamp(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, "0");
  return `${d.getUTCFullYear()}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}T${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}Z`;
}

export function buildIcs(calendarName: string, events: IcsEvent[]): string {
  const now = formatUtcStamp(new Date());
  const lines: string[] = [
    "BEGIN:VCALENDAR",
    "VERSION:2.0",
    "PRODID:-//Epicure//Meal Plan//EN",
    "CALSCALE:GREGORIAN",
    foldLine(`X-WR-CALNAME:${escapeText(calendarName)}`),
  ];

  for (const event of events) {
    const end = new Date(event.start.getTime() + event.durationMinutes * 60_000);
    lines.push(
      "BEGIN:VEVENT",
      `UID:${event.uid}`,
      `DTSTAMP:${now}`,
      `DTSTART:${formatDateTime(event.start)}`,
      `DTEND:${formatDateTime(end)}`,
      foldLine(`SUMMARY:${escapeText(event.title)}`)
    );
    if (event.description) lines.push(foldLine(`DESCRIPTION:${escapeText(event.description)}`));
    lines.push("END:VEVENT");
  }

  lines.push("END:VCALENDAR");
  return lines.join("\r\n") + "\r\n";
}
