import { useEffect, useRef, useState } from 'react';
import { usePlatform } from '../../platform';
import styles from './HeaderUpdateIcon.module.css';

interface UpdateStatus {
	hasUpdate: boolean;
	required: boolean;
	latestVersion: string | null;
	currentVersion: string | null;
	releaseNotes: string | null;
	downloading: boolean;
	downloaded: boolean;
	progress: number;
	error: string | null;
}

const INITIAL: UpdateStatus = {
	hasUpdate: false,
	required: false,
	latestVersion: null,
	currentVersion: null,
	releaseNotes: null,
	downloading: false,
	downloaded: false,
	progress: 0,
	error: null,
};

// Strip the `[REQUIRED]` marker from the notes so the popover doesn't
// repeat information the UI itself already conveys.
function cleanNotes(notes: string | null): string {
	if (!notes) return '';
	return notes.replace(/^\s*\[REQUIRED\]\s*/i, '').trim();
}

function UpdateArrow() {
	return (
		<svg
			aria-hidden="true"
			xmlns="http://www.w3.org/2000/svg"
			width="20"
			height="20"
			fill="none"
			viewBox="0 0 24 24"
		>
			<path
				fill="currentColor"
				d="M12 2a1 1 0 0 1 1 1v10.59l3.3-3.3a1 1 0 1 1 1.4 1.42l-5 5a1 1 0 0 1-1.4 0l-5-5a1 1 0 1 1 1.4-1.42l3.3 3.3V3a1 1 0 0 1 1-1M3 20a1 1 0 1 0 0 2h18a1 1 0 1 0 0-2z"
			/>
		</svg>
	);
}

export function HeaderUpdateIcon() {
	const platform = usePlatform() as any;
	const updates = platform?.updates ?? null;
	const hasInApp =
		typeof updates?.getStatus === 'function' &&
		typeof updates?.downloadAndInstall === 'function';

	const [status, setStatus] = useState<UpdateStatus>(INITIAL);
	const [open, setOpen] = useState(false);
	const wrapRef = useRef<HTMLDivElement | null>(null);

	useEffect(() => {
		if (!hasInApp) return;
		let cancelled = false;
		(async () => {
			try {
				const current = await updates.getStatus();
				if (!cancelled && current) setStatus({ ...INITIAL, ...current });
			} catch {}
		})();
		const off = updates.onStatusChanged?.((next: UpdateStatus) => {
			setStatus({ ...INITIAL, ...next });
		});
		return () => {
			cancelled = true;
			if (typeof off === 'function') off();
		};
	}, [hasInApp, updates]);

	useEffect(() => {
		if (!open) return;
		const onDocClick = (e: MouseEvent) => {
			if (wrapRef.current && !wrapRef.current.contains(e.target as Node)) {
				setOpen(false);
			}
		};
		document.addEventListener('mousedown', onDocClick);
		return () => document.removeEventListener('mousedown', onDocClick);
	}, [open]);

	if (!hasInApp) return null;
	if (!status.hasUpdate) return null;

	const versionLabel = status.latestVersion ? `v${status.latestVersion}` : 'a new version';
	const currentLabel = status.currentVersion ? ` (you have v${status.currentVersion})` : '';
	const notes = cleanNotes(status.releaseNotes);

	const onInstall = () => {
		if (!updates?.downloadAndInstall) return;
		void updates.downloadAndInstall();
	};

	// Required update: render as a blocking overlay instead of a
	// silent icon. The user must update to continue.
	if (status.required) {
		return (
			<div className={styles.blocker} role="alertdialog" aria-modal="true">
				<div className={styles.blockerCard}>
					<h2>Update required</h2>
					<p>
						{`${versionLabel} is required to keep using the app${currentLabel}.`}
						{notes ? `\n\n${notes}` : ''}
					</p>
					{status.downloading && (
						<div className={styles.progressTrack}>
							<div
								className={styles.progressFill}
								style={{ width: `${Math.max(2, status.progress)}%` }}
							/>
						</div>
					)}
					<button
						type="button"
						className={styles.primaryBtn}
						onClick={onInstall}
						disabled={status.downloading}
					>
						{status.downloading
							? `Downloading… ${Math.round(status.progress)}%`
							: status.downloaded
								? 'Install and restart'
								: 'Update now'}
					</button>
				</div>
			</div>
		);
	}

	return (
		<div className={styles.wrap} ref={wrapRef}>
			<button
				type="button"
				className={styles.button}
				onClick={() => setOpen((v) => !v)}
				aria-label={`Update to ${versionLabel}`}
				title={`Update to ${versionLabel}`}
			>
				<UpdateArrow />
			</button>
			{open && (
				<div className={styles.popover} role="dialog">
					<div className={styles.popoverTitle}>{`Update to ${versionLabel}`}</div>
					<div className={styles.popoverSubtitle}>
						{notes ||
							`A new version is available${currentLabel}. You can keep using the current version, or update now.`}
					</div>
					{status.downloading && (
						<div className={styles.progressTrack}>
							<div
								className={styles.progressFill}
								style={{ width: `${Math.max(2, status.progress)}%` }}
							/>
						</div>
					)}
					<div className={styles.actions}>
						<button
							type="button"
							className={styles.secondaryBtn}
							onClick={() => setOpen(false)}
							disabled={status.downloading}
						>
							Later
						</button>
						<button
							type="button"
							className={styles.primaryBtn}
							onClick={onInstall}
							disabled={status.downloading}
						>
							{status.downloading
								? `…${Math.round(status.progress)}%`
								: status.downloaded
									? 'Restart'
									: 'Update now'}
						</button>
					</div>
				</div>
			)}
		</div>
	);
}
