// Settings → Announcement — the banner across the top of the website
// (2026-10-21, Doug's Point). Restaurant-only: the card exists for Menu-style
// workspaces (SettingsView `menuOnly`), and the server 404s everywhere else.
//
// Server: GET/PUT/DELETE /api/announcement → lib/announcement.js, which owns
// validation and decides what the site sees (dates, strip rule, id). The
// site reads GET /api/public/<slug>/announcement (docs/ANNOUNCEMENT.md).
// The photo uploads through the attachments API first (entity
// 'announcement', id 1); Save points the banner at it and clears old ones.

const ANN_STYLES = [
    ['strip',  'Strip',  'One line of text across the top of your site. Photo and button show only on Expand or Card.'],
    ['expand', 'Expand', 'A line across the top that opens into a card with the photo, message and button.'],
    ['card',   'Card',   'An open card under your main banner with the photo, message and button.'],
];
const ANN_LIMITS = { title: 80, body: 500, label: 30 };
// Same short list as Open Hours — only asked when hours have no time zone.
const ANN_ZONES = [['America/New_York', 'Eastern'], ['America/Chicago', 'Central'], ['America/Denver', 'Mountain'],
                   ['America/Phoenix', 'Arizona (no DST)'], ['America/Los_Angeles', 'Pacific'], ['America/Anchorage', 'Alaska'],
                   ['Pacific/Honolulu', 'Hawaii']];

const AnnouncementSection = ({ tenant }) => {
    const blank = { enabled: false, style: 'expand', title: '', body: '', photo_id: null,
                    button_label: '', button_url: '', starts_on: '', ends_on: '', timezone: '' };
    const toForm = (a) => a ? {
        enabled: !!a.enabled, style: a.style || 'expand', title: a.title || '', body: a.body || '',
        photo_id: a.photo_id || null, button_label: a.button ? a.button.label : '', button_url: a.button ? a.button.url : '',
        starts_on: a.starts_on || '', ends_on: a.ends_on || '', timezone: a.timezone || '',
    } : { ...blank };

    const [loaded, setLoaded]   = React.useState(null);   // GET payload, or { missing: true }
    const [form, setForm]       = React.useState(blank);
    const [saved, setSaved]     = React.useState(blank);
    const [live, setLive]       = React.useState(null);
    const [error, setError]     = React.useState('');
    const [notice, setNotice]   = React.useState('');
    const [busy, setBusy]       = React.useState(false);
    const [thumb, setThumb]     = React.useState(null);
    const [loadError, setLoadError] = React.useState('');

    const load = () => {
        setLoadError('');
        api.getAnnouncement().then(d => {
            const f = toForm(d.announcement);
            setLoaded(d); setForm(f); setSaved(f); setLive(d.live);
        }).catch(e => {
            if (/not found/i.test(e.message || '')) setLoaded({ missing: true });
            else setLoadError(e.message || 'Could not load the announcement.');
        });
    };
    React.useEffect(load, []);

    // Thumbnail: <img src> can't carry the auth header, so fetch an object URL.
    React.useEffect(() => {
        let url = null, gone = false;
        if (form.photo_id) {
            api.attachmentImageUrl(form.photo_id).then(u => { if (gone) URL.revokeObjectURL(u); else { url = u; setThumb(u); } })
                .catch(() => setThumb(null));
        } else setThumb(null);
        return () => { gone = true; if (url) URL.revokeObjectURL(url); };
    }, [form.photo_id]);

    if (loadError) return <LoadErrorBanner what="the announcement" onRetry={load} />;
    if (!loaded) return <div className="settings-section"><p style={{ color: 'var(--text-3)' }}>Loading…</p></div>;
    if (loaded.missing) {
        return (
            <div className="settings-section">
                <p style={{ color: 'var(--text-3)' }}>The website announcement is available for menu-style workspaces.</p>
            </div>
        );
    }

    const set = (k, v) => { setForm(f => ({ ...f, [k]: v })); setNotice(''); };
    const dirty = JSON.stringify(form) !== JSON.stringify(saved);
    const needsZone = !loaded.timezone_from_hours && (form.starts_on || form.ends_on);
    const rich = form.style !== 'strip';
    const chip = (on) => on ? { background: 'var(--accent, #3b82f6)', color: '#fff' } : {};
    const count = (v, max) => (
        <span style={{ fontSize: '0.75rem', color: v.trim().length > max ? 'var(--danger, #dc2626)' : 'var(--text-3)' }}>
            {v.trim().length} / {max}
        </span>
    );
    const prettyDate = (d) => new Date(d + 'T12:00:00').toLocaleDateString(undefined, { month: 'short', day: 'numeric' });

    // One line saying what the website shows right now (from the server's
    // own computation of the SAVED banner — never guessed client-side).
    const status = (() => {
        if (!saved.title) return { ok: false, text: 'Not set up yet' };
        if (live) return { ok: true, text: 'Showing on your website' };
        if (!saved.enabled) return { ok: false, text: 'Off' };
        if (saved.starts_on && saved.ends_on && saved.ends_on < new Date().toISOString().slice(0, 10)) return { ok: false, text: `Ended ${prettyDate(saved.ends_on)}` };
        if (saved.starts_on) return { ok: false, text: `Starts ${prettyDate(saved.starts_on)}` };
        return { ok: false, text: `Ended ${prettyDate(saved.ends_on)}` };
    })();

    const upload = async (e) => {
        const file = e.target.files && e.target.files[0];
        e.target.value = '';
        if (!file) return;
        if (!['image/jpeg', 'image/png', 'image/webp'].includes(file.type)) { setError('Photos must be JPEG, PNG or WebP.'); return; }
        setBusy(true); setError('');
        try {
            const att = await api.uploadAttachment('announcement', 1, file);
            set('photo_id', att.id);
        } catch (err) { setError(err.message || 'Upload failed.'); }
        setBusy(false);
    };

    const save = async () => {
        setBusy(true); setError(''); setNotice('');
        try {
            const d = await api.saveAnnouncement({
                enabled: form.enabled, style: form.style, title: form.title, body: form.body,
                photo_id: form.photo_id,
                button: form.button_label || form.button_url ? { label: form.button_label, url: form.button_url } : null,
                starts_on: form.starts_on || null, ends_on: form.ends_on || null,
                timezone: needsZone ? (form.timezone || null) : null,
            });
            const f = toForm(d.announcement);
            setForm(f); setSaved(f); setLive(d.live);
            // Say WHY it isn't showing right where the owner is looking — the
            // status line sits at the top of the card, often scrolled away
            // (found live 2026-10-21: a future start date read as "broken").
            const today = new Date().toISOString().slice(0, 10);
            setNotice(d.live ? 'Saved — your website shows it within a minute.'
                : !f.enabled ? 'Saved. It\'s switched off, so your website isn\'t showing it.'
                : f.starts_on && f.starts_on > today ? `Saved. It starts showing on ${prettyDate(f.starts_on)}.`
                : f.ends_on && f.ends_on < today ? `Saved. Its stop date (${prettyDate(f.ends_on)}) has passed, so it isn't showing.`
                : 'Saved.');
        } catch (err) { setError(err.message || 'Could not save.'); }
        setBusy(false);
    };

    const remove = async () => {
        const yes = await confirmAction({
            title: 'Remove the announcement?',
            message: 'The banner and its photo are deleted. Your website stops showing it within a minute.',
            confirmLabel: 'Remove', danger: true,
        });
        if (!yes) return;
        setBusy(true); setError('');
        try {
            await api.clearAnnouncement();
            setForm({ ...blank }); setSaved({ ...blank }); setLive(null); setNotice('Removed.');
        } catch (err) { setError(err.message || 'Could not remove it.'); }
        setBusy(false);
    };

    return (
        <div className="settings-section">
            <p style={{ fontSize: '0.875rem', color: status.ok ? 'var(--success, #16a34a)' : 'var(--text-3)', margin: '0 0 1rem' }}>
                <i className={`fas ${status.ok ? 'fa-circle' : 'fa-circle-notch'}`} style={{ marginRight: '0.4rem', fontSize: '0.7rem' }}></i>{status.text}
            </p>

            <div className="form-group">
                <label className="form-label">Show on my website</label>
                <div className="tag-filter-row" style={{ margin: 0 }}>
                    <span className="tag-pill tag-filter-chip" style={chip(form.enabled)} onClick={() => set('enabled', true)}>On</span>
                    <span className="tag-pill tag-filter-chip" style={chip(!form.enabled)} onClick={() => set('enabled', false)}>Off</span>
                </div>
            </div>

            <div className="form-group">
                <label className="form-label">Style</label>
                <div className="tag-filter-row" style={{ margin: 0 }}>
                    {ANN_STYLES.map(([k, label]) => (
                        <span key={k} className="tag-pill tag-filter-chip" style={chip(form.style === k)} onClick={() => set('style', k)}>{label}</span>
                    ))}
                </div>
                <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '0.4rem 0 0' }}>
                    {ANN_STYLES.find(s => s[0] === form.style)[2]}
                </p>
            </div>

            <div className="form-group" style={{ maxWidth: 640 }}>
                <label className="form-label" style={{ display: 'flex', justifyContent: 'space-between' }}>Headline {count(form.title, ANN_LIMITS.title)}</label>
                <input className="form-input" value={form.title} onChange={e => set('title', e.target.value)}
                       placeholder="e.g. Pumpkin pie pizza is back" />
            </div>

            <div className="form-group" style={{ maxWidth: 640 }}>
                <label className="form-label" style={{ display: 'flex', justifyContent: 'space-between' }}>
                    <span>Message <span style={{ fontWeight: 400, color: 'var(--text-3)' }}>(optional{rich ? '' : ' — Strip shows the headline only'})</span></span>
                    {count(form.body, ANN_LIMITS.body)}
                </label>
                <textarea className="form-input" rows={3} value={form.body} onChange={e => set('body', e.target.value)} />
            </div>

            <div style={{ opacity: rich ? 1 : 0.55 }}>
                <div className="form-group">
                    <label className="form-label">Photo <span style={{ fontWeight: 400, color: 'var(--text-3)' }}>(optional)</span></label>
                    <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', flexWrap: 'wrap' }}>
                        {thumb && <img src={thumb} alt="" style={{ width: 96, height: 64, objectFit: 'cover', borderRadius: 6, border: '1px solid var(--border)' }} />}
                        <label className="btn btn-secondary btn-small" style={{ cursor: busy ? 'default' : 'pointer' }}>
                            <i className="fas fa-image"></i> {form.photo_id ? 'Replace photo' : 'Add photo'}
                            <input type="file" accept="image/jpeg,image/png,image/webp" hidden disabled={busy} onChange={upload} />
                        </label>
                        {form.photo_id && (
                            <button type="button" className="btn-link" onClick={() => set('photo_id', null)}>Remove photo</button>
                        )}
                    </div>
                </div>

                <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', maxWidth: 640 }}>
                    <div className="form-group" style={{ flex: '1 1 180px' }}>
                        <label className="form-label">Button text</label>
                        <input className="form-input" value={form.button_label} maxLength={ANN_LIMITS.label}
                               onChange={e => set('button_label', e.target.value)} placeholder="e.g. See the menu" />
                    </div>
                    <div className="form-group" style={{ flex: '2 1 260px' }}>
                        <label className="form-label">Button link</label>
                        <input className="form-input" value={form.button_url} spellCheck={false}
                               onChange={e => set('button_url', e.target.value)} placeholder="/#menu" />
                    </div>
                </div>
                <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '-0.5rem 0 1rem', maxWidth: 640 }}>
                    A spot on your site (<code>/#menu</code>), a web address (<code>https://…</code>), a phone number
                    (<code>tel:+15555550123</code>) or an email (<code>mailto:orders@example.com</code>). Leave both blank for no button.
                </p>
            </div>

            <div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', maxWidth: 420 }}>
                <div className="form-group" style={{ flex: 1 }}>
                    <label className="form-label">Start showing</label>
                    <input type="date" className="form-input" value={form.starts_on} onChange={e => set('starts_on', e.target.value)} />
                </div>
                <div className="form-group" style={{ flex: 1 }}>
                    <label className="form-label">Stop after</label>
                    <input type="date" className="form-input" value={form.ends_on} onChange={e => set('ends_on', e.target.value)} />
                </div>
            </div>
            <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '-0.5rem 0 1rem' }}>
                Optional. Both days count. Leave the end blank to keep it up until you switch it off.
            </p>

            {needsZone && (
                <div className="form-group" style={{ maxWidth: 420 }}>
                    <label className="form-label">Time zone for these dates</label>
                    <select className="form-input" value={form.timezone} onChange={e => set('timezone', e.target.value)}>
                        <option value="">Pick one…</option>
                        {ANN_ZONES.map(([tz, label]) => <option key={tz} value={tz}>{label} — {tz}</option>)}
                    </select>
                    <p style={{ fontSize: '0.8125rem', color: 'var(--text-3)', margin: '0.4rem 0 0' }}>
                        Asked here because Open Hours has no time zone yet. Set your hours and this uses theirs.
                    </p>
                </div>
            )}

            {error && <p style={{ color: 'var(--danger, #dc2626)', fontSize: '0.875rem' }}>{error}</p>}
            {notice && <p style={{ color: 'var(--success, #16a34a)', fontSize: '0.875rem' }}>{notice}</p>}

            <div className="btn-group">
                <button type="button" className="btn btn-primary" disabled={busy || !dirty} onClick={save}>
                    {busy ? <><i className="fas fa-spinner fa-spin"></i> Saving…</> : <><i className="fas fa-check"></i> Save</>}
                </button>
                {saved.title && (
                    <button type="button" className="btn btn-secondary" disabled={busy} onClick={remove}>
                        <i className="fas fa-trash"></i> Remove announcement
                    </button>
                )}
            </div>
        </div>
    );
};
