/* Mega-Sweets admin panel — password-gated content editor + analytics.
   Loaded before app.jsx; exported via window.Admin. Uses React.* hooks directly
   (no `const { useState } = React` — that's already global in OrderFlow.jsx). */

const TONES = ['sky', 'purple', 'magenta'];

function authFetch(token, url, opts) {
  opts = opts || {};
  const headers = Object.assign({}, opts.headers || {}, { Authorization: `Bearer ${token}` });
  return fetch(url, Object.assign({}, opts, { headers }));
}

async function uploadImage(token, file, kind) {
  const fd = new FormData();
  fd.append('file', file);
  fd.append('kind', kind);
  const r = await authFetch(token, '/api/admin/upload', { method: 'POST', body: fd });
  const d = await r.json();
  if (!r.ok || !d.ok) throw new Error(d.error || 'Upload failed');
  return d.url;
}

/* --------------------------- Login gate --------------------------- */

function AdminLogin({ onToken }) {
  const [password, setPassword] = React.useState('');
  const [error, setError] = React.useState('');
  const [busy, setBusy] = React.useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setError(''); setBusy(true);
    try {
      const r = await fetch('/api/admin/login', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ password }),
      });
      const d = await r.json();
      if (r.ok && d.ok) { sessionStorage.setItem('ms_admin_token', d.token); onToken(d.token); }
      else setError(d.error || 'Incorrect password');
    } catch { setError('Network error'); }
    finally { setBusy(false); }
  };

  return (
    <div className="adm-login">
      <div className="ms-card adm-login-card">
        <img className="adm-login-logo" src="assets/logo-wordmark.png" alt="Mega-Sweets" />
        <h2 style={{ margin: '6px 0 2px' }}>Admin</h2>
        <p className="small" style={{ marginBottom: 16 }}>Enter the password to manage the menu &amp; view traffic.</p>
        <form onSubmit={submit}>
          <div className="ms-field">
            <input className="ms-input" type="password" placeholder="Password" value={password}
              onChange={e => setPassword(e.target.value)} autoFocus />
          </div>
          {error && <p className="od-error" style={{ marginTop: 0 }}>{error}</p>}
          <button className="ms-btn ms-btn--primary" style={{ width: '100%', marginTop: 6 }} disabled={busy}>
            {busy ? 'Checking…' : 'Log in'}
          </button>
        </form>
      </div>
    </div>
  );
}

/* --------------------------- Image field --------------------------- */

function ImageField({ token, label, value, kind, onChange }) {
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const pick = async (e) => {
    const file = e.target.files && e.target.files[0];
    if (!file) return;
    setErr(''); setBusy(true);
    try { onChange(await uploadImage(token, file, kind)); }
    catch (ex) { setErr(ex.message); }
    finally { setBusy(false); e.target.value = ''; }
  };
  return (
    <div className="adm-img">
      <div className="adm-img-prev">{value ? <img src={value} alt={label} /> : <span className="small">none</span>}</div>
      <div className="adm-img-meta">
        <div className="adm-img-label">{label}</div>
        <label className="ms-btn ms-btn--outline adm-upload">
          {busy ? 'Uploading…' : 'Upload image'}
          <input type="file" accept="image/png,image/jpeg,image/webp,image/gif" onChange={pick} hidden disabled={busy} />
        </label>
        <div className="adm-hint">PNG or JPG, under 5MB. Real photo → JPG; cutout with see-through background → PNG.</div>
        {err && <div className="od-error" style={{ marginTop: 6 }}>{err}</div>}
      </div>
    </div>
  );
}

/* --------------------------- Content editor --------------------------- */

function ContentEditor({ token, defaults, mergeContent }) {
  const [c, setC] = React.useState(null);
  const [status, setStatus] = React.useState('');
  const [saving, setSaving] = React.useState(false);

  React.useEffect(() => {
    fetch('/api/content').then(r => r.ok ? r.json() : {}).then(d => setC(mergeContent(d))).catch(() => setC(defaults));
  }, []);

  if (!c) return <p className="small">Loading…</p>;

  const set = (patch) => setC(prev => Object.assign({}, prev, patch));
  const setPerDozen = (k, v) => set({ perDozen: Object.assign({}, c.perDozen, { [k]: Number(v) || 0 }) });
  const setImage = (k, url) => set({ images: Object.assign({}, c.images, { [k]: url }) });

  const setPkg = (i, patch) => set({ packages: c.packages.map((p, idx) => idx === i ? Object.assign({}, p, patch) : p) });
  const addPkg = () => set({ packages: [...c.packages, { name: 'New package', items: [], treats: 0, price: 0, tone: 'sky' }] });
  const delPkg = (i) => set({ packages: c.packages.filter((_, idx) => idx !== i) });

  const setFlavor = (i, patch) => set({ flavors: c.flavors.map((f, idx) => idx === i ? Object.assign({}, f, patch) : f) });
  const addFlavor = () => set({ flavors: [...c.flavors, { name: 'New flavor', image: 'assets/flavors/vanilla.png' }] });
  const delFlavor = (i) => set({ flavors: c.flavors.filter((_, idx) => idx !== i) });

  const save = async () => {
    setSaving(true); setStatus('');
    try {
      const r = await authFetch(token, '/api/admin/content', {
        method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(c),
      });
      if (r.status === 401) { setStatus('Session expired — please log in again.'); return; }
      const d = await r.json();
      setStatus(d.ok ? 'Saved! Changes are live on the site.' : (d.error || 'Save failed'));
    } catch { setStatus('Network error'); }
    finally { setSaving(false); }
  };

  return (
    <div className="adm-content">
      {/* Per-dozen prices */}
      <section className="ms-card adm-sec">
        <h3>Per-dozen prices</h3>
        <div className="od-row">
          <div className="ms-field"><label>Cake Pops ($/dozen)</label>
            <input className="ms-input" type="number" min="0" value={c.perDozen.cakePops} onChange={e => setPerDozen('cakePops', e.target.value)} /></div>
          <div className="ms-field"><label>Cakesicles ($/dozen)</label>
            <input className="ms-input" type="number" min="0" value={c.perDozen.cakesicles} onChange={e => setPerDozen('cakesicles', e.target.value)} /></div>
        </div>
      </section>

      {/* Images */}
      <section className="ms-card adm-sec">
        <h3>Main images</h3>
        <ImageField token={token} label="Hero photo" kind="hero" value={c.images.hero} onChange={u => setImage('hero', u)} />
        <ImageField token={token} label="Cake Pops photo" kind="product" value={c.images.cakePops} onChange={u => setImage('cakePops', u)} />
        <ImageField token={token} label="Cakesicles photo" kind="product" value={c.images.cakesicles} onChange={u => setImage('cakesicles', u)} />
      </section>

      {/* Packages */}
      <section className="ms-card adm-sec">
        <div className="adm-sec-head"><h3>Party packages</h3><button className="ms-btn ms-btn--outline" onClick={addPkg}>+ Add package</button></div>
        {c.packages.map((p, i) => (
          <div className="adm-row" key={i}>
            <div className="od-row">
              <div className="ms-field"><label>Name</label><input className="ms-input" value={p.name} onChange={e => setPkg(i, { name: e.target.value })} /></div>
              <div className="ms-field"><label>Price ($)</label><input className="ms-input" type="number" min="0" value={p.price} onChange={e => setPkg(i, { price: Number(e.target.value) || 0 })} /></div>
            </div>
            <div className="od-row">
              <div className="ms-field"><label>Treat count</label><input className="ms-input" type="number" min="0" value={p.treats} onChange={e => setPkg(i, { treats: Number(e.target.value) || 0 })} /></div>
              <div className="ms-field"><label>Color tone</label>
                <select className="ms-input" value={p.tone} onChange={e => setPkg(i, { tone: e.target.value })}>
                  {TONES.map(t => <option key={t} value={t}>{t}</option>)}
                </select></div>
            </div>
            <div className="ms-field"><label>Contents (one per line)</label>
              <textarea className="ms-input" rows={3} value={(p.items || []).join('\n')}
                onChange={e => setPkg(i, { items: e.target.value.split('\n').map(s => s.trim()).filter(Boolean) })} /></div>
            <button className="ms-btn ms-btn--ghost adm-del" onClick={() => delPkg(i)}>Remove package</button>
          </div>
        ))}
      </section>

      {/* Flavors */}
      <section className="ms-card adm-sec">
        <div className="adm-sec-head"><h3>Flavors</h3><button className="ms-btn ms-btn--outline" onClick={addFlavor}>+ Add flavor</button></div>
        {c.flavors.map((f, i) => (
          <div className="adm-row adm-flavor" key={i}>
            <div className="adm-flavor-img">{f.image ? <img src={f.image} alt={f.name} /> : null}</div>
            <div className="adm-flavor-fields">
              <div className="ms-field"><label>Name</label><input className="ms-input" value={f.name} onChange={e => setFlavor(i, { name: e.target.value })} /></div>
              <ImageField token={token} label="Flavor image" kind="flavor" value={f.image} onChange={u => setFlavor(i, { image: u })} />
            </div>
            <button className="ms-btn ms-btn--ghost adm-del" onClick={() => delFlavor(i)}>Remove</button>
          </div>
        ))}
      </section>

      <div className="adm-save-bar">
        {status && <span className={status.startsWith('Saved') ? 'adm-ok' : 'od-error'} style={{ margin: 0 }}>{status}</span>}
        <button className="ms-btn ms-btn--primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save changes'}</button>
      </div>
    </div>
  );
}

/* --------------------------- Analytics --------------------------- */

function AnalyticsView({ token, onExpire }) {
  const [period, setPeriod] = React.useState('7d');
  const [data, setData] = React.useState(null);
  const [err, setErr] = React.useState('');

  React.useEffect(() => {
    setData(null); setErr('');
    authFetch(token, `/api/admin/analytics?period=${period}`)
      .then(r => { if (r.status === 401) { onExpire(); throw new Error('expired'); } return r.json(); })
      .then(setData).catch(() => setErr('Could not load analytics'));
  }, [period]);

  const periods = [['24h', 'Today'], ['7d', '7 days'], ['30d', '30 days'], ['all', 'All time']];
  const maxDay = data && data.daily.length ? Math.max(...data.daily.map(d => d.views)) : 1;

  return (
    <div className="adm-analytics">
      <div className="adm-period">
        {periods.map(([k, label]) => (
          <button key={k} className={`ms-btn ${period === k ? 'ms-btn--primary' : 'ms-btn--outline'}`} onClick={() => setPeriod(k)}>{label}</button>
        ))}
      </div>
      {err && <p className="od-error">{err}</p>}
      {!data && !err && <p className="small">Loading…</p>}
      {data && (
        <React.Fragment>
          <div className="adm-stats">
            <div className="ms-card adm-stat"><div className="adm-stat-n">{data.summary.total_views}</div><div className="small">Total views</div></div>
            <div className="ms-card adm-stat"><div className="adm-stat-n">{data.summary.unique_visitors}</div><div className="small">Unique visitors</div></div>
          </div>

          <section className="ms-card adm-sec">
            <h3>Views by day</h3>
            {data.daily.length ? data.daily.map(d => (
              <div className="adm-bar-row" key={d.date}>
                <span className="adm-bar-label small">{d.date}</span>
                <span className="adm-bar"><span className="adm-bar-fill" style={{ width: `${Math.round((d.views / maxDay) * 100)}%` }} /></span>
                <span className="adm-bar-n small">{d.views}</span>
              </div>
            )) : <p className="small">No views yet.</p>}
          </section>

          <div className="od-row">
            <section className="ms-card adm-sec">
              <h3>Where they came from</h3>
              {data.top_sources.length ? data.top_sources.map((s, i) => (
                <div className="adm-list-row" key={i}><span>{s.source}</span><span className="adm-list-n">{s.count}</span></div>
              )) : <p className="small">No data yet.</p>}
            </section>
            <section className="ms-card adm-sec">
              <h3>Countries</h3>
              {data.countries.length ? data.countries.map((s, i) => (
                <div className="adm-list-row" key={i}><span>{s.country}</span><span className="adm-list-n">{s.count}</span></div>
              )) : <p className="small">No data yet.</p>}
            </section>
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

/* --------------------------- Shell --------------------------- */

function Admin({ defaults, mergeContent }) {
  const [token, setToken] = React.useState(() => sessionStorage.getItem('ms_admin_token') || '');
  const [tab, setTab] = React.useState('content');

  const logout = () => { sessionStorage.removeItem('ms_admin_token'); setToken(''); };

  if (!token) return <AdminLogin onToken={setToken} />;

  return (
    <div className="adm">
      <header className="adm-header">
        <div className="adm-brand"><img src="assets/logo-wordmark.png" alt="Mega-Sweets" /><span>Admin</span></div>
        <div className="adm-tabs">
          <button className={`ms-btn ${tab === 'content' ? 'ms-btn--primary' : 'ms-btn--ghost'}`} onClick={() => setTab('content')}>Content</button>
          <button className={`ms-btn ${tab === 'analytics' ? 'ms-btn--primary' : 'ms-btn--ghost'}`} onClick={() => setTab('analytics')}>Analytics</button>
          <button className="ms-btn ms-btn--ghost" onClick={logout}>Log out</button>
        </div>
      </header>
      <main className="adm-main">
        {tab === 'content' && <ContentEditor token={token} defaults={defaults} mergeContent={mergeContent} />}
        {tab === 'analytics' && <AnalyticsView token={token} onExpire={logout} />}
      </main>
    </div>
  );
}

Object.assign(window, { Admin });
