import React, { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { __, sprintf } from '@wordpress/i18n';
import Icon from '../icons/Icon';
import { Portal } from './core';
import { IconButton } from './Button';

/* ======================================================================
   Toasts
   ====================================================================== */
const ToastContext = createContext(null);
const TOAST_ICONS = { success: 'check-circle', error: 'alert-circle', warning: 'alert-triangle', info: 'info' };

function ToastItem({ toast, onDismiss }) {
	const timer = useRef(null);
	const start = useCallback(() => {
		if (toast.duration === 0) return;
		timer.current = window.setTimeout(() => onDismiss(toast.id), toast.duration || 4500);
	}, [toast, onDismiss]);
	const stop = () => window.clearTimeout(timer.current);
	useEffect(() => {
		start();
		return stop;
	}, [start]);

	return (
		<div
			className={['bp-toast', `bp-toast--${toast.tone}`].join(' ')}
			role={toast.tone === 'error' ? 'alert' : 'status'}
			onMouseEnter={stop}
			onMouseLeave={start}
			onFocus={stop}
			onBlur={start}
		>
			<Icon name={TOAST_ICONS[toast.tone] || 'info'} className="bp-toast__icon" />
			<div className="bp-toast__body">
				<div className="bp-toast__title">{toast.title}</div>
				{toast.message ? <div className="bp-toast__msg">{toast.message}</div> : null}
				{toast.action ? (
					<button type="button" className="bp-btn bp-btn--link bp-btn--sm" style={{ marginTop: 4 }} onClick={() => { toast.action.onClick(); onDismiss(toast.id); }}>
						{toast.action.label}
					</button>
				) : null}
			</div>
			<IconButton icon="x" size="sm" label={__('Dismiss notification', 'pointly-booking')} onClick={() => onDismiss(toast.id)} />
		</div>
	);
}

/**
 * Provides `useToast()`:
 *   const toast = useToast();
 *   toast.success(__('Saved')); toast.error(msg); toast.show({ tone, title, message, duration, action })
 */
export function ToastProvider({ children }) {
	const [toasts, setToasts] = useState([]);
	const idRef = useRef(0);

	const dismiss = useCallback((id) => setToasts((list) => list.filter((t) => t.id !== id)), []);
	const show = useCallback((opts) => {
		idRef.current += 1;
		const t = { tone: 'info', ...opts, id: idRef.current };
		setToasts((list) => [...list.slice(-3), t]);
		return t.id;
	}, []);

	const api = React.useMemo(
		() => ({
			show,
			dismiss,
			success: (title, message) => show({ tone: 'success', title, message }),
			error: (title, message) => show({ tone: 'error', title, message, duration: 7000 }),
			warning: (title, message) => show({ tone: 'warning', title, message }),
			info: (title, message) => show({ tone: 'info', title, message }),
		}),
		[show, dismiss]
	);

	return (
		<ToastContext.Provider value={api}>
			{children}
			<Portal>
				<div className="bp-toasts" aria-live="polite" aria-relevant="additions">
					{toasts.map((t) => (
						<ToastItem key={t.id} toast={t} onDismiss={dismiss} />
					))}
				</div>
			</Portal>
		</ToastContext.Provider>
	);
}

const noopToast = { show: () => 0, dismiss: () => {}, success: () => 0, error: () => 0, warning: () => 0, info: () => 0 };
export function useToast() {
	return useContext(ToastContext) || noopToast;
}

/* ======================================================================
   Pagination
   ====================================================================== */
function pageList(page, pages) {
	if (pages <= 7) return Array.from({ length: pages }, (_, i) => i + 1);
	const out = [1];
	const from = Math.max(2, page - 1);
	const to = Math.min(pages - 1, page + 1);
	if (from > 2) out.push('…');
	for (let i = from; i <= to; i++) out.push(i);
	if (to < pages - 1) out.push('…');
	out.push(pages);
	return out;
}

export function Pagination({ page, perPage, total, onPageChange, label = __('Pagination', 'pointly-booking') }) {
	const pages = Math.max(1, Math.ceil(total / Math.max(1, perPage)));
	const from = total === 0 ? 0 : (page - 1) * perPage + 1;
	const to = Math.min(total, page * perPage);
	return (
		<nav className="bp-pagination" aria-label={label}>
			<div className="bp-pagination__info">
				{/* translators: 1: first item number, 2: last item number, 3: total items. */}
				{sprintf(__('%1$d–%2$d of %3$d', 'pointly-booking'), from, to, total)}
			</div>
			{pages > 1 ? (
				<div className="bp-pagination__pages">
					<button type="button" className="bp-page-btn" disabled={page <= 1} onClick={() => onPageChange(page - 1)} aria-label={__('Previous page', 'pointly-booking')}>
						<Icon name="chevron-left" />
					</button>
					{pageList(page, pages).map((p, i) =>
						p === '…' ? (
							<span key={`e${i}`} className="bp-page-ellipsis" aria-hidden="true">
								…
							</span>
						) : (
							<button
								key={p}
								type="button"
								className="bp-page-btn"
								aria-current={p === page ? 'page' : undefined}
								/* translators: %d: page number. */
								aria-label={sprintf(__('Page %d', 'pointly-booking'), p)}
								onClick={() => onPageChange(p)}
							>
								{p}
							</button>
						)
					)}
					<button type="button" className="bp-page-btn" disabled={page >= pages} onClick={() => onPageChange(page + 1)} aria-label={__('Next page', 'pointly-booking')}>
						<Icon name="chevron-right" />
					</button>
				</div>
			) : null}
		</nav>
	);
}

/* ======================================================================
   Stepper / progress
   ====================================================================== */

/**
 * Vertical stepper. steps: [{ id, label, value? }]. Completed steps before
 * `current` can be revisited when `onStepClick` is given.
 */
export function Stepper({ steps, current, onStepClick, label = __('Progress', 'pointly-booking') }) {
	const currentIdx = steps.findIndex((s) => s.id === current);
	return (
		<nav aria-label={label}>
			<ol className="bp-stepper">
				{steps.map((s, i) => {
					const done = i < currentIdx;
					const isCurrent = i === currentIdx;
					const cls = ['bp-stepper__item', done ? 'is-done' : '', isCurrent ? 'is-current' : ''].filter(Boolean).join(' ');
					const inner = (
						<>
							<span className="bp-stepper__marker">{done ? <Icon name="check" /> : i + 1}</span>
							<span className="bp-stepper__label">
								{s.label}
								{s.value ? <span className="bp-stepper__value">{s.value}</span> : null}
							</span>
						</>
					);
					return (
						<li key={s.id}>
							{done && onStepClick ? (
								<button type="button" className={cls} onClick={() => onStepClick(s.id)}>
									{inner}
									<span className="bp-visually-hidden">{__('(completed, edit)', 'pointly-booking')}</span>
								</button>
							) : (
								<div className={cls} aria-current={isCurrent ? 'step' : undefined}>
									{inner}
								</div>
							)}
						</li>
					);
				})}
			</ol>
		</nav>
	);
}

export function StepDots({ total, current }) {
	return (
		<div className="bp-stepdots" aria-hidden="true">
			{Array.from({ length: total }).map((_, i) => (
				<span key={i} className={['bp-stepdots__dot', i < current ? 'is-done' : '', i === current ? 'is-current' : ''].filter(Boolean).join(' ')} />
			))}
		</div>
	);
}

export function ProgressBar({ value = 0, max = 100, label }) {
	const pct = Math.max(0, Math.min(100, (value / Math.max(1, max)) * 100));
	return (
		<div className="bp-progress" role="progressbar" aria-valuemin={0} aria-valuemax={max} aria-valuenow={value} aria-label={label}>
			<div className="bp-progress__bar" style={{ '--_value': `${pct}%` }} />
		</div>
	);
}
