// Page: Admin — password gate + server-side product CRUD + settings editor
const { useState: useStateAdmin, useEffect: useEffectAdmin } = React;

// PROTOTYPE-ONLY: replace with real auth (NextAuth, Clerk, Supabase Auth) before going live.

function AdminPage({ products, setProducts, settings, setSettings, pushToast }) {
  const [authed, setAuthed] = useStateAdmin(false);
  const [pw, setPw] = useStateAdmin("");
  const [pwErr, setPwErr] = useStateAdmin("");
  const [editing, setEditing] = useStateAdmin(null); // product id or "new"
  const blank = { id: "", name: "", description: "", price: 0, category: "Home", images: [], stripeProductId: "" };
  const [draft, setDraft] = useStateAdmin(blank);
  const [uploading, setUploading] = useStateAdmin(false);
  const [uploadErr, setUploadErr] = useStateAdmin("");
  const [tab, setTab] = useStateAdmin("products"); // products | hours | classes
  const [hoursDraft, setHoursDraft] = useStateAdmin([]);
  const [classesDraft, setClassesDraft] = useStateAdmin([]);
  const [savingSettings, setSavingSettings] = useStateAdmin(false);

  useEffectAdmin(() => {
    if (authed) {
      setHoursDraft((settings.hours || []).map((h) => ({ ...h })));
      setClassesDraft((settings.classes || []).map((c) => ({ ...c })));
    }
  }, [authed, settings]);

  async function tryLogin(ev) {
    ev.preventDefault();
    try {
      const res = await fetch("/admin/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ password: pw }),
      });
      if (res.ok) {
        setAuthed(true);
        setPwErr("");
      } else {
        const data = await res.json().catch(() => ({}));
        setPwErr(data.error === "admin password not configured"
          ? "Admin is not configured on the server."
          : "Incorrect password.");
      }
    } catch (e) {
      console.error("[admin/login]", e);
      setPwErr("Sign-in failed. Please try again.");
    }
  }

  function startEdit(p) {
    setDraft({
      ...p,
      images: Array.isArray(p.images) ? [...p.images] : (p.image ? [p.image] : []),
      stripeProductId: p.stripeProductId || "",
    });
    setEditing(p.id);
    setUploadErr("");
  }
  function startNew() {
    setDraft({ ...blank, id: "p" + Date.now() });
    setEditing("new");
    setUploadErr("");
  }
  function cancel() { setEditing(null); setDraft(blank); setUploadErr(""); }

  async function uploadImage(file) {
    if (!file) return;
    if (!file.type.startsWith("image/")) {
      setUploadErr("Please choose an image file.");
      return;
    }
    if (file.size > 8 * 1024 * 1024) {
      setUploadErr("File is too large (8 MB max).");
      return;
    }
    setUploadErr("");
    setUploading(true);
    try {
      const fd = new FormData();
      fd.append("file", file);
      const res = await fetch("/admin/upload", {
        method: "POST",
        headers: { "X-Admin-Password": pw },
        body: fd,
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "upload failed");
      setDraft((d) => ({ ...d, images: [...(d.images || []), data.url] }));
      pushToast && pushToast("Image uploaded.");
    } catch (e) {
      console.error("[admin/upload]", e);
      setUploadErr(e.message || "Upload failed.");
    } finally {
      setUploading(false);
    }
  }

  function removeImage(idx) {
    setDraft((d) => ({ ...d, images: d.images.filter((_, i) => i !== idx) }));
  }
  function moveImage(idx, dir) {
    setDraft((d) => {
      const next = [...d.images];
      const j = idx + dir;
      if (j < 0 || j >= next.length) return d;
      [next[idx], next[j]] = [next[j], next[idx]];
      return { ...d, images: next };
    });
  }

  async function saveDraft() {
    if (!draft.name.trim() || isNaN(Number(draft.price))) {
      pushToast && pushToast("Name and price are required.");
      return;
    }
    const body = {
      id: draft.id,
      name: draft.name,
      description: draft.description,
      price: Number(draft.price),
      category: draft.category,
      images: draft.images,
      stripeProductId: draft.stripeProductId.trim(),
    };
    try {
      const isNew = editing === "new";
      const res = await fetch(isNew ? "/api/products" : `/api/products/${encodeURIComponent(draft.id)}`, {
        method: isNew ? "POST" : "PUT",
        headers: { "Content-Type": "application/json", "X-Admin-Password": pw },
        body: JSON.stringify(body),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "save failed");
      const fresh = await fetch("/api/products").then((r) => r.json());
      setProducts(fresh);
      pushToast && pushToast("Saved.");
      setEditing(null);
      setDraft(blank);
    } catch (e) {
      console.error("[admin] save", e);
      pushToast && pushToast(e.message || "Save failed.");
    }
  }

  async function remove(id) {
    if (!confirm("Delete this product?")) return;
    try {
      const res = await fetch(`/api/products/${encodeURIComponent(id)}`, {
        method: "DELETE",
        headers: { "X-Admin-Password": pw },
      });
      if (!res.ok) throw new Error("delete failed");
      const fresh = await fetch("/api/products").then((r) => r.json());
      setProducts(fresh);
      pushToast && pushToast("Deleted.");
    } catch (e) {
      console.error("[admin] delete", e);
      pushToast && pushToast("Delete failed.");
    }
  }

  async function saveHours() {
    setSavingSettings(true);
    try {
      const res = await fetch("/api/settings", {
        method: "PUT",
        headers: { "Content-Type": "application/json", "X-Admin-Password": pw },
        body: JSON.stringify({ hours: hoursDraft }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "save failed");
      setSettings((s) => ({ ...s, hours: data.hours }));
      pushToast && pushToast("Opening hours saved.");
    } catch (e) {
      console.error("[admin] saveHours", e);
      pushToast && pushToast("Couldn't save hours.");
    } finally {
      setSavingSettings(false);
    }
  }

  async function saveClasses() {
    setSavingSettings(true);
    try {
      const res = await fetch("/api/settings", {
        method: "PUT",
        headers: { "Content-Type": "application/json", "X-Admin-Password": pw },
        body: JSON.stringify({ classes: classesDraft }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "save failed");
      setSettings((s) => ({ ...s, classes: data.classes }));
      pushToast && pushToast("Class types saved.");
    } catch (e) {
      console.error("[admin] saveClasses", e);
      pushToast && pushToast("Couldn't save classes.");
    } finally {
      setSavingSettings(false);
    }
  }

  if (!authed) {
    return (
      <main id="main">
        <PageHeader eyebrow="Staff only" title="Admin" sub="Sign in to manage products." />
        <section className="section" style={{ paddingTop: 32 }}>
          <div className="container" style={{ maxWidth: 420 }}>
            <form onSubmit={tryLogin} style={{ display: "grid", gap: 12, background: "var(--surface)", padding: 24, borderRadius: "var(--radius)", border: "1px solid var(--line)" }}>
              <div className="field">
                <label htmlFor="pw">Password</label>
                <input id="pw" className="input" type="password" value={pw} onChange={(e) => setPw(e.target.value)} autoComplete="current-password" />
                {pwErr && <span className="error-text">{pwErr}</span>}
              </div>
              <button className="btn btn-primary" type="submit">Sign in</button>
            </form>
          </div>
        </section>
      </main>
    );
  }

  return (
    <main id="main">
      <PageHeader eyebrow="Admin" title="Manage your site"
                  sub="All changes save to the server and are visible to visitors immediately." />

      <section className="section" style={{ paddingTop: 16 }}>
        <div className="container">
          {/* Tabs */}
          <div className="chips" role="tablist" aria-label="Admin sections" style={{ marginBottom: 24 }}>
            {[
              ["products", "Products"],
              ["hours", "Opening hours"],
              ["classes", "Class types"],
            ].map(([id, label]) => (
              <button key={id}
                      role="tab"
                      aria-selected={tab === id}
                      className={"chip" + (tab === id ? " active" : "")}
                      onClick={() => setTab(id)}>
                {label}
              </button>
            ))}
            <button className="btn btn-ghost btn-sm" style={{ marginLeft: "auto" }} onClick={() => setAuthed(false)}>Sign out</button>
          </div>

          {tab === "products" && (
            <ProductsAdminTab
              products={products} startEdit={startEdit} startNew={startNew} remove={remove} />
          )}

          {tab === "hours" && (
            <HoursAdminTab
              hoursDraft={hoursDraft} setHoursDraft={setHoursDraft}
              saveHours={saveHours} saving={savingSettings} />
          )}

          {tab === "classes" && (
            <ClassesAdminTab
              classesDraft={classesDraft} setClassesDraft={setClassesDraft}
              saveClasses={saveClasses} saving={savingSettings} />
          )}
        </div>
      </section>

      {/* Edit modal */}
      <Modal open={editing !== null} onClose={cancel}>
        <div style={{ gridColumn: "1 / -1", padding: 28, display: "grid", gap: 12 }}>
          <h2 style={{ marginBottom: 4 }}>{editing === "new" ? "Add product" : "Edit product"}</h2>
          <div className="field">
            <label>Name</label>
            <input className="input" value={draft.name} onChange={(e) => setDraft({ ...draft, name: e.target.value })} />
          </div>
          <div className="field">
            <label>Description</label>
            <textarea className="textarea" value={draft.description} onChange={(e) => setDraft({ ...draft, description: e.target.value })} />
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <div className="field">
              <label>Category</label>
              <select className="select" value={draft.category} onChange={(e) => setDraft({ ...draft, category: e.target.value })}>
                {CATEGORIES.filter((c) => c !== "All").map((c) => <option key={c}>{c}</option>)}
              </select>
            </div>
            <div className="field">
              <label>Price (£)</label>
              <input className="input" type="number" min="0" value={draft.price}
                     onChange={(e) => setDraft({ ...draft, price: e.target.value })} />
            </div>
          </div>

          <div className="field">
            <label>Stripe product ID</label>
            <input className="input" placeholder="prod_…"
                   value={draft.stripeProductId}
                   onChange={(e) => setDraft({ ...draft, stripeProductId: e.target.value })} />
            <span style={{ fontSize: 12, color: "var(--muted)", marginTop: 4 }}>
              Optional. If set, Stripe's default price for this product is used at checkout. Otherwise the price above is used.
            </span>
          </div>

          <div className="field">
            <label>Product images</label>
            <div style={{ display: "flex", flexWrap: "wrap", gap: 12, marginBottom: 12 }}>
              {(draft.images || []).map((url, i) => (
                <div key={url + i} style={{ position: "relative", width: 100, height: 120,
                                            borderRadius: 8, overflow: "hidden",
                                            background: "var(--bg-2)", border: "1px solid var(--line)" }}>
                  <img src={url} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                  {i === 0 && (
                    <span style={{ position: "absolute", left: 4, top: 4,
                                   background: "rgba(0,0,0,.6)", color: "#fff",
                                   fontSize: 10, padding: "2px 6px", borderRadius: 4 }}>Primary</span>
                  )}
                  <div style={{ position: "absolute", right: 4, top: 4, display: "flex", flexDirection: "column", gap: 4 }}>
                    <button title="Remove" onClick={() => removeImage(i)}
                            style={imgBtnStyle()}>×</button>
                  </div>
                  <div style={{ position: "absolute", left: 0, right: 0, bottom: 0,
                                display: "flex", justifyContent: "space-between",
                                background: "rgba(0,0,0,.45)" }}>
                    <button onClick={() => moveImage(i, -1)} disabled={i === 0} title="Move left"
                            style={moveBtnStyle(i === 0)}>‹</button>
                    <button onClick={() => moveImage(i, 1)} disabled={i === draft.images.length - 1} title="Move right"
                            style={moveBtnStyle(i === draft.images.length - 1)}>›</button>
                  </div>
                </div>
              ))}
              {(!draft.images || draft.images.length === 0) && (
                <div style={{ width: 100, height: 120, borderRadius: 8,
                              background: "var(--bg-2)", border: "1px dashed var(--line)",
                              display: "grid", placeItems: "center",
                              color: "var(--muted)", fontSize: 12, padding: 8, textAlign: "center" }}>
                  No images yet
                </div>
              )}
            </div>
            <input
              type="file"
              accept="image/png,image/jpeg,image/webp,image/gif"
              disabled={uploading}
              onChange={(e) => {
                const file = e.target.files && e.target.files[0];
                e.target.value = "";
                if (file) uploadImage(file);
              }}
              style={{ display: "block", marginBottom: 6 }}
            />
            <div style={{ fontSize: 12, color: "var(--muted)" }}>
              Add as many as you like — first image is the primary one shown on the card.
              PNG, JPG, WEBP, GIF, up to 8&nbsp;MB each.
            </div>
            {uploading && <div style={{ fontSize: 13, marginTop: 8 }}>Uploading…</div>}
            {uploadErr && <div className="error-text" style={{ marginTop: 8 }}>{uploadErr}</div>}
          </div>

          <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
            <button className="btn btn-primary" onClick={saveDraft}>Save</button>
            <button className="btn btn-ghost" onClick={cancel}>Cancel</button>
          </div>
        </div>
      </Modal>
    </main>
  );
}

function imgBtnStyle() {
  return {
    width: 22, height: 22, borderRadius: "50%", border: "0",
    background: "rgba(0,0,0,.7)", color: "#fff", cursor: "pointer",
    fontSize: 14, lineHeight: 1, padding: 0,
  };
}
function moveBtnStyle(disabled) {
  return {
    flex: 1, height: 22, border: 0, background: "transparent",
    color: disabled ? "rgba(255,255,255,.3)" : "#fff",
    cursor: disabled ? "not-allowed" : "pointer", fontSize: 14,
  };
}

function ProductsAdminTab({ products, startEdit, startNew, remove }) {
  return (
    <React.Fragment>
      <div style={{ display: "flex", justifyContent: "space-between", flexWrap: "wrap", gap: 12, marginBottom: 20 }}>
        <div style={{ color: "var(--muted)" }}>{products.length} products</div>
        <button className="btn btn-primary btn-sm" onClick={startNew}><Icon.Plus /> New product</button>
      </div>

      <div className="admin-table-wrap">
        <table className="admin-table">
          <thead>
            <tr><th></th><th>Name</th><th>Category</th><th>Price</th><th>Stripe ID</th><th></th></tr>
          </thead>
          <tbody>
            {products.map((p) => {
              const img = productPrimaryImage(p);
              const imgs = (p.images || []).length;
              return (
                <tr key={p.id}>
                  <td>
                    <div style={{ position: "relative" }}>
                      <img className="row-thumb" src={img} alt="" />
                      {imgs > 1 && (
                        <span style={{ position: "absolute", right: -6, bottom: -6,
                                       background: "var(--accent)", color: "var(--accent-on)",
                                       fontSize: 10, padding: "1px 5px", borderRadius: 4 }}>{imgs}</span>
                      )}
                    </div>
                  </td>
                  <td>
                    <div style={{ fontFamily: "var(--font-serif)", fontSize: "1rem" }}>{p.name}</div>
                    <div style={{ fontSize: 13, color: "var(--muted)" }}>{(p.description || "").slice(0, 60)}…</div>
                  </td>
                  <td>{p.category}</td>
                  <td>£{p.price}</td>
                  <td style={{ fontSize: 12, color: p.stripeProductId ? "var(--ink-2)" : "var(--muted)" }}>
                    {p.stripeProductId || "—"}
                  </td>
                  <td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
                    <button className="btn btn-ghost btn-sm" onClick={() => startEdit(p)}><Icon.Edit /> Edit</button>
                    <button className="btn btn-ghost btn-sm" onClick={() => remove(p.id)} style={{ color: "#B0413E" }}><Icon.Trash /></button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div className="admin-mobile">
        {products.map((p) => (
          <div key={p.id} className="admin-card">
            <img className="ac-thumb" src={productPrimaryImage(p)} alt="" />
            <div>
              <div style={{ fontFamily: "var(--font-serif)", fontSize: "1.05rem" }}>{p.name}</div>
              <div style={{ fontSize: 13, color: "var(--muted)" }}>{p.category} · £{p.price}{(p.images || []).length > 1 ? ` · ${p.images.length} images` : ""}</div>
              <div style={{ display: "flex", gap: 6, marginTop: 8 }}>
                <button className="btn btn-ghost btn-sm" onClick={() => startEdit(p)}><Icon.Edit /> Edit</button>
                <button className="btn btn-ghost btn-sm" style={{ color: "#B0413E" }} onClick={() => remove(p.id)}><Icon.Trash /></button>
              </div>
            </div>
          </div>
        ))}
      </div>
    </React.Fragment>
  );
}

function HoursAdminTab({ hoursDraft, setHoursDraft, saveHours, saving }) {
  function update(idx, field, value) {
    setHoursDraft((rows) => rows.map((r, i) => i === idx ? { ...r, [field]: value } : r));
  }
  return (
    <div style={{ maxWidth: 520, display: "grid", gap: 12, background: "var(--surface)",
                  padding: 24, borderRadius: "var(--radius)", border: "1px solid var(--line)" }}>
      <h3 style={{ fontFamily: "var(--font-serif)", margin: 0 }}>Opening hours</h3>
      <p style={{ color: "var(--muted)", fontSize: 14, margin: 0 }}>
        Shown in the footer and on the contact page. Use any text — e.g. "Closed", "By appointment".
      </p>
      {hoursDraft.map((row, i) => (
        <div key={i} style={{ display: "grid", gridTemplateColumns: "80px 1fr", gap: 12, alignItems: "center" }}>
          <input className="input" value={row.day} onChange={(e) => update(i, "day", e.target.value)} />
          <input className="input" value={row.hours} onChange={(e) => update(i, "hours", e.target.value)}
                 placeholder="10:00 – 17:00 or Closed" />
        </div>
      ))}
      <div>
        <button className="btn btn-primary" onClick={saveHours} disabled={saving}
                style={{ opacity: saving ? 0.6 : 1 }}>
          {saving ? "Saving…" : "Save opening hours"}
        </button>
      </div>
    </div>
  );
}

function ClassesAdminTab({ classesDraft, setClassesDraft, saveClasses, saving }) {
  function update(idx, field, value) {
    setClassesDraft((rows) => rows.map((r, i) => i === idx ? { ...r, [field]: value } : r));
  }
  function addRow() {
    setClassesDraft((rows) => [...rows, { id: `c${Date.now()}`, name: "New class", duration: "2 hours", price: 35, desc: "" }]);
  }
  function removeRow(idx) {
    setClassesDraft((rows) => rows.filter((_, i) => i !== idx));
  }
  return (
    <div style={{ display: "grid", gap: 16 }}>
      <p style={{ color: "var(--muted)", fontSize: 14, margin: 0 }}>
        Edit the class types shown on the Classes page. Pricing here is for display only — bookings are still
        confirmed by email after a request.
      </p>
      {classesDraft.map((c, i) => (
        <div key={c.id || i}
             style={{ background: "var(--surface)", padding: 20, borderRadius: "var(--radius)",
                      border: "1px solid var(--line)", display: "grid", gap: 10 }}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 120px 100px", gap: 10 }}>
            <div className="field">
              <label>Name</label>
              <input className="input" value={c.name} onChange={(e) => update(i, "name", e.target.value)} />
            </div>
            <div className="field">
              <label>Duration</label>
              <input className="input" value={c.duration} onChange={(e) => update(i, "duration", e.target.value)} />
            </div>
            <div className="field">
              <label>Price (£)</label>
              <input className="input" type="number" min="0" value={c.price}
                     onChange={(e) => update(i, "price", e.target.value)} />
            </div>
          </div>
          <div className="field">
            <label>Description</label>
            <textarea className="textarea" value={c.desc} onChange={(e) => update(i, "desc", e.target.value)} />
          </div>
          <div>
            <button className="btn btn-ghost btn-sm" onClick={() => removeRow(i)} style={{ color: "#B0413E" }}>
              <Icon.Trash /> Remove
            </button>
          </div>
        </div>
      ))}
      <div style={{ display: "flex", gap: 8 }}>
        <button className="btn btn-ghost btn-sm" onClick={addRow}><Icon.Plus /> Add class type</button>
        <button className="btn btn-primary" onClick={saveClasses} disabled={saving}
                style={{ opacity: saving ? 0.6 : 1, marginLeft: "auto" }}>
          {saving ? "Saving…" : "Save class types"}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, { AdminPage });
