// Karaway Admin — wired to the real /api/* endpoints.
// Auth is enforced at the edge by Cloudflare Access; this UI just shows/edits content.

const { useState: useStateA, useEffect: useEffectA, useCallback: useCallbackA } = React;

// ───────────────────────────────────────────── API helpers
const apiGet = (path) => fetch(path, { credentials: 'include' }).then(r => r.ok ? r.json() : Promise.reject(r));
const apiSend = (path, method, body) => fetch(path, {
  method,
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: body ? JSON.stringify(body) : undefined,
}).then(async r => {
  if (!r.ok) throw new Error(`${method} ${path}: ${r.status} ${await r.text()}`);
  return r.json();
});
const apiPost = (p, b) => apiSend(p, 'POST', b);
const apiPut  = (p, b) => apiSend(p, 'PUT', b);
const apiDel  = (p) => apiSend(p, 'DELETE', null);

const useRemote = (path) => {
  const [data, setData] = useStateA(null);
  const [loading, setLoading] = useStateA(true);
  const [error, setError] = useStateA(null);
  const reload = useCallbackA(() => {
    setLoading(true);
    apiGet(path).then(setData).catch(e => setError(String(e))).finally(() => setLoading(false));
  }, [path]);
  useEffectA(() => { reload(); }, [reload]);
  return { data, loading, error, reload };
};

// Show a transient toast
const useToast = () => {
  const [msg, setMsg] = useStateA(null);
  const show = (text, kind = 'ok') => {
    setMsg({ text, kind });
    setTimeout(() => setMsg(null), 2600);
  };
  const el = msg ? (
    <div style={{position: 'fixed', bottom: 28, right: 28, padding: '12px 20px', background: msg.kind === 'ok' ? 'var(--ocean)' : '#a0403a', color: 'var(--bg)', borderRadius: 4, zIndex: 500, fontSize: 13, letterSpacing: '0.04em', boxShadow: '0 12px 40px rgba(15,35,38,0.25)'}}>{msg.text}</div>
  ) : null;
  return { show, el };
};

// ───────────────────────────────────────────── Login (Access-protected edge)
const AdminLogin = () => (
  <div className="login-wrap">
    <div className="login-visual">
      <img src={IMAGES.hero} alt="" style={{width: '100%', height: '100%', objectFit: 'cover', opacity: 0.8}}/>
      <div style={{position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(15,35,38,0.3) 0%, rgba(15,35,38,0.85) 100%)'}}/>
      <div style={{position: 'absolute', bottom: 48, left: 48, right: 48, color: 'var(--bg)'}}>
        <div style={{fontSize: 11, letterSpacing: '0.25em', textTransform: 'uppercase', color: 'rgba(250,246,239,0.6)', marginBottom: 12}}>Villa</div>
        <div style={{fontFamily: 'var(--serif)', fontSize: 48, fontWeight: 300, lineHeight: 1.05, marginBottom: 24}}>Karaway<br/>Admin.</div>
        <p style={{fontSize: 14, color: 'rgba(250,246,239,0.75)', maxWidth: 360, lineHeight: 1.6}}>Managed by Cloudflare Access. If the admin doesn't load, you are not signed in — follow the Access prompt.</p>
      </div>
    </div>
    <div className="login-form-wrap">
      <div className="login-form">
        <div style={{marginBottom: 40}}>
          <div className="eyebrow" style={{marginBottom: 12}}>Sign In</div>
          <h1 className="display" style={{fontSize: 40}}>Welcome back.</h1>
        </div>
        <p className="body" style={{marginBottom: 24}}>This page is protected by Cloudflare Access. You'll receive a one-time login email when you visit.</p>
        <a className="btn btn-primary" style={{width: '100%', justifyContent: 'center'}} href="/admin">Continue to Admin</a>
        <p className="small" style={{color: 'var(--muted)', textAlign: 'center', marginTop: 32}}>Secured via Cloudflare Access</p>
      </div>
    </div>
  </div>
);

// ───────────────────────────────────────────── Sidebar
const AdminSidebar = ({ view, setView }) => {
  const Item = ({ id, icon, label }) => (
    <button className={`admin-nav-item ${view === id ? 'active' : ''}`} onClick={() => setView(id)}>
      <Icon name={icon} size={16}/><span>{label}</span>
    </button>
  );
  return (
    <aside className="admin-sidebar">
      <div className="admin-sidebar-brand"><div className="mark">Villa</div><div className="brand">Karaway</div></div>
      <div className="admin-nav-section">
        <div className="admin-nav-heading">Content</div>
        <Item id="pages"      icon="file"     label="Pages"/>
        <Item id="navigation" icon="link"     label="Navigation"/>
        <Item id="menu"       icon="utensils" label="Food Menu"/>
        <Item id="gallery"    icon="image"    label="Gallery"/>
        <Item id="widgets"    icon="settings" label="Widgets"/>
        <Item id="reviews"    icon="star"     label="Reviews"/>
        <Item id="messages"   icon="mail"     label="Inbox"/>
      </div>
      <div className="admin-nav-section">
        <div className="admin-nav-heading">System</div>
        <Item id="settings"   icon="settings" label="Settings"/>
      </div>
      <div style={{marginTop: 'auto', padding: '16px 12px', borderTop: '1px solid rgba(250,246,239,0.08)'}}>
        <a className="admin-nav-item" href="/cdn-cgi/access/logout"><Icon name="logout" size={16}/><span>Sign out</span></a>
      </div>
    </aside>
  );
};

// ───────────────────────────────────────────── PAGES
const AdminPages = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/pages');
  const pages = data?.pages || [];
  const [selected, setSelected] = useStateA(null);
  const [draft, setDraft] = useStateA(null);
  const [saving, setSaving] = useStateA(false);

  useEffectA(() => {
    if (!selected && pages.length) setSelected(pages[0].id);
  }, [selected, pages]);

  useEffectA(() => {
    const p = pages.find(x => x.id === selected);
    if (p) setDraft({ ...p });
  }, [selected, pages]);

  const save = async () => {
    if (!draft?.id) return;
    setSaving(true);
    try {
      await apiPut('/api/pages', draft);
      toast.show('Page saved');
      reload();
    } catch (e) {
      toast.show(String(e), 'err');
    } finally {
      setSaving(false);
    }
  };

  const addPage = async () => {
    const title = prompt('New page title?');
    if (!title) return;
    const slug = '/' + title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
    try {
      const r = await apiPost('/api/pages', { title, slug, sort_order: pages.length + 1 });
      toast.show('Page created');
      setSelected(r.id);
      reload();
    } catch (e) { toast.show(String(e), 'err'); }
  };

  const delPage = async () => {
    if (!selected) return;
    if (!confirm(`Delete "${draft?.title}"?`)) return;
    try {
      await apiDel(`/api/pages?id=${encodeURIComponent(selected)}`);
      toast.show('Deleted');
      setSelected(null);
      reload();
    } catch (e) { toast.show(String(e), 'err'); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <div style={{display: 'grid', gridTemplateColumns: '280px 1fr', gap: 24}}>
      <div className="admin-card" style={{padding: 0, height: 'fit-content'}}>
        <div style={{padding: '16px 20px', borderBottom: '1px solid #e8e4d9', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
          <div className="eyebrow">All Pages</div>
          <button className="admin-btn admin-btn-ghost" style={{padding: 6}} onClick={addPage}><Icon name="plus" size={16}/></button>
        </div>
        {pages.map(p => (
          <button key={p.id} onClick={() => setSelected(p.id)} style={{display: 'block', width: '100%', padding: '14px 20px', textAlign: 'left', borderBottom: '1px solid #f5f1e3', background: selected === p.id ? '#faf8f2' : 'transparent', borderLeft: selected === p.id ? '2px solid var(--terracotta)' : '2px solid transparent'}}>
            <div style={{fontWeight: 500, fontSize: 14, marginBottom: 4}}>{p.title}</div>
            <div style={{display: 'flex', justifyContent: 'space-between', fontSize: 11}}>
              <span className={`badge badge-${p.published ? 'green' : 'amber'}`}>{p.published ? 'published' : 'draft'}</span>
              <span style={{color: 'var(--muted)', fontFamily: 'var(--mono)'}}>{p.slug}</span>
            </div>
          </button>
        ))}
      </div>
      <div className="admin-card">
        {draft ? (
          <>
            <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24}}>
              <div><div className="eyebrow" style={{marginBottom: 6}}>Editing</div><h3 className="serif" style={{fontSize: 24, fontWeight: 400}}>{draft.title}</h3></div>
              <div style={{display: 'flex', gap: 8}}>
                <a className="admin-btn admin-btn-outline" href={draft.slug} target="_blank" rel="noreferrer"><Icon name="eye" size={14}/>Preview</a>
                <button className="admin-btn admin-btn-ghost" onClick={delPage} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/></button>
                <button className="admin-btn admin-btn-primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save & Publish'}</button>
              </div>
            </div>
            <div className="form-grid-2">
              <div className="form-row"><label className="label">Page title</label><input className="input" value={draft.title || ''} onChange={e => setDraft({...draft, title: e.target.value})}/></div>
              <div className="form-row"><label className="label">URL slug</label><input className="input" value={draft.slug || ''} onChange={e => setDraft({...draft, slug: e.target.value})}/></div>
            </div>
            <div className="form-row"><label className="label">Hero headline</label><input className="input" value={draft.hero_headline || ''} onChange={e => setDraft({...draft, hero_headline: e.target.value})}/></div>
            <div className="form-row"><label className="label">Hero image URL / R2 path</label><input className="input" value={draft.hero_image || ''} onChange={e => setDraft({...draft, hero_image: e.target.value})} placeholder="/media/gallery/xxx.jpg or https://…"/></div>
            <div className="form-row">
              <label className="label">Body content (HTML)</label>
              <textarea className="textarea" rows={12} value={draft.body_html || ''} onChange={e => setDraft({...draft, body_html: e.target.value})} style={{fontFamily: 'var(--mono)', fontSize: 12}}/>
              <p className="small" style={{color: 'var(--muted)', marginTop: 6}}>Allowed: &lt;h2&gt;–&lt;h4&gt;, &lt;p&gt;, &lt;a&gt;, &lt;strong&gt;, &lt;em&gt;, &lt;ul&gt;, &lt;ol&gt;, &lt;li&gt;, &lt;blockquote&gt;. Scripts stripped.</p>
            </div>
            <label style={{display: 'flex', gap: 8, alignItems: 'center', fontSize: 13}}>
              <input type="checkbox" checked={!!draft.published} onChange={e => setDraft({...draft, published: e.target.checked ? 1 : 0})}/> Published
            </label>
          </>
        ) : <div style={{color: 'var(--muted)'}}>Select a page to edit.</div>}
      </div>
    </div>
  );
};

// ───────────────────────────────────────────── NAVIGATION
const AdminNavigation = ({ toast, pages }) => {
  const { data, loading, reload } = useRemote('/api/nav');
  const [items, setItems] = useStateA([]);
  const [editing, setEditing] = useStateA(null);
  const [saving, setSaving] = useStateA(false);

  useEffectA(() => { if (data?.nav) setItems(data.nav); }, [data]);

  const upd = (id, patch) => setItems(items.map(i => i.id === id ? {...i, ...patch} : i));
  const add = () => setItems([...items, { id: 'nav_' + Date.now(), label: 'New link', type: 'external', target: 'https://', new_tab: 1, sort_order: items.length + 1 }]);
  const remove = (id) => setItems(items.filter(i => i.id !== id));
  const move = (idx, dir) => {
    const arr = [...items];
    const to = idx + dir;
    if (to < 0 || to >= arr.length) return;
    [arr[idx], arr[to]] = [arr[to], arr[idx]];
    arr.forEach((it, i) => { it.sort_order = i + 1; });
    setItems(arr);
  };

  const save = async () => {
    setSaving(true);
    try {
      await apiPut('/api/nav', { nav: items.map((it, i) => ({...it, sort_order: i + 1})) });
      toast.show('Navigation saved');
      reload();
    } catch (e) { toast.show(String(e), 'err'); } finally { setSaving(false); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <div style={{maxWidth: 880}}>
      <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16}}>
        <p style={{color: 'var(--ink-soft)', fontSize: 14, margin: 0}}>Main nav. Link to internal pages or external URLs.</p>
        <button className="admin-btn admin-btn-primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save changes'}</button>
      </div>
      <div className="admin-card" style={{padding: 0}}>
        {items.map((it, idx) => (
          <div key={it.id}>
            <div style={{padding: 16, borderBottom: idx < items.length - 1 || editing === it.id ? '1px solid #f0ecdf' : 'none', display: 'flex', alignItems: 'center', gap: 16}}>
              <div style={{display: 'flex', flexDirection: 'column'}}>
                <button onClick={() => move(idx, -1)} disabled={idx === 0} style={{padding: 2, fontSize: 10, opacity: idx === 0 ? 0.3 : 1}}>▲</button>
                <button onClick={() => move(idx, 1)} disabled={idx === items.length - 1} style={{padding: 2, fontSize: 10, opacity: idx === items.length - 1 ? 0.3 : 1}}>▼</button>
              </div>
              <div style={{flex: 1}}>
                <div style={{fontWeight: 500, fontSize: 14, marginBottom: 4}}>{it.label}</div>
                <div style={{fontSize: 12, color: 'var(--ink-soft)', fontFamily: 'var(--mono)'}}>
                  {it.type === 'internal' ? `→ /${it.target === 'home' ? '' : it.target}` : `↗ ${(it.target || '').slice(0, 52)}`}
                  {it.new_tab ? <span style={{marginLeft: 8, color: 'var(--muted)'}}>(new tab)</span> : null}
                </div>
              </div>
              <span className={`badge badge-${it.type === 'internal' ? 'green' : 'amber'}`}>{it.type}</span>
              <button className="admin-btn admin-btn-outline" onClick={() => setEditing(editing === it.id ? null : it.id)}><Icon name="edit" size={14}/>{editing === it.id ? 'Close' : 'Edit'}</button>
              <button className="admin-btn admin-btn-ghost" onClick={() => remove(it.id)} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/></button>
            </div>
            {editing === it.id && (
              <div style={{padding: 20, background: '#faf8f2', borderBottom: idx < items.length - 1 ? '1px solid #f0ecdf' : 'none'}}>
                <div className="form-grid-2">
                  <div className="form-row"><label className="label">Link label</label><input className="input" value={it.label || ''} onChange={e => upd(it.id, {label: e.target.value})}/></div>
                  <div className="form-row"><label className="label">Link type</label>
                    <select className="select" value={it.type} onChange={e => upd(it.id, {type: e.target.value, target: e.target.value === 'internal' ? (pages[0]?.id || 'home') : 'https://', new_tab: e.target.value === 'external' ? 1 : 0})}>
                      <option value="internal">Internal page</option>
                      <option value="external">External URL</option>
                    </select>
                  </div>
                </div>
                {it.type === 'internal' ? (
                  <div className="form-row"><label className="label">Page</label>
                    <select className="select" value={it.target} onChange={e => upd(it.id, {target: e.target.value})}>
                      {pages.map(p => <option key={p.id} value={p.id}>{p.title} ({p.slug})</option>)}
                    </select>
                  </div>
                ) : (
                  <div className="form-row"><label className="label">URL</label><input className="input" value={it.target} onChange={e => upd(it.id, {target: e.target.value})} placeholder="https://"/></div>
                )}
                <label style={{display: 'flex', gap: 8, alignItems: 'center', fontSize: 13}}>
                  <input type="checkbox" checked={!!it.new_tab} onChange={e => upd(it.id, {new_tab: e.target.checked ? 1 : 0})}/>
                  Open in new tab
                </label>
              </div>
            )}
          </div>
        ))}
      </div>
      <button className="admin-btn admin-btn-primary" onClick={add} style={{marginTop: 16}}><Icon name="plus" size={14}/>Add menu link</button>
    </div>
  );
};

// ───────────────────────────────────────────── MENU CARDS
const AdminMenu = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/menu');
  const [items, setItems] = useStateA([]);
  const [saving, setSaving] = useStateA(false);
  useEffectA(() => { if (data?.menu_cards) setItems(data.menu_cards); }, [data]);

  const upd = (id, patch) => setItems(items.map(i => i.id === id ? {...i, ...patch} : i));
  const remove = (id) => setItems(items.filter(i => i.id !== id));
  const add = () => setItems([...items, { id: 'mc_' + Date.now(), label: 'New menu', url: 'https://', enabled: 0, sort_order: items.length + 1 }]);
  const save = async () => {
    setSaving(true);
    try {
      await apiPut('/api/menu', { menu_cards: items });
      toast.show('Menu saved'); reload();
    } catch (e) { toast.show(String(e), 'err'); } finally { setSaving(false); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <div style={{maxWidth: 760}}>
      <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16}}>
        <p style={{color: 'var(--ink-soft)', fontSize: 14, margin: 0}}>External PDF link cards on the Menu page.</p>
        <button className="admin-btn admin-btn-primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save'}</button>
      </div>
      <div className="stack">
        {items.map(it => (
          <div key={it.id} className="admin-card">
            <div className="form-grid-2">
              <div className="form-row"><label className="label">Menu name</label><input className="input" value={it.label || ''} onChange={e => upd(it.id, {label: e.target.value})}/></div>
              <div className="form-row"><label className="label">Status</label>
                <label style={{display: 'flex', gap: 8, alignItems: 'center', fontSize: 13, padding: '14px 0'}}>
                  <input type="checkbox" checked={!!it.enabled} onChange={e => upd(it.id, {enabled: e.target.checked ? 1 : 0})}/> Visible on menu page
                </label>
              </div>
            </div>
            <div className="form-row"><label className="label">PDF / external URL</label><input className="input" value={it.url || ''} onChange={e => upd(it.id, {url: e.target.value})}/></div>
            <button className="admin-btn admin-btn-ghost" onClick={() => remove(it.id)} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/>Remove</button>
          </div>
        ))}
      </div>
      <button className="admin-btn admin-btn-primary" onClick={add} style={{marginTop: 16, background: 'transparent', color: 'var(--ocean)', border: '1px solid var(--ocean)'}}><Icon name="plus" size={14}/>Add menu card</button>
    </div>
  );
};

// ───────────────────────────────────────────── GALLERY
const AdminGallery = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/gallery');
  const images = data?.gallery || [];
  const [uploading, setUploading] = useStateA(false);

  const upload = async (files) => {
    setUploading(true);
    try {
      for (const f of files) {
        const fd = new FormData();
        fd.append('file', f);
        const r = await fetch('/api/upload', { method: 'POST', credentials: 'include', body: fd });
        if (!r.ok) throw new Error(`Upload failed: ${await r.text()}`);
      }
      toast.show(`Uploaded ${files.length} image${files.length > 1 ? 's' : ''}`);
      reload();
    } catch (e) { toast.show(String(e), 'err'); } finally { setUploading(false); }
  };

  const remove = async (id) => {
    if (!confirm('Delete this image?')) return;
    try { await apiDel(`/api/gallery?id=${encodeURIComponent(id)}`); toast.show('Deleted'); reload(); }
    catch (e) { toast.show(String(e), 'err'); }
  };

  const move = async (id, dir) => {
    const idx = images.findIndex(i => i.id === id);
    const to = idx + dir;
    if (to < 0 || to >= images.length) return;
    const a = images[idx], b = images[to];
    try {
      await apiPut('/api/gallery', { updates: [{ id: a.id, sort_order: b.sort_order }, { id: b.id, sort_order: a.sort_order }] });
      reload();
    } catch (e) { toast.show(String(e), 'err'); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <>
      <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24}}>
        <p style={{color: 'var(--ink-soft)', fontSize: 14}}>{images.length} images · stored in Cloudflare R2</p>
        <label className="admin-btn admin-btn-primary" style={{cursor: 'pointer'}}>
          <Icon name="upload" size={14}/>
          {uploading ? 'Uploading…' : 'Upload Images'}
          <input type="file" multiple accept="image/*" style={{display: 'none'}} disabled={uploading} onChange={e => e.target.files?.length && upload(Array.from(e.target.files))}/>
        </label>
      </div>
      <div className="admin-card" style={{padding: 20}}>
        <div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 16}}>
          {images.map((it, i) => (
            <div key={it.id}>
              <div style={{aspectRatio: '4/3', overflow: 'hidden', borderRadius: 2}}>
                <img src={`/media/${it.r2_key}`} style={{width: '100%', height: '100%', objectFit: 'cover'}} alt={it.alt_text || it.label || ''}/>
              </div>
              <div style={{padding: '10px 4px', display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
                <span style={{fontSize: 11, color: 'var(--ink-soft)', fontFamily: 'var(--mono)'}}>{it.label || it.id}</span>
                <div style={{display: 'flex', gap: 4}}>
                  <button className="admin-btn-ghost" style={{padding: 4}} onClick={() => move(it.id, -1)} disabled={i === 0}>←</button>
                  <button className="admin-btn-ghost" style={{padding: 4}} onClick={() => move(it.id, 1)} disabled={i === images.length - 1}>→</button>
                  <button className="admin-btn-ghost" style={{padding: 4, color: 'var(--terracotta)'}} onClick={() => remove(it.id)}><Icon name="trash" size={14}/></button>
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

// ───────────────────────────────────────────── REVIEWS
const AdminReviews = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/reviews');
  const reviews = data?.reviews || [];
  const [editing, setEditing] = useStateA(null);

  const save = async (r) => {
    try {
      if (r.id && reviews.find(x => x.id === r.id)) {
        await apiPut('/api/reviews', r);
      } else {
        await apiPost('/api/reviews', r);
      }
      toast.show('Saved'); setEditing(null); reload();
    } catch (e) { toast.show(String(e), 'err'); }
  };

  const del = async (id) => {
    if (!confirm('Delete this review?')) return;
    try { await apiDel(`/api/reviews?id=${encodeURIComponent(id)}`); toast.show('Deleted'); reload(); }
    catch (e) { toast.show(String(e), 'err'); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <>
      <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24}}>
        <p style={{color: 'var(--ink-soft)', fontSize: 14}}>{reviews.length} reviews · one featured on homepage</p>
        <button className="admin-btn admin-btn-primary" onClick={() => setEditing({ id: '', author: '', source: 'Google', rating: 5, text: '', featured: 0 })}><Icon name="plus" size={14}/>Add Review</button>
      </div>
      {editing && (
        <div className="admin-card" style={{marginBottom: 24}}>
          <div className="form-grid-2">
            <div className="form-row"><label className="label">Author</label><input className="input" value={editing.author} onChange={e => setEditing({...editing, author: e.target.value})}/></div>
            <div className="form-row"><label className="label">Source</label>
              <select className="select" value={editing.source || ''} onChange={e => setEditing({...editing, source: e.target.value})}>
                <option>Google</option><option>Airbnb</option><option>Booking.com</option><option>VRBO</option><option>Guest Book</option>
              </select>
            </div>
          </div>
          <div className="form-grid-2">
            <div className="form-row"><label className="label">Rating</label>
              <select className="select" value={editing.rating} onChange={e => setEditing({...editing, rating: parseInt(e.target.value)})}>
                {[5,4,3,2,1].map(n => <option key={n} value={n}>{n} ★</option>)}
              </select>
            </div>
            <div className="form-row"><label className="label">Featured</label>
              <label style={{display: 'flex', gap: 8, alignItems: 'center', fontSize: 13, padding: '14px 0'}}>
                <input type="checkbox" checked={!!editing.featured} onChange={e => setEditing({...editing, featured: e.target.checked ? 1 : 0})}/>
                Show on homepage (replaces previous featured)
              </label>
            </div>
          </div>
          <div className="form-row"><label className="label">Review text</label><textarea className="textarea" rows={5} value={editing.text} onChange={e => setEditing({...editing, text: e.target.value})}/></div>
          <div style={{display: 'flex', gap: 8, justifyContent: 'flex-end'}}>
            <button className="admin-btn admin-btn-outline" onClick={() => setEditing(null)}>Cancel</button>
            <button className="admin-btn admin-btn-primary" onClick={() => save(editing)}>Save</button>
          </div>
        </div>
      )}
      <div className="stack">
        {reviews.map(r => (
          <div key={r.id} className="admin-card" style={{display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16}}>
            <div style={{flex: 1}}>
              <div style={{display: 'flex', gap: 12, alignItems: 'center', marginBottom: 10}}>
                <div style={{fontWeight: 500}}>{r.author}</div>
                <span className="badge badge-green">{r.source || '—'}</span>
                {r.featured ? <span className="badge badge-amber">Featured</span> : null}
                <div style={{display: 'flex', gap: 2, color: 'var(--terracotta)'}}>{Array.from({length: r.rating}).map((_, i) => <Icon key={i} name="star" size={12}/>)}</div>
              </div>
              <p style={{fontSize: 14, color: 'var(--ink-soft)', lineHeight: 1.6}}>{r.text}</p>
            </div>
            <div style={{display: 'flex', gap: 8}}>
              <button className="admin-btn admin-btn-outline" onClick={() => setEditing({...r})}><Icon name="edit" size={14}/>Edit</button>
              <button className="admin-btn admin-btn-ghost" onClick={() => del(r.id)} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/></button>
            </div>
          </div>
        ))}
      </div>
    </>
  );
};

// ───────────────────────────────────────────── WIDGETS
const AdminWidgets = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/widgets');
  const [items, setItems] = useStateA([]);
  const [selected, setSelected] = useStateA(null);
  const [saving, setSaving] = useStateA(false);
  useEffectA(() => {
    if (data?.widgets) {
      setItems(data.widgets);
      if (!selected && data.widgets[0]) setSelected(data.widgets[0].id);
    }
  }, [data]);

  const w = items.find(x => x.id === selected);
  const upd = (patch) => setItems(items.map(x => x.id === selected ? {...x, ...patch} : x));
  const addNew = () => {
    const id = 'w_' + Date.now();
    const nw = { id, name: 'New widget', placement: 'homepage', kind: 'iframe', src: 'https://', width: '100%', height: 400, enabled: 0, sort_order: items.length + 1 };
    setItems([...items, nw]); setSelected(id);
  };
  const del = () => {
    if (!selected) return;
    setItems(items.filter(x => x.id !== selected));
    setSelected(items[0]?.id || null);
  };
  const setSize = (wv, h) => upd({ width: wv, height: h });
  const save = async () => {
    setSaving(true);
    try { await apiPut('/api/widgets', { widgets: items }); toast.show('Widgets saved'); reload(); }
    catch (e) { toast.show(String(e), 'err'); } finally { setSaving(false); }
  };

  if (loading) return <div>Loading…</div>;

  return (
    <div style={{display: 'grid', gridTemplateColumns: '320px 1fr', gap: 24}}>
      <div>
        <button className="admin-btn admin-btn-primary" onClick={addNew} style={{width: '100%', justifyContent: 'center', marginBottom: 12}}><Icon name="plus" size={14}/>Add widget</button>
        <button className="admin-btn admin-btn-outline" onClick={save} disabled={saving} style={{width: '100%', justifyContent: 'center', marginBottom: 12}}>{saving ? 'Saving…' : 'Save all changes'}</button>
        <div className="admin-card" style={{padding: 0}}>
          {items.map(x => (
            <button key={x.id} onClick={() => setSelected(x.id)} style={{display: 'block', width: '100%', padding: '14px 16px', textAlign: 'left', borderBottom: '1px solid #f5f1e3', background: selected === x.id ? '#faf8f2' : 'transparent', borderLeft: selected === x.id ? '2px solid var(--terracotta)' : '2px solid transparent'}}>
              <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 4}}>
                <div style={{fontWeight: 500, fontSize: 14}}>{x.name}</div>
                <span className={`badge badge-${x.enabled ? 'green' : 'amber'}`}>{x.enabled ? 'on' : 'off'}</span>
              </div>
              <div style={{fontSize: 12, color: 'var(--muted)'}}>{x.placement} · {x.kind}</div>
            </button>
          ))}
        </div>
      </div>
      {w ? (
        <div className="admin-card">
          <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24}}>
            <div><div className="eyebrow" style={{marginBottom: 6}}>Editing Widget</div><h3 className="serif" style={{fontSize: 22, fontWeight: 400}}>{w.name}</h3></div>
            <div style={{display: 'flex', gap: 8, alignItems: 'center'}}>
              <label style={{display: 'flex', gap: 8, alignItems: 'center', fontSize: 13, padding: '0 12px'}}>
                <input type="checkbox" checked={!!w.enabled} onChange={e => upd({enabled: e.target.checked ? 1 : 0})}/> Enabled
              </label>
              <button className="admin-btn admin-btn-ghost" onClick={del} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/></button>
            </div>
          </div>
          <div className="form-grid-2">
            <div className="form-row"><label className="label">Widget name</label><input className="input" value={w.name} onChange={e => upd({name: e.target.value})}/></div>
            <div className="form-row"><label className="label">Placement</label>
              <select className="select" value={w.placement} onChange={e => upd({placement: e.target.value})}>
                <option>homepage</option><option>homepage footer</option><option>rooms page</option><option>menu page</option><option>contact page</option><option>gallery page</option><option>webcam page</option><option>custom page</option>
              </select>
            </div>
          </div>
          <div className="form-row"><label className="label">Widget type</label>
            <div style={{display: 'flex', gap: 8}}>
              <button className={`admin-btn ${w.kind === 'iframe' ? 'admin-btn-primary' : 'admin-btn-outline'}`} onClick={() => upd({kind: 'iframe'})}>iframe URL</button>
              <button className={`admin-btn ${w.kind === 'html' ? 'admin-btn-primary' : 'admin-btn-outline'}`} onClick={() => upd({kind: 'html'})}>HTML snippet</button>
            </div>
          </div>
          <div className="form-row">
            <label className="label">{w.kind === 'iframe' ? 'Embed URL' : 'HTML / script'}</label>
            {w.kind === 'iframe' ? <input className="input" value={w.src} onChange={e => upd({src: e.target.value})} placeholder="https://..."/> : <textarea className="textarea" rows={5} value={w.src} onChange={e => upd({src: e.target.value})} style={{fontFamily: 'var(--mono)', fontSize: 12}}/>}
            <p className="small" style={{color: 'var(--muted)', marginTop: 6}}>HostMoat, Google Maps, Calendly, etc. HTML snippets are rendered in a sandboxed iframe.</p>
          </div>
          <div className="form-row">
            <label className="label">Size</label>
            <div className="form-grid-2">
              <div><div style={{fontSize: 11, color: 'var(--muted)', marginBottom: 4}}>Width</div><input className="input" value={w.width} onChange={e => upd({width: e.target.value})} placeholder="100% or 600"/></div>
              <div><div style={{fontSize: 11, color: 'var(--muted)', marginBottom: 4}}>Height (px)</div><input className="input" type="number" value={w.height} onChange={e => upd({height: parseInt(e.target.value) || 0})}/></div>
            </div>
            <div style={{display: 'flex', gap: 6, marginTop: 10, flexWrap: 'wrap'}}>
              <span style={{fontSize: 11, color: 'var(--muted)', padding: '8px 0', marginRight: 4}}>Presets:</span>
              <button className="admin-btn admin-btn-outline" onClick={() => setSize('100%', 400)}>Full · 400</button>
              <button className="admin-btn admin-btn-outline" onClick={() => setSize('100%', 560)}>Full · 560</button>
              <button className="admin-btn admin-btn-outline" onClick={() => setSize('100%', 720)}>Full · 720</button>
              <button className="admin-btn admin-btn-outline" onClick={() => setSize('600', 400)}>600 × 400</button>
              <button className="admin-btn admin-btn-outline" onClick={() => setSize('320', 240)}>320 × 240</button>
            </div>
          </div>
          <div>
            <label className="label">Live preview</label>
            <div style={{padding: 20, background: '#faf8f2', borderRadius: 4, border: '1px solid #e8e4d9'}}>
              <div style={{position: 'relative', width: w.width, height: w.height, maxWidth: '100%', resize: 'both', overflow: 'auto', border: '1px dashed var(--ocean)', background: 'var(--white)'}}>
                {w.kind === 'iframe' ? (
                  <iframe src={w.src} style={{width: '100%', height: '100%', border: 'none'}} sandbox="allow-scripts allow-same-origin allow-forms allow-popups"/>
                ) : (
                  <iframe srcDoc={w.src} style={{width: '100%', height: '100%', border: 'none'}} sandbox="allow-scripts allow-forms"/>
                )}
              </div>
              <p className="small" style={{color: 'var(--muted)', marginTop: 10}}>Drag the bottom-right corner of the preview to resize visually.</p>
            </div>
          </div>
        </div>
      ) : <div>Add a widget to begin.</div>}
    </div>
  );
};

// ───────────────────────────────────────────── MESSAGES (Inbox)
const AdminMessages = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/contact');
  const msgs = data?.messages || [];
  const del = async (id) => {
    if (!confirm('Delete this message?')) return;
    try { await apiDel(`/api/contact?id=${encodeURIComponent(id)}`); toast.show('Deleted'); reload(); }
    catch (e) { toast.show(String(e), 'err'); }
  };
  if (loading) return <div>Loading…</div>;
  if (!msgs.length) return <p style={{color: 'var(--muted)'}}>No messages yet. Contact-form submissions land here.</p>;
  return (
    <div className="stack">
      {msgs.map(m => (
        <div key={m.id} className="admin-card">
          <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16}}>
            <div style={{flex: 1}}>
              <div style={{display: 'flex', gap: 10, alignItems: 'center', marginBottom: 6}}>
                <strong>{m.name}</strong>
                <a href={`mailto:${m.email}`} style={{color: 'var(--terracotta)', fontSize: 13}}>{m.email}</a>
                {m.subject ? <span className="badge badge-green">{m.subject}</span> : null}
              </div>
              <p style={{fontSize: 14, lineHeight: 1.6, color: 'var(--ink-soft)', whiteSpace: 'pre-wrap'}}>{m.message}</p>
              <div style={{fontSize: 11, color: 'var(--muted)', marginTop: 10, fontFamily: 'var(--mono)'}}>{m.created_at}</div>
            </div>
            <button className="admin-btn admin-btn-ghost" onClick={() => del(m.id)} style={{color: 'var(--terracotta)'}}><Icon name="trash" size={14}/></button>
          </div>
        </div>
      ))}
    </div>
  );
};

// ───────────────────────────────────────────── SETTINGS
const AdminSettings = ({ toast }) => {
  const { data, loading, reload } = useRemote('/api/settings');
  const [s, setS] = useStateA({});
  const [saving, setSaving] = useStateA(false);
  useEffectA(() => { if (data?.settings) setS(data.settings); }, [data]);

  const save = async () => {
    setSaving(true);
    try { await apiPut('/api/settings', { settings: s }); toast.show('Settings saved'); reload(); }
    catch (e) { toast.show(String(e), 'err'); } finally { setSaving(false); }
  };

  if (loading) return <div>Loading…</div>;

  const F = ({ k, label, type = 'text', ...rest }) => (
    <div className="form-row">
      <label className="label">{label}</label>
      {type === 'textarea'
        ? <textarea className="textarea" rows={2} value={s[k] || ''} onChange={e => setS({...s, [k]: e.target.value})}/>
        : <input className="input" value={s[k] || ''} onChange={e => setS({...s, [k]: e.target.value})} {...rest}/>}
    </div>
  );

  return (
    <div style={{maxWidth: 720}}>
      <div style={{display: 'flex', justifyContent: 'flex-end', marginBottom: 16}}>
        <button className="admin-btn admin-btn-primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save settings'}</button>
      </div>
      <div className="admin-card" style={{marginBottom: 24}}>
        <h3 className="serif" style={{fontSize: 22, fontWeight: 400, marginBottom: 20}}>Site Identity</h3>
        <div className="form-grid-2">
          <F k="site_name" label="Site name"/>
          <F k="tagline" label="Tagline"/>
        </div>
        <F k="meta_description" label="Meta description" type="textarea"/>
      </div>
      <div className="admin-card" style={{marginBottom: 24}}>
        <h3 className="serif" style={{fontSize: 22, fontWeight: 400, marginBottom: 20}}>HostMoat Integration</h3>
        <p style={{fontSize: 13, color: 'var(--ink-soft)', marginBottom: 16}}>Bookings, pre-arrival forms, and the AI chatbot all run through your HostMoat property.</p>
        <F k="hostmoat_booking_url" label="Book-Stay / Booking URL"/>
        <F k="pre_arrival_url"      label="Pre-Arrival Form URL (shown to confirmed guests)"/>
        <F k="hostmoat_property_id" label="HostMoat property UUID (for AI chat)"/>
        <p className="small" style={{color: 'var(--muted)', marginTop: -8, marginBottom: 8}}>Chat widget only appears once property UUID is filled in.</p>
      </div>
      <div className="admin-card" style={{marginBottom: 24}}>
        <h3 className="serif" style={{fontSize: 22, fontWeight: 400, marginBottom: 20}}>Webcam & Weather</h3>
        <F k="webcam_url" label="Webcam URL (iframe src, YouTube URL, MP4, or still image)"/>
        <div className="form-row">
          <label className="label">Webcam type</label>
          <select className="select" value={s.webcam_type || 'iframe'} onChange={e => setS({...s, webcam_type: e.target.value})}>
            <option value="iframe">iframe (generic embed)</option>
            <option value="youtube">YouTube live URL</option>
            <option value="mp4">MP4 video file</option>
            <option value="still">Still image (auto-refresh every 30s)</option>
          </select>
        </div>
        <div className="form-grid-2">
          <F k="webcam_location_name" label="Location label (shown on page)"/>
          <F k="weather_location" label="Weather location (city name, for wttr.in)"/>
        </div>
      </div>
      <div className="admin-card" style={{marginBottom: 24}}>
        <h3 className="serif" style={{fontSize: 22, fontWeight: 400, marginBottom: 20}}>Contact & Social</h3>
        <div className="form-grid-2">
          <F k="phone" label="Booking phone"/>
          <F k="email" label="Email"/>
          <F k="hillary_email" label="Prepaid-food email (Hillary)"/>
          <F k="instagram_url" label="Instagram URL"/>
          <F k="facebook_url" label="Facebook URL"/>
          <F k="airbnb_url" label="Airbnb listing"/>
        </div>
      </div>
      <div className="admin-card" style={{marginBottom: 24}}>
        <h3 className="serif" style={{fontSize: 22, fontWeight: 400, marginBottom: 20}}>Address</h3>
        <F k="address_line1" label="Street"/>
        <div className="form-grid-2">
          <F k="address_line2" label="City / area"/>
          <F k="address_line3" label="State, Country"/>
        </div>
      </div>
    </div>
  );
};

// ───────────────────────────────────────────── SHELL
const AdminPanel = () => {
  const [view, setView] = useStateA('pages');
  const toast = useToast();
  const { data: pagesData } = useRemote('/api/pages');
  const titles = { pages: 'Pages', navigation: 'Navigation Menu', menu: 'Food Menu', gallery: 'Gallery', widgets: 'Embedded Widgets', reviews: 'Reviews', messages: 'Inbox', settings: 'Settings' };
  const views = {
    pages:      <AdminPages      toast={toast}/>,
    navigation: <AdminNavigation toast={toast} pages={pagesData?.pages || []}/>,
    menu:       <AdminMenu       toast={toast}/>,
    gallery:    <AdminGallery    toast={toast}/>,
    widgets:    <AdminWidgets    toast={toast}/>,
    reviews:    <AdminReviews    toast={toast}/>,
    messages:   <AdminMessages   toast={toast}/>,
    settings:   <AdminSettings   toast={toast}/>,
  };
  return (
    <div className="admin-body">
      <AdminSidebar view={view} setView={setView}/>
      <main className="admin-main">
        <header className="admin-header">
          <h1>{titles[view]}</h1>
          <div className="admin-header-actions">
            <a className="admin-btn admin-btn-outline" href="/" target="_blank" rel="noreferrer"><Icon name="eye" size={14}/>View site</a>
          </div>
        </header>
        <div className="admin-content">{views[view]}</div>
      </main>
      {toast.el}
    </div>
  );
};

Object.assign(window, { AdminLogin, AdminPanel });
