// ─────────────────────────────────────────────────────────────────────────────
// iCalendar (.ics) file generation
//
// Builds RFC 5545-compliant iCalendar strings for calendar events, including a
// 15-minute DISPLAY alarm.  Used to generate downloadable .ics attachments for
// event confirmations.
// ─────────────────────────────────────────────────────────────────────────────

/**
 * Shape of the event data required to build an .ics file.
 */
export interface IcsEvent {
  uid: string           // Globally unique ID for the event (e.g. a DB UUID)
  title: string
  description?: string
  location?: string
  startTime: Date
  endTime?: Date
  durationMinutes?: number
  organizerName?: string
  organizerEmail?: string
  attendeeName?: string
  attendeeEmail?: string
}

// ── Formatting helpers ───────────────────────────────────────────────────────

/**
 * Format a `Date` as an iCalendar UTC string: `YYYYMMDDTHHMMSSZ`.
 *
 * Strips hyphens and colons from the ISO string and appends the trailing `Z`
 * (UTC marker).
 */
function formatIcsDate(d: Date): string {
  return d.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z"
}

/**
 * Escape special characters per RFC 5545 text property rules.
 *
 * Backslash → `\\`, semicolon → `\;`, comma → `\,`, newline → `\n`.
 */
function escapeIcsText(text: string): string {
  return text
    .replace(/\\/g, "\\\\")
    .replace(/;/g, "\\;")
    .replace(/,/g, "\\,")
    .replace(/\n/g, "\\n")
}

// ── ICS builder ──────────────────────────────────────────────────────────────

/**
 * Construct a complete .ics file content string.
 *
 * End-time resolution order:
 *   1. Explicit `event.endTime`
 *   2. `event.startTime + event.durationMinutes`
 *   3. Fallback to 1 hour after start
 *
 * Every event includes a `VALARM` with a 15-minute-before DISPLAY reminder.
 *
 * @param event - Event details (see `IcsEvent`).
 * @returns     A UTF-8 iCalendar string, ready to be written to a file or sent
 *              as an attachment.
 */
export function buildIcs(event: IcsEvent): string {
  const now = formatIcsDate(new Date())
  const dtStart = formatIcsDate(event.startTime)

  // Compute DTEND (one of three strategies)
  let dtEnd: string
  if (event.endTime) {
    dtEnd = formatIcsDate(event.endTime)
  } else if (event.durationMinutes) {
    const end = new Date(event.startTime.getTime() + event.durationMinutes * 60000)
    dtEnd = formatIcsDate(end)
  } else {
    // Default: 1-hour meeting
    const end = new Date(event.startTime.getTime() + 60 * 60000)
    dtEnd = formatIcsDate(end)
  }

  const lines: string[] = [
    "BEGIN:VCALENDAR",
    "VERSION:2.0",
    "PRODID:-//CRM//Calendar//EN",
    "CALSCALE:GREGORIAN",
    "METHOD:PUBLISH",
    "BEGIN:VEVENT",
    `UID:${event.uid}`,
    `DTSTAMP:${now}`,
    `DTSTART:${dtStart}`,
    `DTEND:${dtEnd}`,
    `SUMMARY:${escapeIcsText(event.title)}`,
  ]

  if (event.description) {
    lines.push(`DESCRIPTION:${escapeIcsText(event.description)}`)
  }

  if (event.organizerEmail) {
    const cn = event.organizerName ? `;CN=${escapeIcsText(event.organizerName)}` : ""
    lines.push(`ORGANIZER${cn}:mailto:${event.organizerEmail}`)
  }

  if (event.attendeeEmail) {
    const cn = event.attendeeName ? `;CN=${escapeIcsText(event.attendeeName)}` : ""
    lines.push(`ATTENDEE${cn};ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION:mailto:${event.attendeeEmail}`)
  }

  lines.push("STATUS:CONFIRMED")

  // 15-minute-before reminder
  lines.push("BEGIN:VALARM")
  lines.push("TRIGGER:-PT15M")
  lines.push("ACTION:DISPLAY")
  lines.push(`DESCRIPTION:Reminder: ${escapeIcsText(event.title)}`)
  lines.push("END:VALARM")

  lines.push("END:VEVENT")
  lines.push("END:VCALENDAR")

  return lines.join("\r\n")
}
