/* The Cakerz admin app. This file only renders /admin routes and does not
   change the approved public storefront. */
(function () {
  const { useEffect, useMemo, useState } = React;
  const { Btn, Stars } = window.Atelier;
  const API = window.CakerzBackend;
  const PG = { maxWidth: 1200, margin: "0 auto" };
  const input = { width: "100%", boxSizing: "border-box", padding: "10px 12px", border: "1.5px solid var(--c-line-strong)", borderRadius: 9, font: "400 14px/1.4 var(--font-body)", background: "#fff" };
  const panel = { background: "var(--c-surface)", border: "1px solid var(--c-line)", borderRadius: 14, padding: 20 };
  const statuses = ["new", "reviewing", "quoted", "approved", "completed", "cancelled"];
  const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
  const defaultBusinessHours = window.Atelier.DEFAULT_BUSINESS_HOURS;

  function goAdmin(id) {
    const path = id === "dashboard" ? "/admin" : "/admin/" + id;
    window.history.pushState({}, "", path);
    window.dispatchEvent(new PopStateEvent("popstate"));
    window.scrollTo(0, 0);
  }

  function titleize(value) {
    return String(value || "").replace(/[-_]/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
  }

  function money(value) {
    return "$" + Number(value || 0).toFixed(2).replace(".00", "");
  }

  function productImages(item) {
    return [...(item?.product_images || [])].sort((a, b) => Number(b.is_primary) - Number(a.is_primary) || Number(a.sort_order || 0) - Number(b.sort_order || 0));
  }

  function primaryImage(item) {
    return productImages(item).find((image) => image.is_primary) || productImages(item)[0] || null;
  }

  function Field({ label, value, onChange, type = "text", area, options }) {
    const Control = area ? "textarea" : options ? "select" : "input";
    return (
      <label style={{ display: "grid", gap: 6 }}>
        <span style={{ font: "700 12px/1 var(--font-body)", color: "var(--c-ink-soft)" }}>{label}</span>
        <Control
          type={type}
          value={value ?? ""}
          rows={area ? 3 : undefined}
          onChange={(event) => onChange(event.target.type === "checkbox" ? event.target.checked : event.target.value)}
          checked={type === "checkbox" ? Boolean(value) : undefined}
          style={type === "checkbox" ? { width: 18, height: 18 } : input}
        >
          {options?.map((option) => <option key={option.value ?? option} value={option.value ?? option}>{option.label ?? option}</option>)}
        </Control>
      </label>
    );
  }

  function Notice({ type = "info", children }) {
    const palette = type === "error"
      ? ["#fff1f2", "#7a1f2d", "#e2a3aa"]
      : type === "ok"
        ? ["var(--ok-bg)", "var(--ok)", "transparent"]
        : ["var(--c-surface-2)", "var(--c-ink-soft)", "var(--c-line)"];
    return <div style={{ background: palette[0], color: palette[1], border: "1px solid " + palette[2], borderRadius: 10, padding: "11px 13px", font: "700 13.5px/1.45 var(--font-body)" }}>{children}</div>;
  }

  function useAdminData(loader, deps) {
    const [state, setState] = useState({ loading: true, error: "", data: null });
    const reload = () => {
      setState((current) => ({ ...current, loading: true, error: "" }));
      loader()
        .then((data) => setState({ loading: false, error: "", data }))
        .catch((error) => setState({ loading: false, error: error.message || "Could not load admin data.", data: null }));
    };
    useEffect(reload, deps);
    return { ...state, reload };
  }

  function Login({ onLogin }) {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [error, setError] = useState("");
    const [busy, setBusy] = useState(false);
    const submit = async (event) => {
      event.preventDefault();
      setError("");
      setBusy(true);
      try {
        await API.signInAdmin(email, password);
        onLogin();
      } catch (loginError) {
        setError(loginError.message || "Login failed.");
      } finally {
        setBusy(false);
      }
    };
    return (
      <main style={{ ...PG, maxWidth: 520, padding: "48px 22px 80px" }}>
        <form onSubmit={submit} style={{ ...panel, boxShadow: "var(--shadow-md)", display: "grid", gap: 16 }}>
          <div>
            <div style={{ font: "700 12px/1 var(--font-body)", letterSpacing: ".16em", textTransform: "uppercase", color: "var(--c-secondary)", marginBottom: 8 }}>The Cakerz admin</div>
            <h1 style={{ font: "600 38px/1 var(--font-display)", margin: 0 }}>Staff login</h1>
          </div>
          <Field label="Email" type="email" value={email} onChange={setEmail} />
          <Field label="Password" type="password" value={password} onChange={setPassword} />
          {error && <Notice type="error">{error}</Notice>}
          <Btn type="submit" disabled={busy}>{busy ? "Signing in..." : "Sign in"}</Btn>
          <p style={{ margin: 0, color: "var(--c-ink-soft)", fontSize: 13 }}>Access requires a Supabase Auth user linked to an active `admin_profiles` row.</p>
        </form>
      </main>
    );
  }

  function AdminChrome({ section, profile, onLogout, children, mobile }) {
    const sections = [
      ["dashboard", "Dashboard", "ph-squares-four"],
      ["products", "Products", "ph-cake"],
      ["categories", "Categories", "ph-list-bullets"],
      ["reviews", "Reviews", "ph-star"],
      ["hero", "Hero / Homepage", "ph-house-line"],
      ["custom-cakes", "Custom cakes", "ph-palette"],
      ["orders", "Orders", "ph-receipt"],
      ["settings", "Settings", "ph-sliders-horizontal"],
    ];
    return (
      <main style={{ ...PG, padding: mobile ? "22px 18px 50px" : "34px 22px 70px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", gap: 16, alignItems: "center", marginBottom: 20, flexWrap: "wrap" }}>
          <div>
            <div style={{ font: "700 12px/1 var(--font-body)", letterSpacing: ".16em", textTransform: "uppercase", color: "var(--c-secondary)", marginBottom: 7 }}>The Cakerz admin</div>
            <h1 style={{ font: "600 clamp(30px,4vw,46px)/1.04 var(--font-display)", margin: 0 }}>{titleize(section === "dashboard" ? "dashboard" : section)}</h1>
          </div>
          <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
            <span style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>{profile?.full_name || "Admin"} · {profile?.role}</span>
            <Btn variant="outline" onClick={() => window.location.assign("/")}>Storefront</Btn>
            <Btn variant="ghost" onClick={onLogout}>Logout</Btn>
          </div>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: mobile ? "1fr" : "238px 1fr", gap: 18, alignItems: "start" }}>
          <aside style={{ ...panel, display: "grid", gap: 8 }}>
            {sections.map(([id, label, icon]) => (
              <button key={id} onClick={() => goAdmin(id)} style={{ border: "1px solid " + (section === id ? "var(--c-accent)" : "var(--c-line)"), background: section === id ? "var(--c-accent-soft)" : "transparent", color: section === id ? "var(--c-accent)" : "var(--c-ink)", borderRadius: 10, padding: "11px 12px", cursor: "pointer", display: "flex", gap: 9, alignItems: "center", font: "700 14px/1 var(--font-body)", textAlign: "left" }}><i className={"ph " + icon} /> {label}</button>
            ))}
          </aside>
          <section style={{ display: "grid", gap: 16 }}>{children}</section>
        </div>
      </main>
    );
  }

  function Dashboard() {
    const { loading, error, data } = useAdminData(() => API.adminOverview(), []);
    const cards = [
      ["Active products", data?.products ?? 0, "ph-cake"],
      ["Active categories", data?.categories ?? 0, "ph-list-bullets"],
      ["Open custom requests", data?.requests ?? 0, "ph-palette"],
      ["Paid orders", data?.orders ?? 0, "ph-receipt"],
    ];
    return (
      <>
        <div style={panel}>
          <h2 style={{ font: "600 28px/1 var(--font-display)", margin: "0 0 8px" }}>Dashboard</h2>
          <p style={{ margin: 0, color: "var(--c-ink-soft)" }}>Manage products, categories, custom cake requests and order settings from Supabase-backed admin tools.</p>
        </div>
        {error && <Notice type="error">{error}</Notice>}
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 14 }}>
          {cards.map(([label, value, icon]) => (
            <div key={label} style={panel}>
              <i className={"ph " + icon} style={{ fontSize: 24, color: "var(--c-accent)" }} />
              <div style={{ font: "600 34px/1 var(--font-display)", marginTop: 10 }}>{loading ? "..." : value}</div>
              <div style={{ color: "var(--c-ink-soft)", fontWeight: 800, fontSize: 13 }}>{label}</div>
            </div>
          ))}
        </div>
      </>
    );
  }

  function Products() {
    const products = useAdminData(() => API.listProductsAdmin(), []);
    const categories = useAdminData(() => API.listCategoriesAdmin(), []);
    const empty = { category_id: "", slug: "", name: "", description: "", kind: "cake", base_price: "", price_label: "Price on request", price_on_request: true, group_name: "", serves: "", tags: "", flavours: "", included_items: "", direct_checkout: false, is_featured: false, is_active: true, sort_order: 0, product_images: [] };
    const [form, setForm] = useState(empty);
    const [imageFile, setImageFile] = useState(null);
    const [imagePreview, setImagePreview] = useState("");
    const [formOpen, setFormOpen] = useState(false);
    const [message, setMessage] = useState("");
    const [error, setError] = useState("");
    const categoryOptions = (categories.data || []).map((cat) => ({ value: cat.id, label: cat.name }));
    useEffect(() => {
      if (!imageFile) {
        setImagePreview("");
        return undefined;
      }
      const url = URL.createObjectURL(imageFile);
      setImagePreview(url);
      return () => URL.revokeObjectURL(url);
    }, [imageFile]);
    const resetForm = () => {
      setForm(empty);
      setImageFile(null);
      setImagePreview("");
      setFormOpen(false);
    };
    const save = async () => {
      setMessage("");
      setError("");
      try {
        await API.saveProductAdmin({ ...form, image_file: imageFile });
        resetForm();
        products.reload();
        setMessage("Product saved.");
      } catch (saveError) {
        setError(saveError.message || "Product could not be saved.");
      }
    };
    const edit = (item) => {
      setImageFile(null);
      setImagePreview("");
      setForm({
        ...item,
      category_id: item.category_id,
      base_price: item.base_price ?? "",
      price_on_request: item.base_price == null,
      tags: (item.tags || []).join(", "),
      flavours: (item.flavours || []).join(", "),
      included_items: (item.included_items || []).join("\n"),
      });
      setFormOpen(true);
      window.scrollTo({ top: 0, behavior: "smooth" });
    };
    const handleImageAction = async (action) => {
      setError("");
      setMessage("");
      try {
        await action();
        products.reload();
        setMessage("Product image updated.");
      } catch (actionError) {
        setError(actionError.message || "Product image could not be updated.");
      }
    };
    const currentImages = productImages(form);
    const previewImage = imagePreview || primaryImage(form)?.public_url || "";
    return (
      <>
        <div style={panel}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12, marginBottom: formOpen ? 14 : 0 }}>
            <div>
              <h2 style={{ font: "600 25px/1 var(--font-display)", margin: 0 }}>{form.id ? "Edit product" : "Add product"}</h2>
              <p style={{ margin: "6px 0 0", color: "var(--c-ink-soft)", fontSize: 13 }}>Keep this panel closed when reviewing the product list.</p>
            </div>
            <Btn size="sm" variant={formOpen ? "outline" : "primary"} onClick={() => setFormOpen(!formOpen)}>{formOpen ? "Collapse form" : "Add product"}</Btn>
          </div>
          {formOpen && <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 12, maxHeight: 620, overflowY: "auto", paddingRight: 4 }}>
            <Field label="Category" value={form.category_id} onChange={(v) => setForm({ ...form, category_id: v })} options={[{ value: "", label: "Select category" }, ...categoryOptions]} />
            <Field label="Type" value={form.kind} onChange={(v) => setForm({ ...form, kind: v })} options={["cake", "cupcake", "dessert", "coffee", "party"]} />
            <Field label="Name" value={form.name} onChange={(v) => setForm({ ...form, name: v })} />
            <Field label="Slug" value={form.slug} onChange={(v) => setForm({ ...form, slug: v })} />
            <Field label="Group/subcategory" value={form.group_name || ""} onChange={(v) => setForm({ ...form, group_name: v })} />
            <Field label="Price" type="number" value={form.base_price} onChange={(v) => setForm({ ...form, base_price: v, price_on_request: false, direct_checkout: true })} />
            <Field label="Price label" value={form.price_label || ""} onChange={(v) => setForm({ ...form, price_label: v })} />
            <Field label="Serves" value={form.serves} onChange={(v) => setForm({ ...form, serves: v })} />
            <Field label="Sort order" type="number" value={form.sort_order} onChange={(v) => setForm({ ...form, sort_order: v })} />
            <Field label="Tags (comma separated)" value={form.tags} onChange={(v) => setForm({ ...form, tags: v })} />
            <Field label="Flavours (comma separated)" value={form.flavours} onChange={(v) => setForm({ ...form, flavours: v })} />
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.price_on_request} onChange={(e) => setForm({ ...form, price_on_request: e.target.checked, direct_checkout: e.target.checked ? false : form.direct_checkout })} /> Price on request</label>
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.direct_checkout} onChange={(e) => setForm({ ...form, direct_checkout: e.target.checked })} /> Direct checkout</label>
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.is_active} onChange={(e) => setForm({ ...form, is_active: e.target.checked })} /> Active</label>
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.is_featured} onChange={(e) => setForm({ ...form, is_featured: e.target.checked })} /> Featured</label>
            <div style={{ gridColumn: "1 / -1" }}><Field label="Description" area value={form.description} onChange={(v) => setForm({ ...form, description: v })} /></div>
            <div style={{ gridColumn: "1 / -1" }}><Field label="Combo pack included items (one per line)" area value={form.included_items || ""} onChange={(v) => setForm({ ...form, included_items: v })} /></div>
            <div style={{ gridColumn: "1 / -1", display: "grid", gridTemplateColumns: "minmax(150px,220px) 1fr", gap: 14, alignItems: "start" }}>
              <div style={{ height: 150, borderRadius: 12, border: "1px solid var(--c-line)", background: "var(--c-surface-2)", overflow: "hidden", display: "grid", placeItems: "center", color: "var(--c-ink-soft)", fontSize: 13 }}>
                {previewImage ? <img src={previewImage} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : "Image preview"}
              </div>
              <div style={{ display: "grid", gap: 10 }}>
                <label style={{ display: "grid", gap: 6 }}>
                  <span style={{ font: "700 12px/1 var(--font-body)", color: "var(--c-ink-soft)" }}>{form.id ? "Replace product image" : "Main product image"}</span>
                  <input style={input} type="file" accept="image/png,image/jpeg,image/webp" onChange={(event) => setImageFile(event.target.files?.[0] || null)} />
                  <span style={{ fontSize: 12, color: "var(--c-ink-faint)" }}>JPG, PNG or WebP only. Maximum 2MB per image and 4 images per product.</span>
                </label>
                {form.id && currentImages.length > 0 && (
                  <div style={{ display: "grid", gap: 8 }}>
                    {currentImages.map((image) => (
                      <div key={image.id} style={{ display: "grid", gridTemplateColumns: "54px 1fr auto auto", gap: 9, alignItems: "center", border: "1px solid var(--c-line)", borderRadius: 10, padding: 8 }}>
                        <img src={image.public_url} alt={image.alt_text || form.name || ""} style={{ width: 54, height: 44, borderRadius: 7, objectFit: "cover", background: "var(--c-surface-2)" }} />
                        <span style={{ font: "700 12px/1.2 var(--font-body)", color: image.is_primary ? "var(--c-accent)" : "var(--c-ink-soft)" }}>{image.is_primary ? "Primary image" : "Product image"}</span>
                        {!image.is_primary && <Btn size="sm" variant="outline" onClick={() => handleImageAction(() => API.setProductImagePrimaryAdmin(form.id, image.id))}>Set primary</Btn>}
                        <Btn size="sm" variant="ghost" onClick={() => handleImageAction(() => API.removeProductImageAdmin(image))}>Remove</Btn>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            </div>
          </div>}
          {formOpen && <>
          <div style={{ display: "flex", gap: 10, marginTop: 14, flexWrap: "wrap" }}>
            <Btn onClick={save}>{form.id ? "Update product" : "Add product"}</Btn>
            {form.id && <Btn variant="ghost" onClick={resetForm}>Cancel edit</Btn>}
          </div>
          <div style={{ marginTop: 12 }}><Notice>Individual cake prices can be added later. If no price is set, the website will show Price on request.</Notice></div>
          </>}
          {error && <div style={{ marginTop: 12 }}><Notice type="error">{error}</Notice></div>}
          {message && <div style={{ marginTop: 12 }}><Notice type="ok">{message}</Notice></div>}
        </div>
        {products.error && <Notice type="error">{products.error}</Notice>}
        <div style={{ display: "grid", gap: 12 }}>
          <div style={{ ...panel, display: "grid", gridTemplateColumns: "78px 1.2fr .9fr .7fr .6fr .6fr .7fr auto", gap: 10, alignItems: "center", paddingTop: 12, paddingBottom: 12, color: "var(--c-ink-soft)", font: "800 12px/1.2 var(--font-body)" }}>
            <span>Image</span><span>Product</span><span>Category / group</span><span>Price</span><span>Active</span><span>Featured</span><span>Image status</span><span>Edit</span>
          </div>
          {(products.data || []).map((item) => {
            const thumb = primaryImage(item);
            return (
            <div key={item.id} style={{ ...panel, display: "grid", gridTemplateColumns: "78px 1.2fr .9fr .7fr .6fr .6fr .7fr auto", gap: 10, alignItems: "center", paddingTop: 12, paddingBottom: 12 }}>
              <div style={{ width: 78, height: 64, borderRadius: 10, overflow: "hidden", background: "var(--c-surface-2)", border: "1px solid var(--c-line)", display: "grid", placeItems: "center", color: "var(--c-ink-faint)", fontSize: 12 }}>
                {thumb?.public_url ? <img src={thumb.public_url} alt={thumb.alt_text || item.name || ""} style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : "No image"}
              </div>
              <div>
                <h3 style={{ margin: "0 0 4px", font: "600 19px/1.05 var(--font-display)" }}>{item.name}</h3>
                <p style={{ margin: 0, color: "var(--c-ink-soft)", fontSize: 12 }}>{item.slug}</p>
              </div>
              <div style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>{item.categories?.name || "-"}<br />{item.group_name || "No group"}</div>
              <div style={{ fontWeight: 800, color: "var(--c-accent)", fontSize: 13 }}>{item.base_price == null ? (item.price_label || "Price on request") : money(item.base_price)}</div>
              <div style={{ fontWeight: 800, color: item.is_active ? "var(--ok)" : "var(--c-ink-faint)", fontSize: 12 }}>{item.is_active ? "Active" : "Hidden"}</div>
              <div style={{ fontWeight: 800, color: item.is_featured ? "var(--c-accent)" : "var(--c-ink-faint)", fontSize: 12 }}>{item.is_featured ? "Featured" : "-"}</div>
              <div style={{ fontSize: 12, color: thumb?.public_url ? "var(--ok)" : "var(--warn)" }}>{thumb?.public_url ? "Has image" : "No image"}</div>
              <div style={{ display: "grid", gap: 8, justifyItems: "end" }}>
                <Btn size="sm" variant="outline" onClick={() => edit(item)}>Edit</Btn>
                <Btn size="sm" variant="ghost" onClick={async () => { await API.archiveProductAdmin(item.id, !item.is_active); products.reload(); }}>{item.is_active ? "Hide" : "Show"}</Btn>
              </div>
            </div>
            );
          })}
        </div>
      </>
    );
  }

  function Categories() {
    const list = useAdminData(() => API.listCategoriesAdmin(), []);
    const empty = { slug: "", name: "", description: "", icon: "", parent_id: "", sort_order: 0, is_active: true };
    const [form, setForm] = useState(empty);
    const parentOptions = (list.data || []).filter((cat) => !cat.parent_id || cat.id === form.parent_id).map((cat) => ({ value: cat.id, label: cat.name }));
    const save = async () => {
      await API.saveCategoryAdmin(form);
      setForm(empty);
      list.reload();
    };
    return (
      <>
        <div style={panel}>
          <h2 style={{ font: "600 25px/1 var(--font-display)", margin: "0 0 14px" }}>{form.id ? "Edit category" : "Add category"}</h2>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(180px,1fr))", gap: 12 }}>
            <Field label="Name" value={form.name} onChange={(v) => setForm({ ...form, name: v })} />
            <Field label="Slug" value={form.slug} onChange={(v) => setForm({ ...form, slug: v })} />
            <Field label="Icon" value={form.icon} onChange={(v) => setForm({ ...form, icon: v })} />
            <Field label="Parent category" value={form.parent_id || ""} onChange={(v) => setForm({ ...form, parent_id: v })} options={[{ value: "", label: "Top-level category" }, ...parentOptions]} />
            <Field label="Sort order" type="number" value={form.sort_order} onChange={(v) => setForm({ ...form, sort_order: v })} />
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.is_active} onChange={(e) => setForm({ ...form, is_active: e.target.checked })} /> Active</label>
            <div style={{ gridColumn: "1 / -1" }}><Field label="Description" area value={form.description} onChange={(v) => setForm({ ...form, description: v })} /></div>
          </div>
          <div style={{ display: "flex", gap: 10, marginTop: 14 }}><Btn onClick={save}>{form.id ? "Update category" : "Add category"}</Btn>{form.id && <Btn variant="ghost" onClick={() => setForm(empty)}>Cancel</Btn>}</div>
        </div>
        {list.error && <Notice type="error">{list.error}</Notice>}
        {(list.data || []).map((cat) => (
          <div key={cat.id} style={{ ...panel, display: "flex", justifyContent: "space-between", gap: 12 }}>
            <div><strong>{cat.name}</strong><div style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>{cat.slug} · order {cat.sort_order} · {cat.is_active ? "active" : "inactive"}</div></div>
            <Btn size="sm" variant="outline" onClick={() => setForm(cat)}>Edit</Btn>
          </div>
        ))}
      </>
    );
  }

  function CustomRequests() {
    const list = useAdminData(() => API.listCustomCakeRequestsAdmin(), []);
    const [selected, setSelected] = useState(null);
    const active = selected || list.data?.[0];
    const [status, setStatus] = useState("");
    const [notes, setNotes] = useState("");
    useEffect(() => { setStatus(active?.status || "new"); setNotes(active?.internal_notes || ""); }, [active?.id]);
    const save = async () => {
      if (!active) return;
      await API.updateCustomCakeRequestAdmin(active.id, { status, internal_notes: notes });
      list.reload();
    };
    return (
      <div style={{ display: "grid", gridTemplateColumns: "minmax(220px,.8fr) 1.2fr", gap: 14 }}>
        <div style={{ display: "grid", gap: 10 }}>
          {(list.data || []).map((req) => (
            <button key={req.id} onClick={() => setSelected(req)} style={{ ...panel, textAlign: "left", cursor: "pointer", borderColor: active?.id === req.id ? "var(--c-accent)" : "var(--c-line)" }}>
              <strong>{req.contact_name || "Unnamed request"}</strong>
              <div style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>{titleize(req.status)} · {req.required_date || "date TBC"}</div>
            </button>
          ))}
          {!list.loading && !list.data?.length && <Notice>No custom cake requests yet.</Notice>}
        </div>
        <div style={panel}>
          {active ? <>
            <h2 style={{ font: "600 26px/1 var(--font-display)", margin: "0 0 10px" }}>{active.occasion || "Custom cake request"}</h2>
            <p style={{ color: "var(--c-ink-soft)", marginTop: 0 }}>{active.contact_name} · {active.contact_email || active.contact_phone}</p>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, fontSize: 14, marginBottom: 14 }}>
              <div><strong>Servings</strong><br />{active.servings || "-"}</div>
              <div><strong>Flavour</strong><br />{active.flavour || "-"}</div>
              <div><strong>Style</strong><br />{active.design_style || "-"}</div>
              <div><strong>Fulfilment</strong><br />{active.fulfilment_type}</div>
            </div>
            <p style={{ whiteSpace: "pre-wrap", color: "var(--c-ink-soft)" }}>{active.notes || "No notes supplied."}</p>
            <Field label="Status" value={status} onChange={setStatus} options={statuses} />
            <div style={{ height: 10 }} />
            <Field label="Internal notes" area value={notes} onChange={setNotes} />
            <div style={{ marginTop: 14 }}><Btn onClick={save}>Save request</Btn></div>
          </> : <Notice>Select a request.</Notice>}
        </div>
      </div>
    );
  }

  function Orders() {
    const list = useAdminData(() => API.listOrdersAdmin(), []);
    return (
      <div style={panel}>
        <h2 style={{ font: "600 27px/1 var(--font-display)", margin: "0 0 8px" }}>Orders</h2>
        <Notice>Online paid orders will be enabled in the Square checkout phase.</Notice>
        {(list.data || []).map((order) => <p key={order.id}>{order.order_number} · {titleize(order.status)} · {money(order.total)}</p>)}
      </div>
    );
  }

  function HeroSettings() {
    const settings = useAdminData(() => API.getSettingsAdmin(), []);
    const fallback = { eyebrow_text: "Order online · same-week pickup", headline: "The cake shop,", highlight_text: "open all hours.", subheading: "Browse the full menu, customise every detail, schedule pickup or delivery and pay securely with Square — Darwin's complete online cake order.", image_url: "", image_alt: "The Cakerz", primary_cta_label: "Start an order", primary_cta_link: "/menu", secondary_cta_label: "Request a custom cake", secondary_cta_link: "/custom-cakes", trust_points: "Secure Square checkout, Darwin-wide delivery, 48h custom notice", is_active: true };
    const [hero, setHero] = useState(fallback);
    const [message, setMessage] = useState("");
    const [error, setError] = useState("");
    useEffect(() => {
      if (!settings.data) return;
      const nextHero = settings.data.hero || fallback;
      setHero({
        ...fallback,
        ...nextHero,
        trust_points: Array.isArray(nextHero.trust_points) ? nextHero.trust_points.join(", ") : nextHero.trust_points || fallback.trust_points,
        is_active: nextHero.is_active !== false,
      });
    }, [settings.data?.hero?.id, settings.data?.hero?.updated_at, settings.data]);
    const save = async () => {
      setMessage("");
      setError("");
      try {
        await API.saveHomepageHeroAdmin(hero);
        settings.reload();
        setMessage("Homepage hero saved.");
      } catch (saveError) {
        setError(saveError.message || "Homepage hero could not be saved.");
      }
    };
    const uploadHeroImage = async (file) => {
      if (!file) return;
      setMessage("");
      setError("");
      try {
        const imageUrl = await API.uploadHomepageHeroImageAdmin(file);
        setHero({ ...hero, image_url: imageUrl });
        setMessage("Hero image uploaded. Save the hero to publish it.");
      } catch (uploadError) {
        setError(uploadError.message || "Hero image could not be uploaded.");
      }
    };
    if (settings.loading) return <Notice>Loading homepage hero...</Notice>;
    if (settings.error) return <Notice type="error">{settings.error}</Notice>;
    return (
      <div style={panel}>
        <h2 style={{ font: "600 25px/1 var(--font-display)", margin: "0 0 14px" }}>Homepage Hero</h2>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(210px,1fr))", gap: 12 }}>
          <Field label="Eyebrow text" value={hero.eyebrow_text} onChange={(v) => setHero({ ...hero, eyebrow_text: v })} />
          <Field label="Headline" value={hero.headline} onChange={(v) => setHero({ ...hero, headline: v })} />
          <Field label="Italic/highlight text" value={hero.highlight_text} onChange={(v) => setHero({ ...hero, highlight_text: v })} />
          <Field label="Primary CTA label" value={hero.primary_cta_label} onChange={(v) => setHero({ ...hero, primary_cta_label: v })} />
          <Field label="Primary CTA link" value={hero.primary_cta_link} onChange={(v) => setHero({ ...hero, primary_cta_link: v })} />
          <Field label="Secondary CTA label" value={hero.secondary_cta_label} onChange={(v) => setHero({ ...hero, secondary_cta_label: v })} />
          <Field label="Secondary CTA link" value={hero.secondary_cta_link} onChange={(v) => setHero({ ...hero, secondary_cta_link: v })} />
          <Field label="Image URL" value={hero.image_url || ""} onChange={(v) => setHero({ ...hero, image_url: v })} />
          <Field label="Image alt text" value={hero.image_alt || ""} onChange={(v) => setHero({ ...hero, image_alt: v })} />
          <Field label="Trust points (comma separated)" value={hero.trust_points || ""} onChange={(v) => setHero({ ...hero, trust_points: v })} />
          <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!hero.is_active} onChange={(e) => setHero({ ...hero, is_active: e.target.checked })} /> Active</label>
          <label style={{ display: "grid", gap: 6 }}>
            <span style={{ font: "700 12px/1 var(--font-body)", color: "var(--c-ink-soft)" }}>Hero image/logo/image asset</span>
            <input style={input} type="file" accept="image/png,image/jpeg,image/webp" onChange={(event) => uploadHeroImage(event.target.files?.[0])} />
            <span style={{ fontSize: 12, color: "var(--c-ink-faint)" }}>JPG, PNG or WebP only. Maximum 2MB.</span>
          </label>
          <div style={{ gridColumn: "1 / -1" }}><Field label="Subheading" area value={hero.subheading} onChange={(v) => setHero({ ...hero, subheading: v })} /></div>
        </div>
        {hero.image_url && <div style={{ marginTop: 14, width: 220, height: 140, borderRadius: 12, overflow: "hidden", border: "1px solid var(--c-line)", background: "var(--c-surface-2)" }}><img src={hero.image_url} alt={hero.image_alt || ""} style={{ width: "100%", height: "100%", objectFit: "cover" }} /></div>}
        <div style={{ marginTop: 14 }}><Btn onClick={save}>Save homepage hero</Btn></div>
        {error && <div style={{ marginTop: 12 }}><Notice type="error">{error}</Notice></div>}
        {message && <div style={{ marginTop: 12 }}><Notice type="ok">{message}</Notice></div>}
      </div>
    );
  }

  function Reviews() {
    const list = useAdminData(() => API.listReviewsAdmin(), []);
    const products = useAdminData(() => API.listProductsAdmin(), []);
    const empty = { customer_name: "", suburb: "", rating: 5, review_text: "", status: "pending", is_featured: false, display_order: 0, product_id: "", product_slug: "" };
    const [form, setForm] = useState(empty);
    const [message, setMessage] = useState("");
    const [error, setError] = useState("");
    const productOptions = (products.data || []).filter((product) => product.kind === "cake").map((product) => ({ value: product.id, label: `${product.name}${product.group_name ? ` · ${product.group_name}` : ""}`, slug: product.slug }));
    const setReviewProduct = (productId) => {
      const selected = productOptions.find((product) => product.value === productId);
      setForm({ ...form, product_id: productId, product_slug: selected?.slug || "" });
    };
    const save = async () => {
      setMessage("");
      setError("");
      try {
        await API.saveReviewAdmin(form);
        setForm(empty);
        list.reload();
        setMessage("Review saved.");
      } catch (saveError) {
        setError(saveError.message || "Review could not be saved.");
      }
    };
    const updateReview = async (review, patch) => {
      setMessage("");
      setError("");
      try {
        await API.saveReviewAdmin({ ...review, ...patch });
        list.reload();
        setMessage("Review updated.");
      } catch (updateError) {
        setError(updateError.message || "Review could not be updated.");
      }
    };
    const removeReview = async (review) => {
      setMessage("");
      setError("");
      try {
        await API.deleteReviewAdmin(review.id);
        if (form.id === review.id) setForm(empty);
        list.reload();
        setMessage("Review deleted.");
      } catch (deleteError) {
        setError(deleteError.message || "Review could not be deleted.");
      }
    };
    return (
      <>
        <Notice>Customer reviews are managed from Admin → Reviews. Approved reviews appear on the website. Featured review appears in the hero badge with the linked cake photo when a related cake is selected.</Notice>
        <div style={panel}>
          <h2 style={{ font: "600 25px/1 var(--font-display)", margin: "0 0 14px" }}>{form.id ? "Edit review" : "Add review"}</h2>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 12 }}>
            <Field label="Customer name" value={form.customer_name} onChange={(v) => setForm({ ...form, customer_name: v })} />
            <Field label="Suburb/location" value={form.suburb || ""} onChange={(v) => setForm({ ...form, suburb: v })} />
            <Field label="Related cake photo" value={form.product_id || ""} onChange={setReviewProduct} options={[{ value: "", label: "No linked cake" }, ...productOptions]} />
            <Field label="Rating" type="number" value={form.rating} onChange={(v) => setForm({ ...form, rating: v })} />
            <Field label="Status" value={form.status} onChange={(v) => setForm({ ...form, status: v })} options={["pending", "approved", "rejected"]} />
            <Field label="Display order" type="number" value={form.display_order} onChange={(v) => setForm({ ...form, display_order: v })} />
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.is_featured} onChange={(e) => setForm({ ...form, is_featured: e.target.checked })} /> Featured</label>
            <div style={{ gridColumn: "1 / -1" }}><Field label="Review text" area value={form.review_text} onChange={(v) => setForm({ ...form, review_text: v })} /></div>
          </div>
          <div style={{ display: "flex", gap: 10, marginTop: 14 }}>
            <Btn onClick={save}>{form.id ? "Update review" : "Add review"}</Btn>
            {form.id && <Btn variant="ghost" onClick={() => setForm(empty)}>Cancel</Btn>}
          </div>
          {error && <div style={{ marginTop: 12 }}><Notice type="error">{error}</Notice></div>}
          {message && <div style={{ marginTop: 12 }}><Notice type="ok">{message}</Notice></div>}
        </div>
        {list.error && <Notice type="error">{list.error}</Notice>}
        <div style={{ display: "grid", gap: 12 }}>
          {(list.data || []).map((review) => (
            <div key={review.id} style={{ ...panel, display: "grid", gridTemplateColumns: "1fr auto", gap: 14 }}>
              <div>
                <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap", marginBottom: 6 }}>
                  <strong>{review.customer_name}</strong>
                  <span style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>{review.suburb || "No location"} · {review.status} · order {review.display_order}</span>
                  {review.product_name && <span style={{ color: "var(--c-ink-soft)", fontSize: 13 }}>Cake photo: {review.product_name}</span>}
                  {review.is_featured && <span style={{ color: "var(--c-accent)", fontWeight: 800, fontSize: 12 }}>Featured</span>}
                </div>
                <Stars n={Number(review.rating || 5)} s={13} />
                <p style={{ margin: "8px 0 0", color: "var(--c-ink-soft)", fontSize: 14 }}>{review.review_text}</p>
              </div>
              <div style={{ display: "grid", gap: 8, justifyItems: "end" }}>
                <Btn size="sm" variant="outline" onClick={() => setForm(review)}>Edit</Btn>
                {review.status !== "approved" && <Btn size="sm" variant="ghost" onClick={() => updateReview(review, { status: "approved" })}>Approve</Btn>}
                {review.status !== "rejected" && <Btn size="sm" variant="ghost" onClick={() => updateReview(review, { status: "rejected" })}>Reject</Btn>}
                <Btn size="sm" variant={review.is_featured ? "outline" : "ghost"} onClick={() => updateReview(review, { is_featured: !review.is_featured })}>{review.is_featured ? "Unfeature" : "Feature"}</Btn>
                <Btn size="sm" variant="ghost" onClick={() => removeReview(review)}>Delete</Btn>
              </div>
            </div>
          ))}
          {!list.loading && !list.data?.length && <Notice>No reviews yet.</Notice>}
        </div>
      </>
    );
  }

  function Settings() {
    const settings = useAdminData(() => API.getSettingsAdmin(), []);
    const [store, setStore] = useState(null);
    useEffect(() => {
      if (settings.data?.store) {
        setStore({
          ...settings.data.store,
          business_hours: settings.data.store.business_hours || defaultBusinessHours,
        });
      }
    }, [settings.data?.store?.id, settings.data?.store?.updated_at]);
    if (settings.loading) return <Notice>Loading settings...</Notice>;
    if (settings.error) return <Notice type="error">{settings.error}</Notice>;
    return (
      <>
        <div style={panel}>
          <h2 style={{ font: "600 25px/1 var(--font-display)", margin: "0 0 14px" }}>Store settings</h2>
          {store && <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(190px,1fr))", gap: 12 }}>
            <Field label="Store name" value={store.store_name} onChange={(v) => setStore({ ...store, store_name: v })} />
            <Field label="Email" value={store.store_email || ""} onChange={(v) => setStore({ ...store, store_email: v })} />
            <Field label="Phone" value={store.store_phone || ""} onChange={(v) => setStore({ ...store, store_phone: v })} />
            <Field label="Address" value={store.address_line || ""} onChange={(v) => setStore({ ...store, address_line: v })} />
            <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!store.is_accepting_orders} onChange={(e) => setStore({ ...store, is_accepting_orders: e.target.checked })} /> Accepting orders</label>
            <div style={{ gridColumn: "1 / -1" }}><Field label="Order notice" area value={store.order_notice || ""} onChange={(v) => setStore({ ...store, order_notice: v })} /></div>
            <div style={{ gridColumn: "1 / -1" }}><BusinessHoursEditor hours={store.business_hours || defaultBusinessHours} onChange={(hours) => setStore({ ...store, business_hours: hours })} /></div>
            <div style={{ gridColumn: "1 / -1" }}><Btn onClick={async () => { await API.saveStoreSettingsAdmin(store); settings.reload(); }}>Save store settings</Btn></div>
          </div>}
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit,minmax(260px,1fr))", gap: 14 }}>
          {(settings.data?.fulfilment || []).map((item) => <FulfilmentCard key={item.id} item={item} reload={settings.reload} />)}
        </div>
        <div style={panel}>
          <h2 style={{ font: "600 25px/1 var(--font-display)", margin: "0 0 8px" }}>Pickup times</h2>
          <Notice>Frontend pickup time choices now come from business hours above. Individual time slots are kept in the database for compatibility but hidden here to avoid confusing daily operations.</Notice>
        </div>
      </>
    );
  }

  function BusinessHoursEditor({ hours, onChange }) {
    const safeHours = hours || defaultBusinessHours;
    const updateDay = (day, patch) => {
      onChange({
        ...safeHours,
        [day]: { ...(safeHours[day] || defaultBusinessHours[day]), ...patch },
      });
    };
    return (
      <div style={{ display: "grid", gap: 8 }}>
        <div style={{ font: "700 12px/1 var(--font-body)", color: "var(--c-ink-soft)" }}>Business hours for pickup time choices</div>
        {days.map((dayName, day) => {
          const row = safeHours[day] || defaultBusinessHours[day];
          return (
            <div key={dayName} style={{ display: "grid", gridTemplateColumns: "70px 1fr 1fr 90px", gap: 8, alignItems: "center" }}>
              <strong style={{ fontSize: 13 }}>{dayName}</strong>
              <input style={input} type="time" value={row.open || "08:00"} disabled={row.closed} onChange={(e) => updateDay(day, { open: e.target.value })} />
              <input style={input} type="time" value={row.close || "16:00"} disabled={row.closed} onChange={(e) => updateDay(day, { close: e.target.value })} />
              <label style={{ display: "flex", gap: 6, alignItems: "center", fontSize: 13, fontWeight: 800 }}><input type="checkbox" checked={!!row.closed} onChange={(e) => updateDay(day, { closed: e.target.checked })} /> Closed</label>
            </div>
          );
        })}
      </div>
    );
  }

  function FulfilmentCard({ item, reload }) {
    const [form, setForm] = useState(item);
    return (
      <div style={panel}>
        <h3 style={{ marginTop: 0 }}>{titleize(item.fulfilment_type)}</h3>
        <div style={{ display: "grid", gap: 10 }}>
          <Field label="Display name" value={form.display_name} onChange={(v) => setForm({ ...form, display_name: v })} />
          <Field label="Description" area value={form.description || ""} onChange={(v) => setForm({ ...form, description: v })} />
          <Field label="Minimum order" type="number" value={form.minimum_order_total} onChange={(v) => setForm({ ...form, minimum_order_total: v })} />
          <Field label="Fee" type="number" value={form.fee} onChange={(v) => setForm({ ...form, fee: v })} />
          <Field label="Free over" type="number" value={form.free_over || ""} onChange={(v) => setForm({ ...form, free_over: v })} />
          <Field label="Lead time hours" type="number" value={form.lead_time_hours} onChange={(v) => setForm({ ...form, lead_time_hours: v })} />
          <label style={{ display: "flex", alignItems: "center", gap: 8, fontWeight: 800 }}><input type="checkbox" checked={!!form.is_enabled} onChange={(e) => setForm({ ...form, is_enabled: e.target.checked })} /> Enabled</label>
          <Btn onClick={async () => { await API.saveFulfilmentSettingAdmin(form); reload(); }}>Save {item.fulfilment_type}</Btn>
        </div>
      </div>
    );
  }

  function TimeSlot({ slot, reload }) {
    const [form, setForm] = useState(slot);
    return (
      <div style={{ display: "grid", gridTemplateColumns: "1fr 90px 100px auto", gap: 10, alignItems: "center", borderBottom: "1px solid var(--c-line)", padding: "8px 0" }}>
        <span>{days[slot.day_of_week]} · {slot.slot_time} · {slot.fulfilment_type}</span>
        <input style={input} type="number" value={form.capacity} onChange={(e) => setForm({ ...form, capacity: e.target.value })} />
        <label style={{ display: "flex", alignItems: "center", gap: 6 }}><input type="checkbox" checked={!!form.is_active} onChange={(e) => setForm({ ...form, is_active: e.target.checked })} /> Active</label>
        <Btn size="sm" variant="outline" onClick={async () => { await API.saveTimeSlotAdmin(form); reload(); }}>Save</Btn>
      </div>
    );
  }

  function AdminShell({ section, mobile }) {
    const active = section || "dashboard";
    const [profile, setProfile] = useState(null);
    const [checking, setChecking] = useState(true);
    const [authVersion, setAuthVersion] = useState(0);
    const [configReady, setConfigReady] = useState(Boolean(window.CAKERZ_CONFIG));
    useEffect(() => {
      const markReady = () => setConfigReady(true);
      if (window.CAKERZ_CONFIG) markReady();
      window.addEventListener("cakerz-config-ready", markReady);
      return () => window.removeEventListener("cakerz-config-ready", markReady);
    }, []);
    useEffect(() => {
      let alive = true;
      if (!configReady) {
        setChecking(true);
        return () => { alive = false; };
      }
      if (!API.hasSupabaseConfig()) {
        setChecking(false);
        return () => { alive = false; };
      }
      API.getAdminProfile()
        .then((nextProfile) => alive && setProfile(nextProfile))
        .catch(() => alive && setProfile(null))
        .finally(() => alive && setChecking(false));
      return () => { alive = false; };
    }, [authVersion, configReady]);

    if (!configReady) return <main style={{ ...PG, padding: "54px 22px" }}><Notice>Checking admin config...</Notice></main>;
    if (!API.hasSupabaseConfig()) {
      return <main style={{ ...PG, maxWidth: 720, padding: "54px 22px" }}><Notice type="error">Supabase public config is missing. Add `VITE_SUPABASE_URL` and `VITE_SUPABASE_ANON_KEY` before using admin.</Notice></main>;
    }
    if (checking) return <main style={{ ...PG, padding: "54px 22px" }}><Notice>Checking admin session...</Notice></main>;
    if (!profile || active === "login") return <Login onLogin={() => { setAuthVersion((v) => v + 1); goAdmin("dashboard"); }} />;

    const logout = async () => {
      await API.logoutAdmin();
      setProfile(null);
      goAdmin("login");
    };
    const pages = {
      dashboard: <Dashboard />,
      products: <Products />,
      categories: <Categories />,
      reviews: <Reviews />,
      hero: <HeroSettings />,
      "custom-cakes": <CustomRequests />,
      orders: <Orders />,
      settings: <Settings />,
    };
    return <AdminChrome section={pages[active] ? active : "dashboard"} profile={profile} onLogout={logout} mobile={mobile}>{pages[active] || pages.dashboard}</AdminChrome>;
  }

  window.CakerzAdmin = { AdminShell };
})();
