/**
 * iCal/ICS generation utility for calendar export
 * Follows RFC 5545 iCalendar specification
 */

export interface ICalEvent {
  id: number;
  title: string;
  description: string | null;
  due_date: string;
  scheduled_date: string | null;
  status: 'planned' | 'in_progress' | 'completed' | 'overdue';
  page_url: string | null;
}

/**
 * Formats a Date object to iCal date-time format (YYYYMMDDTHHMMSSZ)
 */
function formatICalDateTime(date: Date): string {
  const year = date.getUTCFullYear();
  const month = String(date.getUTCMonth() + 1).padStart(2, '0');
  const day = String(date.getUTCDate()).padStart(2, '0');
  const hours = String(date.getUTCHours()).padStart(2, '0');
  const minutes = String(date.getUTCMinutes()).padStart(2, '0');
  const seconds = String(date.getUTCSeconds()).padStart(2, '0');

  return `${year}${month}${day}T${hours}${minutes}${seconds}Z`;
}

/**
 * Formats a Date object to iCal date format (YYYYMMDD)
 */
function formatICalDate(date: Date): string {
  const year = date.getUTCFullYear();
  const month = String(date.getUTCMonth() + 1).padStart(2, '0');
  const day = String(date.getUTCDate()).padStart(2, '0');

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

/**
 * Escapes special characters in iCal text fields
 * Follows RFC 5545 section 3.3.11
 */
function escapeICalText(text: string): string {
  return text
    .replace(/\\/g, '\\\\') // Backslash
    .replace(/;/g, '\\;') // Semicolon
    .replace(/,/g, '\\,') // Comma
    .replace(/\n/g, '\\n') // Newline
    .replace(/\r/g, ''); // Remove carriage return
}

/**
 * Folds long lines to 75 characters as per RFC 5545 section 3.1
 */
function foldLine(line: string): string {
  if (line.length <= 75) return line;

  const folded: string[] = [];
  let remaining = line;

  // First line can be 75 characters
  folded.push(remaining.slice(0, 75));
  remaining = remaining.slice(75);

  // Subsequent lines are 74 characters (1 space for continuation)
  while (remaining.length > 0) {
    folded.push(' ' + remaining.slice(0, 74));
    remaining = remaining.slice(74);
  }

  return folded.join('\r\n');
}

/**
 * Generates a unique identifier for an iCal event
 */
function generateUID(eventId: number, domain = 'rankwiz.ai'): string {
  return `seo-calendar-${eventId}@${domain}`;
}

/**
 * Maps calendar entry status to iCal STATUS property
 */
function mapStatusToICal(status: ICalEvent['status']): string {
  switch (status) {
    case 'completed':
      return 'CONFIRMED';
    case 'in_progress':
      return 'CONFIRMED';
    case 'planned':
      return 'TENTATIVE';
    case 'overdue':
      return 'CONFIRMED';
    default:
      return 'TENTATIVE';
  }
}

/**
 * Generates an iCal VEVENT component from a calendar entry
 */
function generateVEvent(event: ICalEvent): string {
  const lines: string[] = ['BEGIN:VEVENT'];

  // Required fields
  const uid = generateUID(event.id);
  lines.push(`UID:${uid}`);

  // Timestamp (current time)
  const dtstamp = formatICalDateTime(new Date());
  lines.push(`DTSTAMP:${dtstamp}`);

  // Start date (use scheduled_date if available, otherwise due_date)
  const startDate = new Date(event.scheduled_date || event.due_date);
  // All-day event (use DATE format without time)
  lines.push(`DTSTART;VALUE=DATE:${formatICalDate(startDate)}`);

  // Due date (as end date for the task)
  const dueDate = new Date(event.due_date);
  lines.push(`DTEND;VALUE=DATE:${formatICalDate(dueDate)}`);

  // Summary (title)
  const summary = escapeICalText(event.title);
  lines.push(foldLine(`SUMMARY:${summary}`));

  // Description
  if (event.description) {
    const description = escapeICalText(event.description);
    lines.push(foldLine(`DESCRIPTION:${description}`));
  }

  // URL
  if (event.page_url) {
    lines.push(foldLine(`URL:${event.page_url}`));
  }

  // Status
  const status = mapStatusToICal(event.status);
  lines.push(`STATUS:${status}`);

  // Mark completed tasks
  if (event.status === 'completed') {
    lines.push('PERCENT-COMPLETE:100');
  }

  lines.push('END:VEVENT');

  return lines.join('\r\n');
}

/**
 * Generates a complete iCal/ICS file from an array of calendar events
 */
export function generateICalendar(events: ICalEvent[], calendarName = 'SEO Calendar'): string {
  const lines: string[] = [];

  // Calendar header
  lines.push('BEGIN:VCALENDAR');
  lines.push('VERSION:2.0');
  lines.push('PRODID:-//RankWiz AI//SEO Calendar//EN');
  lines.push('CALSCALE:GREGORIAN');
  lines.push('METHOD:PUBLISH');
  lines.push(foldLine(`X-WR-CALNAME:${escapeICalText(calendarName)}`));
  lines.push('X-WR-TIMEZONE:UTC');

  // Add each event
  events.forEach((event) => {
    lines.push(generateVEvent(event));
  });

  // Calendar footer
  lines.push('END:VCALENDAR');

  return lines.join('\r\n');
}

/**
 * Triggers a browser download of an iCal/ICS file
 */
export function downloadICalendar(
  events: ICalEvent[],
  filename = 'calendar.ics',
  calendarName = 'SEO Calendar',
): void {
  const icalContent = generateICalendar(events, calendarName);
  const blob = new Blob([icalContent], { type: 'text/calendar;charset=utf-8' });
  const url = URL.createObjectURL(blob);

  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  document.body.removeChild(link);

  // Clean up the URL object
  URL.revokeObjectURL(url);
}
