import { Reservation, Settings } from '@backend/domain'
import { Injectable } from '@nestjs/common'
import { format, formatISO } from 'date-fns'

@Injectable()
export class ICSService {
	generateIcs(reservation: Reservation, settings: Settings, options?: { cancelled?: boolean }): string {
		const start = this.normalizeDate(reservation.startDate)
		const end = this.normalizeDate(reservation.endDate)
		const cancelled = options?.cancelled === true

		const ics_lines = [
			'BEGIN:VCALENDAR',
			'PRODID:-//KADiCon Inc//KADiCon v1.0//EN',
			'VERSION:2.0',
			// METHOD:CANCEL with the same UID removes the event from the guest's calendar
			`METHOD:${cancelled ? 'CANCEL' : 'REQUEST'}`,
			'CALSCALE:GREGORIAN',
			'BEGIN:VEVENT',
			`UID:${reservation.id}`,
			`DTSTAMP:${start}`,
			`DTSTART:${start}`,
			`DTEND:${end}`,
			`SUMMARY:${`Reservation at ${settings.customerApp.displayName}`.replace(/.{65}/g, '$&\r\n ')}`, // making sure it does not exceed 75 characters per line
			`LOCATION:${settings.restaurant.address}`,
			`ATTENDEE;CN=${reservation.customerData.name}:mailto:${reservation.customerData.email}`,
			`ORGANIZER;CN=${settings.customerApp.displayName}:mailto:${settings.restaurant.email}`,
			`BEGIN:VALARM`,
			`TRIGGER:-PT30M`,
			`ACTION:DISPLAY`,
			`DESCRIPTION:Reservation at ${settings.customerApp.displayName} at ${format(reservation.startDate, 'H:mm')}`,
			`END:VALARM`,
			'DESCRIPTION:',
			`STATUS:${cancelled ? 'CANCELLED' : 'CONFIRMED'}`,
			'LAST-MODIFIED:' + this.normalizeDate(new Date()),
			// Cancellations must carry a higher sequence than the original invite
			`SEQUENCE:${cancelled ? '1' : '0'}`,
			'END:VEVENT',
			'END:VCALENDAR',
		]
		return ics_lines.join('\r\n')
	}

	/**
	 * It takes a date object and returns a string in the ISO format
	 * @param {Date} date - The date to be formatted.
	 * @returns A string in the ISO format without timezone information
	 */
	normalizeDate(date: Date): string {
		// split removes additional timezone info (outlook would produce error otherwise)
		return formatISO(date, { format: 'basic' }).split('+')[0]
	}
}
