/**
 * RecordingRecoveryModal — shown once on app startup when the
 * Electron main process reports one or more recording sessions
 * with `endedAt === null`. Those are sessions that didn't
 * finalize (e.g. the app was killed mid-recording).
 *
 * Each session offers three actions:
 *   - Keep   — stamps `endedAt` to the latest track's mtime so
 *              the manifest parses cleanly on future scans.
 *   - Delete — removes the session folder entirely.
 *   - Open   — reveals the session folder in the OS file browser
 *              so the user can manually inspect / copy out files.
 *
 * Gated on `platform.features.hasRecording` — the modal never
 * renders on web/Android.
 */
import { useEffect, useState } from 'react';
import { FolderOpen, Trash } from '@phosphor-icons/react';
import { Modal, Button } from '@discord-clone/ui';
import { usePlatform } from '../../platform';
import styles from './RecordingRecoveryModal.module.css';

interface RecoverableSession {
	sessionId: string;
	sessionDir: string;
	channelId: string | null;
	channelName: string | null;
	startedAt: number;
	participantCount: number;
	trackCount: number;
}

function formatStartedAt(ts: number): string {
	try {
		const d = new Date(ts);
		return d.toLocaleString([], {
			year: 'numeric',
			month: 'short',
			day: 'numeric',
			hour: 'numeric',
			minute: '2-digit',
		});
	} catch {
		return '—';
	}
}

export function RecordingRecoveryModal() {
	const platform = usePlatform() as any;
	const hasRecording = !!platform?.features?.hasRecording;
	const recording = platform?.recording;

	const [sessions, setSessions] = useState<RecoverableSession[]>([]);
	const [isOpen, setIsOpen] = useState(false);
	const [busy, setBusy] = useState<string | null>(null);

	useEffect(() => {
		if (!hasRecording || !recording) return;
		let cancelled = false;
		(async () => {
			try {
				// Look up the user-preferred root (same place the
				// recorder reads from) so we scan the right folder.
				let rootDir: string | null = null;
				try {
					const raw = localStorage.getItem('voiceSettings');
					if (raw) {
						const parsed = JSON.parse(raw);
						if (parsed && typeof parsed.recordingDir === 'string') {
							rootDir = parsed.recordingDir;
						}
					}
				} catch {}
				const res = await recording.listRecoverable({ rootDir });
				if (cancelled) return;
				if (res?.ok && Array.isArray(res.sessions) && res.sessions.length > 0) {
					setSessions(res.sessions);
					setIsOpen(true);
				}
			} catch (err) {
				console.warn('Recording recovery scan failed:', err);
			}
		})();
		return () => {
			cancelled = true;
		};
	}, [hasRecording, recording]);

	if (!hasRecording) return null;

	const dismiss = () => {
		setIsOpen(false);
		setSessions([]);
	};

	const handleKeep = async (session: RecoverableSession) => {
		if (!recording) return;
		setBusy(session.sessionId);
		try {
			await recording.recoverSession({
				sessionDir: session.sessionDir,
				action: 'keep',
			});
			setSessions((prev) => prev.filter((s) => s.sessionId !== session.sessionId));
		} catch (err) {
			console.warn('Failed to keep recovered session:', err);
		} finally {
			setBusy(null);
		}
	};

	const handleDelete = async (session: RecoverableSession) => {
		if (!recording) return;
		const ok = window.confirm(
			`Delete recording from ${formatStartedAt(session.startedAt)}?\n\n` +
				`This permanently removes ${session.trackCount} audio file${session.trackCount === 1 ? '' : 's'}.`,
		);
		if (!ok) return;
		setBusy(session.sessionId);
		try {
			await recording.recoverSession({
				sessionDir: session.sessionDir,
				action: 'delete',
			});
			setSessions((prev) => prev.filter((s) => s.sessionId !== session.sessionId));
		} catch (err) {
			console.warn('Failed to delete recovered session:', err);
		} finally {
			setBusy(null);
		}
	};

	const handleOpen = async (session: RecoverableSession) => {
		if (!recording) return;
		try {
			await recording.openFolder(session.sessionDir);
		} catch (err) {
			console.warn('Failed to open recovered folder:', err);
		}
	};

	useEffect(() => {
		if (isOpen && sessions.length === 0) {
			setIsOpen(false);
		}
	}, [isOpen, sessions.length]);

	return (
		<Modal.Root isOpen={isOpen} onClose={dismiss} size="medium">
			<Modal.Header title="Recover voice recordings" onClose={dismiss} />
			<Modal.Content>
				<div className={styles.card}>
					<p className={styles.lead}>
						These voice recordings didn't finalise cleanly. The audio is
						intact up to the moment the app was interrupted. Choose what
						to do with each session — keeping a session just stamps the
						end time so it stops appearing in this list.
					</p>
					<div className={styles.list}>
						{sessions.map((session) => (
							<div key={session.sessionId} className={styles.row}>
								<div className={styles.rowMeta}>
									<span className={styles.rowPrimary}>
										{session.channelName ? `#${session.channelName}` : 'Voice call'}
										{' • '}
										{formatStartedAt(session.startedAt)}
									</span>
									<span className={styles.rowSecondary}>
										{session.trackCount} file
										{session.trackCount === 1 ? '' : 's'} ·{' '}
										{session.participantCount} participant
										{session.participantCount === 1 ? '' : 's'}
									</span>
								</div>
								<div className={styles.rowActions}>
									<button
										type="button"
										className={styles.actionButton}
										onClick={() => handleOpen(session)}
										disabled={busy === session.sessionId}
										title="Open in file explorer"
									>
										<FolderOpen size={14} weight="bold" />
										Open
									</button>
									<button
										type="button"
										className={`${styles.actionButton} ${styles.actionDanger}`}
										onClick={() => handleDelete(session)}
										disabled={busy === session.sessionId}
										title="Delete recording"
									>
										<Trash size={14} weight="bold" />
										Delete
									</button>
									<button
										type="button"
										className={styles.actionButton}
										onClick={() => handleKeep(session)}
										disabled={busy === session.sessionId}
										title="Keep this recording"
									>
										Keep
									</button>
								</div>
							</div>
						))}
					</div>
					<div className={styles.footer}>
						<Button variant="secondary" size="sm" onClick={dismiss}>
							Close
						</Button>
					</div>
				</div>
			</Modal.Content>
		</Modal.Root>
	);
}
