import React, { useEffect, useMemo } from 'react';
import { __ } from '@wordpress/i18n';
import { Alert, Field, Input, Select, Skeleton, Switch, useToast } from '../../../shared/ui';
import api from '../../core/api';
import useAsync from '../../core/useAsync';
import useForm from '../../core/useForm';
import { useUnsavedChanges } from '../../core/AdminContext';
import CURRENCIES from '../../core/currencies';
import { formatMoney } from '../../core/format';
import { FormGrid, Page, PageHeader, SaveBar, Section } from '../../ui/page';

const DAYS = () => [
	{ i: 1, label: __('Monday', 'pointly-booking') },
	{ i: 2, label: __('Tuesday', 'pointly-booking') },
	{ i: 3, label: __('Wednesday', 'pointly-booking') },
	{ i: 4, label: __('Thursday', 'pointly-booking') },
	{ i: 5, label: __('Friday', 'pointly-booking') },
	{ i: 6, label: __('Saturday', 'pointly-booking') },
	{ i: 0, label: __('Sunday', 'pointly-booking') },
];

const first = (s, keys, fallback) => {
	for (const k of keys) if (Object.prototype.hasOwnProperty.call(s, k) && s[k] !== '' && s[k] !== null && s[k] !== undefined) return s[k];
	return fallback;
};

/** "09:00-17:00" -> { open: true, start, end } */
const parseDay = (txt) => {
	const m = /^(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})$/.exec(String(txt || '').trim());
	return m ? { open: true, start: m[1], end: m[2] } : { open: false, start: '09:00', end: '17:00' };
};

function toForm(s) {
	const days = {};
	DAYS().forEach(({ i }) => (days[i] = parseDay(s[`pointlybooking_schedule_${i}`])));
	return {
		currency: String(first(s, ['currency', 'pointlybooking_default_currency'], 'USD')).toUpperCase(),
		currency_position: first(s, ['currency_position', 'pointlybooking_currency_position'], 'before'),
		slot_interval_minutes: Number(s.slot_interval_minutes) || 15,
		future_days_limit: Number(s.pointlybooking_future_days_limit) || 60,
		default_status: s.pointlybooking_default_booking_status || 'pending',
		open_time: s.pointlybooking_open_time || '09:00',
		close_time: s.pointlybooking_close_time || '17:00',
		breaks: s.pointlybooking_breaks !== undefined ? s.pointlybooking_breaks : '12:00-13:00',
		brand_color: s.brand_color || '',
		days,
	};
}

function fromForm(f, base) {
	const out = { ...base };
	out.currency = f.currency;
	out.currency_position = f.currency_position;
	out.slot_interval_minutes = Number(f.slot_interval_minutes) || 15;
	out.pointlybooking_future_days_limit = Number(f.future_days_limit) || 60;
	out.pointlybooking_default_booking_status = f.default_status;
	out.pointlybooking_open_time = f.open_time;
	out.pointlybooking_close_time = f.close_time;
	out.pointlybooking_breaks = f.breaks;
	out.brand_color = f.brand_color;
	DAYS().forEach(({ i }) => {
		const d = f.days[i];
		out[`pointlybooking_schedule_${i}`] = d.open ? `${d.start}-${d.end}` : '';
	});
	return out;
}

export default function GeneralTab() {
	const toast = useToast();
	const settings = useAsync(() => api.get('/admin/settings'), [], { keepPrevious: false });
	const form = useForm(toForm({}));
	const [saving, setSaving] = React.useState(false);
	const [error, setError] = React.useState('');
	useUnsavedChanges(form.dirty && !saving, 'settings');

	useEffect(() => {
		if (settings.data) form.load(toForm(settings.data));
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [settings.data]);

	const v = form.values;
	const set = form.set;
	const preview = useMemo(() => formatMoney(12.5, v.currency), [v.currency]);

	const save = async () => {
		setError('');
		if (v.brand_color && !/^#[0-9a-fA-F]{6}$/.test(v.brand_color)) return setError(__('Brand colour must look like #2563eb.', 'pointly-booking'));
		if (Object.values(v.days).some((d) => d.open && d.end <= d.start)) return setError(__('Closing time must be after opening time.', 'pointly-booking'));
		setSaving(true);
		const sent = v;
		try {
			await api.post('/admin/settings', fromForm(sent, settings.data || {}));
			form.markSaved(sent);
			toast.success(__('Settings saved', 'pointly-booking'));
		} catch (e) {
			setError(e.message);
		} finally {
			setSaving(false);
		}
	};

	const setDay = (i, patch) => set('days', { ...v.days, [i]: { ...v.days[i], ...patch } });

	return (
		<Page>
			<PageHeader title={__('General settings', 'pointly-booking')} subtitle={__('Booking rules, currency and default opening hours.', 'pointly-booking')} />
			{settings.error ? <Alert tone="danger">{settings.error}</Alert> : null}
			{error ? <Alert tone="danger" live>{error}</Alert> : null}
			{settings.loading && !settings.data ? (
				<div className="bp-stack">
					<Skeleton height={160} block />
					<Skeleton height={220} block />
				</div>
			) : (
				<>
					<Section title={__('Booking rules', 'pointly-booking')}>
						<FormGrid cols={3}>
							<Field label={__('Time between start times', 'pointly-booking')} hint={__('How often a booking can start, in minutes.', 'pointly-booking')}>
								<Select value={v.slot_interval_minutes} onChange={(e) => set('slot_interval_minutes', Number(e.target.value))} options={[5, 10, 15, 20, 30, 45, 60].map((n) => ({ value: n, label: `${n} ${__('min', 'pointly-booking')}` }))} />
							</Field>
							<Field label={__('Booking window (days ahead)', 'pointly-booking')} hint={__('Customers can book up to this many days in advance.', 'pointly-booking')}>
								<Input type="number" min="1" max="365" value={v.future_days_limit} onChange={(e) => set('future_days_limit', e.target.value)} />
							</Field>
							<Field label={__('Status of new bookings', 'pointly-booking')} hint={__('“Pending” waits for your approval.', 'pointly-booking')}>
								<Select
									value={v.default_status}
									onChange={(e) => set('default_status', e.target.value)}
									options={[
										{ value: 'confirmed', label: __('Confirmed automatically', 'pointly-booking') },
										{ value: 'pending', label: __('Pending approval', 'pointly-booking') },
									]}
								/>
							</Field>
						</FormGrid>
					</Section>

					<Section title={__('Currency', 'pointly-booking')}>
						<FormGrid cols={3}>
							<Field label={__('Currency', 'pointly-booking')}>
								<Select value={v.currency} onChange={(e) => set('currency', e.target.value)} options={CURRENCIES.map((c) => ({ value: c.code, label: `${c.code} — ${c.name}` }))} />
							</Field>
							<Field label={__('Symbol position', 'pointly-booking')}>
								<Select
									value={v.currency_position}
									onChange={(e) => set('currency_position', e.target.value)}
									options={[
										{ value: 'before', label: __('Before the amount ($10)', 'pointly-booking') },
										{ value: 'after', label: __('After the amount (10$)', 'pointly-booking') },
									]}
								/>
							</Field>
							<Field label={__('Preview', 'pointly-booking')}>
								<div className="bp-settings-preview" aria-live="polite">{preview}</div>
							</Field>
						</FormGrid>
					</Section>

					<Section title={__('Default opening hours', 'pointly-booking')} description={__('Used when neither the Schedule page nor a staff member defines hours. Set detailed hours and breaks on the Schedule page.', 'pointly-booking')}>
						<div className="bp-hours" role="group" aria-label={__('Weekly hours', 'pointly-booking')}>
							{DAYS().map((d) => {
								const row = v.days[d.i];
								return (
									<div className="bp-hours__row" key={d.i}>
										<Switch label={d.label} checked={row.open} onChange={(open) => setDay(d.i, { open })} />
										{row.open ? (
											<div className="bp-hours__times">
												<Input type="time" step="300" value={row.start} onChange={(e) => setDay(d.i, { start: e.target.value })} aria-label={`${d.label} — ${__('opens', 'pointly-booking')}`} />
												<span aria-hidden="true">–</span>
												<Input type="time" step="300" value={row.end} onChange={(e) => setDay(d.i, { end: e.target.value })} aria-label={`${d.label} — ${__('closes', 'pointly-booking')}`} />
											</div>
										) : (
											<span className="bp-text-muted">{__('Closed', 'pointly-booking')}</span>
										)}
									</div>
								);
							})}
						</div>
						<FormGrid cols={3}>
							<Field label={__('Daily breaks', 'pointly-booking')} hint={__('Comma-separated, e.g. 12:00-13:00,15:00-15:15', 'pointly-booking')}>
								<Input value={v.breaks} onChange={(e) => set('breaks', e.target.value)} placeholder="12:00-13:00" dir="ltr" />
							</Field>
						</FormGrid>
					</Section>

					<Section title={__('Appearance', 'pointly-booking')} description={__('Brand colour for the admin and the booking form. More options are in the Form designer.', 'pointly-booking')}>
						<FormGrid cols={3}>
							<Field label={__('Brand colour', 'pointly-booking')} hint={__('Leave empty for the default blue.', 'pointly-booking')}>
								<div className="bp-colorfield">
									<input type="color" className="bp-colorfield__swatch" value={/^#[0-9a-fA-F]{6}$/.test(v.brand_color) ? v.brand_color : '#2563eb'} onChange={(e) => set('brand_color', e.target.value)} aria-label={__('Pick a colour', 'pointly-booking')} />
									<Input value={v.brand_color} onChange={(e) => set('brand_color', e.target.value)} placeholder="#2563eb" dir="ltr" />
								</div>
							</Field>
						</FormGrid>
					</Section>
				</>
			)}
			<SaveBar dirty={form.dirty} saving={saving} onSave={save} onDiscard={form.reset} error={error && !form.dirty ? error : ''} />
		</Page>
	);
}
