import type { ApiTrainsTrainDetails } from '@owlboard/owlboard-ts';

export const estClass = (act: any, est: any) =>
	act ? 'actual' : est ? 'estimate' : undefined;

/**
 * Converts ISO/JSON time to UK-formatted HH:MM string, with optional (default off) seconds
 * Ensures Europe/London timezone irrespective of browser timezone.
 */
export function formatUkTime(
	dateStr: string | Date | undefined,
	includeSeconds: boolean = false
): string {
	if (!dateStr) return '-';
	const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr;

	if (isNaN(date.getTime())) return '-';

	return date.toLocaleTimeString('en-GB', {
		hour: '2-digit',
		minute: '2-digit',
		...(includeSeconds && { second: '2-digit' }),
		hour12: false,
		timeZone: 'Europe/London'
	});
}

/**
 * Converts ISO/JSON time to UK-formatted DD/MM/YY HH:MM:SS string.
 * Ensures Europe/London timezone irrespective of browser timezone.
 */
export function formatUkDateTime(
	dateStr: string | Date | undefined,
	includeSeconds: boolean = false
): string {
	if (!dateStr) return '--/--/-- --:--:--';

	const date = typeof dateStr === 'string' ? new Date(dateStr) : dateStr;

	if (isNaN(date.getTime())) return '--/--/-- --:--:--';

	return date
		.toLocaleString('en-GB', {
			day: '2-digit',
			month: '2-digit',
			year: '2-digit',
			hour: '2-digit',
			minute: '2-digit',
			...(includeSeconds && { second: '2-digit' }),
			hour12: false,
			timeZone: 'Europe/London'
		})
		.replace(',', '');
}

/**
 * Specific type that can handle the TrainDetails.ServiceLocation and the ApiStationsBoard.BoardService types for delay calculation
 */
interface DelayInput {
	// Board types
	sta?: string | null;
	std?: string | null;
	eta?: string | null;
	etd?: string | null;
	ata?: string | null;
	atd?: string | null;

	// Journey types
	pta?: string | null;
	ptd?: string | null;
	wta?: string | null;
	wtd?: string | null;
	atp?: string | null;
	wtp?: string | null;
	etp?: string | null;
}

/**
 * Calculates a 'delay' value, in the formats:
 * RT, 1E, 7L, etc.
 * @param 'Schedule Location' or 'Board Service' object
 * @returns Delay string for departure boards
 */
export function calculateDelay(loc: DelayInput): {
	val: string;
	type: string;
} {
	const pairs = [
		// Departure check (Board: atd/etd vs std | Journey: atd vs ptd/wtd)
		{ actual: loc.atd || loc.etd, sched: loc.std || loc.ptd || loc.wtd },
		// Arrival check (Board: ata/eta vs sta | Journey: ata vs pta/wta)
		{ actual: loc.ata || loc.eta, sched: loc.sta || loc.pta || loc.wta },
		// Passing check
		{ actual: loc.atp || loc.etp, sched: loc.wtp }
	];

	const match = pairs.find((p) => p.actual && p.sched);

	if (!match || !match.actual || !match.sched) return { val: '', type: 'none' };

	const diffMinutes = Math.round((Date.parse(match.actual) - Date.parse(match.sched)) / 60000);

	if (diffMinutes === 0) return { val: 'RT', type: 'ontime' };

	const absDiff = Math.abs(diffMinutes);
	if (diffMinutes > 0) {
		return { val: `${absDiff}L`, type: 'late' };
	} else {
		return { val: `${absDiff}E`, type: 'early' };
	}
}

/**
 * Accepts a pair of times (string or Date) and outputs a delay class 'delay-early', 'delay-late' or 'delay-rt'
 * @param sched Scheduled Time (string, Date)
 * @param act Actual Time (string, Date)
 */
export function delayClassFromTimePair(sched: any, act: any): string {
	if (!sched || !act) return '';

	const s = new Date(sched).getTime();
	const a = new Date(act).getTime();

	if (isNaN(s) || isNaN(a)) return '';

	const diff = a - s;
	const oneMinute = 60000;

	// on-time if within one minute
	if (Math.abs(diff) < oneMinute) {
		return 'delay-rt';
	}

	return diff > 0 ? 'delay-late' : 'delay-early';
}

/**
 * Accepts a pair of times (string or Date) and returns true if service considered 'on-time'
 * @param sched Scheduled Time (string, Date)
 * @param act Actual Time (string, Date)
 */
export function isRightTime(
	sched: string | Date | undefined,
	act: string | Date | undefined
): boolean {
	console.log(`Checking [sched: ${sched}, act: ${act}]`);
	if (!sched || !act) return false;

	const s = new Date(sched).getTime();
	const a = new Date(act).getTime();

	if (isNaN(s) || isNaN(a)) return false;

	return Math.abs(a - s) < 60000;
}
