import React, { useEffect, useState } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import { Alert, Button, Icon, Skeleton, SkeletonGroup } from '../../../shared/ui';
import { api, waitForPaid } from '../api';
import { formatClock, formatDateWithWeekday, formatDuration, formatMoney, tzLabel } from '../format';
import { paymentMeta } from '../payments';

/**
 * Loads the booking (server truth) after checkout. Online payments can take a
 * few seconds to be confirmed by the provider's webhook, so those are polled.
 */
function useBooking(id, key, online) {
	const [state, setState] = useState({ loading: true, booking: null, status: null, error: '' });
	useEffect(() => {
		let alive = true;
		(async () => {
			try {
				const status = online ? await waitForPaid(id, key) : await api.status(id, key);
				const booking = await api.summary(id, key);
				if (alive) setState({ loading: false, booking, status, error: '' });
			} catch (e) {
				if (alive) setState({ loading: false, booking: null, status: null, error: e.message });
			}
		})();
		return () => {
			alive = false;
		};
	}, [id, key, online]);
	return state;
}

export function outcome(status, method) {
	const online = paymentMeta(method).online;
	const st = status?.status || '';
	const pay = status?.payment_status || '';
	if (online && !(st === 'confirmed' && pay === 'paid')) {
		if (st === 'cancelled' || pay === 'cancelled' || pay === 'failed') return 'failed';
		return 'processing';
	}
	return st === 'pending' ? 'requested' : 'confirmed';
}

export default function ConfirmationStep({ id, method, bookingKey, onAnother, onClose, onRetryPayment }) {
	const online = paymentMeta(method).online;
	const { loading, booking, status, error } = useBooking(id, bookingKey, online);
	const [copied, setCopied] = useState(false);

	if (loading) {
		return (
			<SkeletonGroup label={__('Confirming your booking…', 'pointly-booking')} className="bp-bw-confirm__loading">
				<Skeleton height={64} circle width={64} />
				<Skeleton height={28} width="60%" />
				<Skeleton height={120} />
			</SkeletonGroup>
		);
	}

	if (error || !booking) {
		return (
			<div className="bp-bw-confirm">
				<Alert tone="warning" live title={__('We could not load your booking details', 'pointly-booking')}>
					{error || __('If you received a confirmation email, your booking is safe.', 'pointly-booking')}
				</Alert>
				<div className="bp-bw-confirm__actions">
					<Button variant="primary" onClick={onClose}>
						{__('Close', 'pointly-booking')}
					</Button>
				</div>
			</div>
		);
	}

	const result = outcome(status, method);
	const tone = result === 'failed' ? 'danger' : result === 'processing' ? 'warning' : 'success';
	const icon = result === 'failed' ? 'x-circle' : result === 'processing' ? 'clock' : 'check-circle';
	const heading = {
		confirmed: __('You are booked!', 'pointly-booking'),
		requested: __('Booking request received', 'pointly-booking'),
		processing: __('Finishing your payment…', 'pointly-booking'),
		failed: __('Payment was not completed', 'pointly-booking'),
	}[result];
	const sub = {
		confirmed: __('A confirmation email is on its way.', 'pointly-booking'),
		requested: __('We will confirm your booking shortly by email.', 'pointly-booking'),
		processing: __('Your payment is still being processed. This can take a moment; you will get an email once it is confirmed.', 'pointly-booking'),
		failed: __('Your booking was not confirmed and no time is being held. You can try again.', 'pointly-booking'),
	}[result];

	const copy = async () => {
		try {
			await navigator.clipboard.writeText(booking.reference);
			setCopied(true);
			window.setTimeout(() => setCopied(false), 2000);
		} catch (e) {
			// Clipboard unavailable: the reference is visible and selectable anyway.
		}
	};

	const showCalendar = result === 'confirmed' || result === 'requested';

	return (
		<div className="bp-bw-confirm">
			<div className={`bp-bw-confirm__hero bp-bw-confirm__hero--${tone}`} role="status">
				<span className="bp-bw-confirm__badge" aria-hidden="true">
					<Icon name={icon} size={32} />
				</span>
				<h3 className="bp-bw-confirm__title">
					{heading}
				</h3>
				<p className="bp-bw-confirm__sub">{sub}</p>
			</div>

			<div className="bp-bw-confirm__ref">
				<span className="bp-bw-confirm__ref-label">{__('Booking reference', 'pointly-booking')}</span>
				<span className="bp-bw-confirm__ref-value">{booking.reference}</span>
				<Button variant="ghost" size="sm" icon={copied ? 'check' : 'copy'} onClick={copy}>
					{copied ? __('Copied', 'pointly-booking') : __('Copy', 'pointly-booking')}
				</Button>
			</div>

			<dl className="bp-bw-confirm__details">
				<div>
					<dt>{__('Service', 'pointly-booking')}</dt>
					<dd>
						{booking.service}
						{booking.duration ? <span className="bp-bw-confirm__muted"> · {formatDuration(booking.duration)}</span> : null}
					</dd>
				</div>
				{booking.staff ? (
					<div>
						<dt>{__('Staff', 'pointly-booking')}</dt>
						<dd>{booking.staff}</dd>
					</div>
				) : null}
				<div>
					<dt>{__('When', 'pointly-booking')}</dt>
					<dd>
						{formatDateWithWeekday(booking.date)}
						<br />
						{booking.end_time
							? /* translators: 1: start time, 2: end time. */ sprintf(__('%1$s – %2$s', 'pointly-booking'), formatClock(booking.start_time), formatClock(booking.end_time))
							: formatClock(booking.start_time)}
						{booking.timezone ? <span className="bp-bw-confirm__muted"> ({tzLabel(booking.timezone)})</span> : null}
					</dd>
				</div>
				{booking.extras && booking.extras.length ? (
					<div>
						<dt>{__('Extras', 'pointly-booking')}</dt>
						<dd>{booking.extras.map((x) => x.name).join(', ')}</dd>
					</div>
				) : null}
				<div>
					<dt>{__('Total', 'pointly-booking')}</dt>
					<dd>
						{booking.total > 0 ? formatMoney(booking.total, booking.currency) : __('Free', 'pointly-booking')}
						{booking.total > 0 ? (
							<span className="bp-bw-confirm__muted">
								{' · '}
								{booking.payment_status === 'paid' ? __('Paid', 'pointly-booking') : paymentMeta(booking.payment_method || method).label}
							</span>
						) : null}
					</dd>
				</div>
			</dl>

			{showCalendar ? (
				<div className="bp-bw-confirm__calendar">
					<h3 className="bp-bw-subhead">{__('Add to your calendar', 'pointly-booking')}</h3>
					<div className="bp-bw-confirm__buttons">
						{booking.google_calendar_url ? (
							<Button variant="secondary" icon="calendar-plus" href={booking.google_calendar_url} target="_blank" rel="noopener noreferrer">
								{__('Google Calendar', 'pointly-booking')}
							</Button>
						) : null}
						{booking.ics_url ? (
							<Button variant="secondary" icon="download" href={booking.ics_url} download>
								{__('Download .ics', 'pointly-booking')}
							</Button>
						) : null}
					</div>
				</div>
			) : null}

			<div className="bp-bw-confirm__actions">
				{result === 'failed' && online ? (
					<Button variant="primary" onClick={onRetryPayment}>
						{__('Try again', 'pointly-booking')}
					</Button>
				) : (
					<Button variant="secondary" icon="calendar-plus" onClick={onAnother}>
						{__('Book another', 'pointly-booking')}
					</Button>
				)}
				{booking.manage_url && result !== 'failed' ? (
					<Button variant="ghost" href={booking.manage_url}>
						{__('Manage this booking', 'pointly-booking')}
					</Button>
				) : null}
				<Button variant="ghost" onClick={onClose}>
					{__('Close', 'pointly-booking')}
				</Button>
			</div>
		</div>
	);
}
