// How dates are DISPLAYED. Nothing here touches what is stored.
//
// The log keeps ADIF/ISO throughout — the database, ADIF export, LoTW, every
// upload. This is the reading layer only, because an operator reading
// "2026-07-30" as the 7th of the 30th month is reading their own log wrongly,
// and that is a display problem, not a data one.
//
// Storage stays ISO deliberately and permanently: it sorts correctly as text,
// it is what ADIF specifies, and a log whose stored format followed a UI
// preference would become unreadable the day the preference changed.
import { writeUiPref } from '@/lib/uiPref';

export type DateFormat = 'iso' | 'fr' | 'us';

const KEY = 'opslog.dateFormat';

function read(): DateFormat {
	const v = localStorage.getItem(KEY);
	return v === 'fr' || v === 'us' ? v : 'iso';
}

let current: DateFormat = read();

// A minimal store so every grid and panel re-renders the moment the format
// changes, rather than showing the old one until the next restart.
const listeners = new Set<() => void>();

export function getDateFormat(): DateFormat {
	return current;
}

export function setDateFormat(f: DateFormat): void {
	current = f;
	writeUiPref(KEY, f);
	listeners.forEach((l) => l());
}

export function subscribeDateFormat(fn: () => void): () => void {
	listeners.add(fn);
	return () => listeners.delete(fn);
}

// reloadDateFormat re-reads the stored value — for after the portable prefs
// have been synced from the database at startup, which happens AFTER this
// module's first read.
export function reloadDateFormat(): void {
	const v = read();
	if (v !== current) {
		current = v;
		listeners.forEach((l) => l());
	}
}

const pad = (n: number) => String(n).padStart(2, '0');

// order arranges the three parts. Separators stay '-' in every format: a slash
// in the French one would be conventional but it also invites the reader to
// take it for a US date, which is exactly the confusion being fixed.
function order(y: number, m: number, d: number): string {
	switch (current) {
		case 'fr':
			return `${pad(d)}-${pad(m)}-${y}`;
		case 'us':
			return `${pad(m)}-${pad(d)}-${y}`;
	}
	return `${y}-${pad(m)}-${pad(d)}`;
}

// formatDateTimeUTC renders a timestamp with the time, in UTC.
//
// UTC is not negotiable and is not part of the preference: a logbook is kept in
// UTC, and a date shown in local time would disagree with the QSO's own record
// twice a year.
export function formatDateTimeUTC(s: unknown): string {
	if (!s) return '';
	const d = new Date(String(s));
	if (isNaN(d.getTime())) return String(s);
	return `${order(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`;
}

// formatDateOnly renders a date with no time. It accepts both the ADIF form
// (YYYYMMDD, used by every QSL and upload date) and anything Date can parse.
export function formatDateOnly(s: unknown): string {
	if (!s) return '';
	const t = String(s).trim();
	const m = t.match(/^(\d{4})(\d{2})(\d{2})/);
	if (m) return order(Number(m[1]), Number(m[2]), Number(m[3]));
	const d = new Date(t);
	if (isNaN(d.getTime())) return t;
	return order(d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate());
}
