import React, { useCallback, useEffect, useState } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { Alert, Badge, Button, Skeleton, SkeletonGroup, useConfirm, useToast } from '../../shared/ui';
import useForm from '../core/useForm';
import { useUnsavedChanges } from '../core/AdminContext';
import { Page, PageHeader, SaveBar } from '../ui/page';

export const recordId = () => Number(new URLSearchParams(window.location.search).get('id') || 0) || 0;

/**
 * State machine behind an "edit one record" screen.
 *
 * useRecord({ id, blank, load, save, remove, editHref, listHref, validate })
 *   load(id)            -> values for the form (async)
 *   save(values, id)    -> id of the saved record (async; create when id is 0)
 *   remove(id)          -> async
 *   validate(values)    -> '' or an error message (or { message, field })
 */
export function useRecord({ id, blank, load, save, remove, editHref, listHref, validate, toastSaved }) {
	const form = useForm(blank);
	const toast = useToast();
	const confirm = useConfirm();
	const [loading, setLoading] = useState(!!id);
	const [saving, setSaving] = useState(false);
	const [error, setError] = useState('');
	const [loadError, setLoadError] = useState('');
	useUnsavedChanges(form.dirty && !saving, 'record');

	const loadRecord = useCallback(async () => {
		if (!id) return;
		setLoading(true);
		setLoadError('');
		try {
			form.load(await load(id));
		} catch (e) {
			setLoadError(e.message);
		} finally {
			setLoading(false);
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [id]);

	useEffect(() => {
		loadRecord();
	}, [loadRecord]);

	const onSave = async () => {
		setError('');
		const problem = validate ? validate(form.values) : '';
		if (problem) {
			setError(typeof problem === 'string' ? problem : problem.message);
			window.scrollTo({ top: 0, behavior: 'smooth' });
			return false;
		}
		setSaving(true);
		const sent = form.values;
		try {
			const newId = await save(sent, id);
			toast.success(toastSaved || __('Saved', 'pointly-booking'));
			if (!id && newId && editHref) {
				// Creating: continue on the edit URL so a reload keeps working.
				form.markSaved(sent);
				window.location.href = editHref(newId);
				return true;
			}
			form.markSaved(sent);
			return true;
		} catch (e) {
			setError(e.message);
			window.scrollTo({ top: 0, behavior: 'smooth' });
			return false;
		} finally {
			setSaving(false);
		}
	};

	const onDelete = async (name) => {
		const ok = await confirm({
			title: name ? sprintf(/* translators: %s: item name. */ __('Delete “%s”?', 'pointly-booking'), name) : __('Delete this item?', 'pointly-booking'),
			message: __('This cannot be undone.', 'pointly-booking'),
			confirmLabel: __('Delete', 'pointly-booking'),
			cancelLabel: __('Keep it', 'pointly-booking'),
			danger: true,
		});
		if (!ok) return;
		setSaving(true);
		try {
			await remove(id);
			form.markSaved();
			window.location.href = listHref;
		} catch (e) {
			setError(e.message);
			setSaving(false);
		}
	};

	return { form, loading, saving, error, setError, loadError, reload: loadRecord, onSave, onDelete, isNew: !id };
}

/**
 * Layout for an edit screen: header with back link, error banner, content and a sticky save bar.
 */
export default function EditPage({ title, subtitle, backLabel, backHref, status, record, canDelete = true, deleteName, children, extraActions }) {
	const { form, loading, saving, error, loadError, reload, onSave, onDelete, isNew } = record;

	return (
		<Page>
			<PageHeader
				title={title}
				subtitle={subtitle}
				back={{ href: backHref, label: backLabel }}
				actions={
					<>
						{status ? <Badge tone={status.tone} dot>{status.label}</Badge> : null}
						{extraActions}
						{!isNew && canDelete ? (
							<Button variant="danger-ghost" icon="trash" onClick={() => onDelete(deleteName)} disabled={saving}>
								{__('Delete', 'pointly-booking')}
							</Button>
						) : null}
					</>
				}
			/>

			{loadError ? (
				<Alert tone="danger" title={__('This could not be loaded', 'pointly-booking')} actions={<Button size="sm" variant="secondary" onClick={reload}>{__('Try again', 'pointly-booking')}</Button>}>
					{loadError}
				</Alert>
			) : null}

			{error ? (
				<Alert tone="danger" live title={__('Please check the form', 'pointly-booking')}>
					{error}
				</Alert>
			) : null}

			{loading ? (
				<SkeletonGroup label={__('Loading…', 'pointly-booking')} className="bp-stack">
					<Skeleton height={180} block />
					<Skeleton height={220} block />
				</SkeletonGroup>
			) : loadError ? null : (
				children
			)}

			<SaveBar dirty={form.dirty} saving={saving} onSave={onSave} onDiscard={form.reset} alwaysVisible={isNew} saveLabel={isNew ? __('Create', 'pointly-booking') : undefined} />
		</Page>
	);
}
