/**
 * Shared formatting utilities for consistent display across the app.
 */

/**
 * Convert minutes to a human-readable duration string.
 *
 * Examples:
 *   45   → "45m"
 *   60   → "1h"
 *   90   → "1h 30m"
 *   120  → "2h"
 *   150  → "2h 30m"
 */
export function formatDuration(minutes: number): string {
	const hours = Math.floor(minutes / 60);
	const mins = minutes % 60;
	if (hours === 0) return `${mins}m`;
	if (mins === 0) return `${hours}h`;
	return `${hours}h ${mins}m`;
}

/**
 * Format a date/time to "Weekday, Month Day at HH:MM AM/PM".
 *
 * Examples:
 *   "2026-05-29T10:00:00Z" → "Friday, May 29 at 10:00 AM"
 *   "2026-06-05T14:30:00Z" → "Friday, Jun 5 at 2:30 PM"
 */
export function formatDateTime(date: Date | string): string {
	const d = typeof date === 'string' ? new Date(date) : date;
	const dateStr = d.toLocaleDateString('en-US', {
		weekday: 'long',
		month: 'short',
		day: 'numeric',
		timeZone: 'Europe/London'
	});
	const timeStr = d.toLocaleTimeString('en-US', {
		hour: 'numeric',
		minute: '2-digit',
		hour12: true,
		timeZone: 'Europe/London'
	});
	return `${dateStr} at ${timeStr}`;
}

/**
 * Format a Date to ISO date string "YYYY-MM-DD".
 *
 * Example: new Date(2026, 4, 29) → "2026-05-29"
 */
export function formatDateISO(d: Date, timeZone = 'Europe/London'): string {
	return d.toLocaleDateString('en-CA', { timeZone });
}

/**
 * Format a date value to "Weekday, Month Day" only (no time).
 *
 * Example: "2026-05-29" → "Friday, May 29"
 */
export function formatDate(date: Date | string): string {
	const d = typeof date === 'string' ? new Date(date) : date;
	return d.toLocaleDateString('en-US', {
		weekday: 'long',
		month: 'short',
		day: 'numeric',
		timeZone: 'Europe/London'
	});
}

/**
 * Format a time value to "HH:MM AM/PM".
 *
 * Example:  new Date("2026-05-29T14:30:00Z") → "2:30 PM"
 */
export function formatTime(date: Date | string): string {
	const d = typeof date === 'string' ? new Date(date) : date;
	return d.toLocaleTimeString('en-US', {
		hour: 'numeric',
		minute: '2-digit',
		hour12: true,
		timeZone: 'Europe/London'
	});
}

/**
 * Calculate age from a date-of-birth string.
 * Returns the number of full years, or null if DOB is invalid.
 */
export function calculateAge(dateOfBirth: string | undefined | null): number | null {
	if (!dateOfBirth) return null;
	const dob = new Date(dateOfBirth);
	if (isNaN(dob.getTime())) return null;
	const today = new Date();

	// Get London date components to ensure correct DST-safe age calculation
	const [dobY, dobM, dobD] = dob
		.toLocaleDateString('en-CA', { timeZone: 'Europe/London' })
		.split('-')
		.map(Number);
	const [todayY, todayM, todayD] = today
		.toLocaleDateString('en-CA', { timeZone: 'Europe/London' })
		.split('-')
		.map(Number);

	let age = todayY - dobY;
	const monthDiff = todayM - dobM;
	if (monthDiff < 0 || (monthDiff === 0 && todayD < dobD)) {
		age--;
	}
	return age;
}

/**
 * Format a 12-character gift card code into display format (XXXX-XXXX-XXXX).
 * Example: "a3f1c9d2b4e8" → "A3F1-C9D2-B4E8"
 */
export function formatCardCode(id: string): string {
	if (id.length !== 12) return id;
	return `${id.slice(0, 4)}-${id.slice(4, 8)}-${id.slice(8, 12)}`.toUpperCase();
}
