// Extra admin tabs: visitor counter, blog editor, page-content editor, settings.
// Lives in its own file so pages-admin.jsx doesn't balloon.

// ---------- Visitor counter (sits above the orders table) ----------
function VisitorCounterRow() {
  const app = useApp();
  const c = app.counter;
  if (!c) return null;
  // Build a tiny 30-day sparkline from days[]
  const days = c.days || [];
  const max = Math.max(1, ...days.map(d => d.count));
  return (
    <div className="stitched stitched-sage" style={{ padding: 18, marginBottom: 24 }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", flexWrap: "wrap", gap: 16 }}>
        <div>
          <div className="smallcaps" style={{ color: "var(--sage-deep)", marginBottom: 6 }}>Site visitors</div>
          <div style={{ display: "flex", gap: 28, alignItems: "baseline", flexWrap: "wrap" }}>
            <CounterStat label="Total" value={c.total ?? 0} />
            <CounterStat label="Today" value={c.today ?? 0} />
            <CounterStat label="Last 7 days" value={c.last7 ?? 0} />
          </div>
          <div className="mono" style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 6 }}>
            Counts unique browsers, with a 12-hour cool-down so reloads don't inflate the number.
          </div>
        </div>
        {days.length > 0 && (
          <svg viewBox={`0 0 ${Math.max(120, days.length * 8)} 44`} width={Math.max(120, days.length * 8)} height="44" aria-hidden="true" style={{ flexShrink: 0 }}>
            {days.map((d, i) => {
              const h = Math.max(2, (Number(d.count) / max) * 38);
              return <rect key={i} x={i * 8} y={44 - h} width="6" height={h} rx="1.5" fill="var(--sage-deep)" opacity="0.75" />;
            })}
          </svg>
        )}
        <div style={{ display: "flex", gap: 6 }}>
          <button className="btn btn-ghost btn-small" onClick={() => app.refreshCounter?.()}>Refresh</button>
          <button className="btn btn-ghost btn-small" onClick={() => { if (confirm("Reset the visitor counter to zero?")) app.resetCounter?.(); }} style={{ color: "var(--rose-deep)" }}>Reset</button>
        </div>
      </div>
    </div>
  );
}

function CounterStat({ label, value }) {
  return (
    <div>
      <div style={{ fontSize: 36, fontFamily: "'Cormorant Garamond', serif", color: "var(--ink)", lineHeight: 1 }}>{Number(value).toLocaleString()}</div>
      <div className="smallcaps" style={{ color: "var(--ink-3)", fontSize: 11, marginTop: 4 }}>{label}</div>
    </div>
  );
}

// ---------- Blog management ----------
function AdminBlog() {
  const app = useApp();
  const posts = (app.allBlogPosts || []).slice().sort((a, b) => b.createdAt - a.createdAt);
  const [editing, setEditing] = useState(null);
  const [creating, setCreating] = useState(false);
  return (
    <div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16, flexWrap: "wrap", gap: 10 }}>
        <div>
          <h2>Studio journal</h2>
          <p style={{ color: "var(--ink-2)", margin: "4px 0 0" }}>Write blog posts for the journal — they appear on the home page and the journal index.</p>
        </div>
        <button className="btn" onClick={() => setCreating(true)}>+ Write a new post</button>
      </div>

      {posts.length === 0 ? (
        <div className="stitched stitched-sage" style={{ textAlign: "center", padding: 40 }}>
          <p style={{ color: "var(--ink-2)" }}>No posts yet. Write your first journal entry!</p>
          <button className="btn" onClick={() => setCreating(true)}>+ Write a new post</button>
        </div>
      ) : (
        <div style={{ display: "grid", gap: 12 }}>
          {posts.map(p => (
            <div className="stitched" key={p.id} style={{ padding: 18 }}>
              <div style={{ display: "grid", gridTemplateColumns: "120px 1fr auto", gap: 18, alignItems: "center" }}>
                <div style={{ width: 120, height: 90, borderRadius: 8, overflow: "hidden", background: "var(--paper-2)" }}>
                  {p.image
                    ? <img src={p.image} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                    : <Placeholder label="no photo" variant="sage" />}
                </div>
                <div>
                  <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 4 }}>
                    <strong style={{ fontSize: 19 }}>{p.title}</strong>
                    {p.published
                      ? <span className="tag tag-ready">Published</span>
                      : <span className="tag tag-new">Draft</span>}
                  </div>
                  <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>
                    {fmtDate(p.createdAt)} · /blog/{p.slug}
                  </div>
                  <p style={{ color: "var(--ink-2)", margin: "8px 0 0", fontSize: 15 }}>{p.excerpt || (p.content || "").slice(0, 140) + "…"}</p>
                </div>
                <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
                  <a className="btn btn-ghost btn-small" href={`#/blog/${p.slug}`}>View</a>
                  <button className="btn btn-ghost btn-small" onClick={() => setEditing(p)}>Edit</button>
                  <button className="btn btn-ghost btn-small" onClick={() => { if (confirm("Delete this post? This cannot be undone.")) app.deleteBlogPost(p.id); }} style={{ color: "var(--rose-deep)" }}>Delete</button>
                </div>
              </div>
            </div>
          ))}
        </div>
      )}

      {creating && (
        <Modal open onClose={() => setCreating(false)}>
          <h2 style={{ marginBottom: 14 }}>Write a new post</h2>
          <BlogPostForm 
            initial={{ title: "", slug: "", excerpt: "", content: "", tags: "", image: "", published: true }} 
            submitLabel="Save post" 
            onSubmit={async (formData) => {
              try {
                await app.addBlogPost(formData);
                app.toast("Post saved!");
                setCreating(false);
              } catch (err) {
                app.toast(err.message || "Couldn't save — try again.");
              }
            }} 
          />
        </Modal>
      )}
     {editing && (
        <Modal open onClose={() => setEditing(null)}>
          <h2 style={{ marginBottom: 14 }}>Edit post</h2>
          <BlogPostForm 
            initial={{ ...editing, tags: (editing.tags || []).join(", ") }} 
            submitLabel="Save changes" 
            onSubmit={async (formData) => {
              try {
                await app.updateBlogPost(editing.id, formData);
                app.toast("Saved!");
                setEditing(null);
              } catch (err) {
                app.toast(err.message || "Couldn't save — try again.");
              }
            }} 
          />
        </Modal>
      )}
    </div>
  );
}

function BlogPostForm({ initial, submitLabel, onSubmit }) {
  const [f, setF] = useState({ ...initial });
  const [imageFile, setImageFile] = useState(null);
  const [uploading, setUploading] = useState(false); // Track upload state
  const set = (k, v) => setF(s => ({ ...s, [k]: v }));
  const fileRef = useRef(null);

  const handleImage = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setImageFile(file);
    const dataUrl = await readFileAsDataURL(file);
    set("image", dataUrl); // Keeps local UI preview working perfectly
  };

 const submit = async (e) => {
    e.preventDefault();
    if (!f.title) return;

    // 1. Create a unified FormData instance
    const formData = new FormData();
    
    // 2. Pack all standard text parameter keys
    formData.append("title", f.title);
    formData.append("slug", f.slug || "");
    formData.append("excerpt", f.excerpt || "");
    formData.append("content", f.content || "");
    formData.append("tags", f.tags || "");
    formData.append("published", f.published ? "1" : "0");

    // 3. Grab the raw file directly from your component's imageFile state
    if (imageFile) {
      formData.append("image", await shrinkImageForUpload(imageFile)); // This matches your backend upload.single("image") expectations!
    } else if (f.image && !f.image.startsWith("data:")) {
      formData.append("image", f.image); // Keeps the old filename if editing without updating the photo
    }

    // 4. Send the whole bundle down to your working context handlers
    onSubmit(formData);
  };
  return (
    <form onSubmit={submit}>
      <div className="field">
        <label>Title</label>
        <input value={f.title} onChange={e => set("title", e.target.value)} placeholder="On the hoop this week…" autoFocus />
      </div>
      <div className="field-row">
        <div className="field">
          <label>Slug (URL) <span className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>· optional</span></label>
          <input value={f.slug || ""} onChange={e => set("slug", e.target.value)} placeholder="on-the-hoop-this-week" />
          <div className="field-hint">Leave blank — we'll make a nice slug from the title.</div>
        </div>
        <div className="field">
          <label>Tags <span className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>· comma-separated</span></label>
          <input value={f.tags || ""} onChange={e => set("tags", e.target.value)} placeholder="studio, wedding" />
        </div>
      </div>
      <div className="field">
        <label>Excerpt (short summary, ~1–2 sentences)</label>
        <textarea rows="2" value={f.excerpt || ""} onChange={e => set("excerpt", e.target.value)} placeholder="A quick peek at what's on the hoop this week." />
      </div>
      <div className="field">
        <label>Post body</label>
        <textarea rows="10" value={f.content || ""} onChange={e => set("content", e.target.value)} placeholder="Write your post here — leave a blank line between paragraphs." style={{ fontFamily: "inherit", fontSize: 17, lineHeight: 1.6 }} />
        <div className="field-hint">Plain text with paragraph breaks. We'll format it for you.</div>
      </div>
      <div className="field">
        <label>Cover image (optional)</label>
        <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
          <div style={{ width: 160, height: 100, borderRadius: 10, overflow: "hidden", border: "1px dashed var(--rose)", background: "var(--paper-2)" }}>
            {f.image ? <img src={f.image} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : <Placeholder label="no cover" />}
          </div>
          <div>
            <button type="button" className="btn btn-ghost btn-small" onClick={() => fileRef.current?.click()}>{f.image ? "Replace image" : "Choose image"}</button>
            <input type="file" accept="image/*" ref={fileRef} style={{ display: "none" }} onChange={handleImage} />
            {f.image && <button type="button" className="btn btn-ghost btn-small" onClick={() => { set("image", ""); setImageFile(null); }} style={{ marginLeft: 6, color: "var(--rose-deep)" }}>Remove</button>}
          </div>
        </div>
      </div>
      <div className="field" style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <input type="checkbox" id="post-published" checked={!!f.published} onChange={e => set("published", e.target.checked)} style={{ width: 18, height: 18 }} />
        <label htmlFor="post-published" style={{ margin: 0 }}>Published <span className="mono" style={{ fontSize: 12, color: "var(--ink-3)" }}>(uncheck to save as draft)</span></label>
      </div>
      <button className="btn" type="submit" disabled={uploading}>
        {uploading ? "Uploading image..." : submitLabel}
      </button>
    </form>
  );
}

// ---------- Page content editor ----------
const CONTENT_BLOCKS = [
  {
    key: "home_studio_title",
    page: "Home page",
    label: "Studio section · headline",
    kind: "text",
    placeholder: "Small studio. Big love for the little details.",
    help: "Headline shown above the 'About the studio' block on the home page.",
  },
  {
    key: "home_studio_body",
    page: "Home page",
    label: "Studio section · body",
    kind: "longtext",
    placeholder: "Every order at Hazelbelle is hand-finished…",
    help: "The little paragraph next to the studio photo. Plain text; line breaks are kept.",
  },
  {
    key: "home_studio_image",
    page: "Home page",
    label: "Studio section · photo",
    kind: "image",
    help: "The photo shown next to the studio paragraph. JPG/PNG up to 8MB.",
  },
  {
    key: "about_intro",
    page: "About page",
    label: "Intro paragraph (top, larger text)",
    kind: "longtext",
    placeholder: "Hazelbelle started at my kitchen table…",
    help: "The first paragraph at the top of the About page.",
  },
  {
    key: "about_body",
    page: "About page",
    label: "Second paragraph(s)",
    kind: "longtext",
    placeholder: "Tell more of your story here. Blank lines start new paragraphs.",
    help: "Optional. Leave blank to keep the default two paragraphs.",
  },
  {
    key: "about_love",
    page: "About page",
    label: "“What I love stitching” list",
    kind: "longtext",
    placeholder: "Personalised baby blankets & christening gifts\nTeam kit, club polos & uniforms\nMemory pieces from a loved one's shirt",
    help: "One item per line. Becomes a bullet list.",
  },
  {
    key: "about_photo_1",
    page: "About page",
    label: "Photo · Joy at the machine",
    kind: "image",
  },
  {
    key: "about_photo_2",
    page: "About page",
    label: "Photo · thread cupboard / second polaroid",
    kind: "image",
  },
];

function AdminContent() {
  const app = useApp();
  const groupedByPage = CONTENT_BLOCKS.reduce((acc, b) => {
    (acc[b.page] = acc[b.page] || []).push(b);
    return acc;
  }, {});
  return (
    <div>
      <h2>Edit pages</h2>
      <p style={{ color: "var(--ink-2)", margin: "4px 0 18px" }}>
        Update the wording &amp; photos for the About page and the studio block on the home page.
        Leave a field blank to keep the original default.
      </p>
      {Object.entries(groupedByPage).map(([page, blocks]) => (
        <div key={page} className="stitched" style={{ marginBottom: 22 }}>
          <h3 style={{ marginBottom: 14 }}>{page}</h3>
          {blocks.map(b => <ContentBlockEditor key={b.key} block={b} current={app.siteContent?.[b.key]} />)}
        </div>
      ))}
    </div>
  );
}

function ContentBlockEditor({ block, current }) {
  const app = useApp();
  const [text, setText] = useState(current?.value || "");
  const [imagePreview, setImagePreview] = useState(current?.image || "");
  const [imageFile, setImageFile] = useState(null);
  const [busy, setBusy] = useState(false);
  const fileRef = useRef(null);

  // Keep local state in sync if the backing record changes (e.g. after save).
  useEffect(() => { setText(current?.value || ""); }, [current?.value]);
  useEffect(() => { setImagePreview(current?.image || ""); }, [current?.image]);

  const handleImage = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setImageFile(file);
    setImagePreview(await readFileAsDataURL(file));
  };

  const save = async () => {
    setBusy(true);
    try {
      await app.setContent(block.key, block.kind === "image" ? undefined : text, imageFile);
      app.toast("Saved.");
      setImageFile(null);
    } catch (err) {
      app.toast(err.message || "Couldn't save.");
    } finally {
      setBusy(false);
    }
  };

  const clear = async () => {
    if (!confirm("Clear this back to the default?")) return;
    await app.clearContent(block.key);
    setText("");
    setImagePreview("");
    setImageFile(null);
  };

  return (
    <div style={{ paddingBottom: 18, marginBottom: 18, borderBottom: "1px dashed var(--line)" }}>
      <label style={{ display: "block", fontSize: 13, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 6 }}>{block.label}</label>
      {block.help && <div className="field-hint" style={{ marginBottom: 8 }}>{block.help}</div>}
      {block.kind === "text" && (
        <input value={text} onChange={e => setText(e.target.value)} placeholder={block.placeholder || ""} style={{ width: "100%", padding: "10px 14px", border: "1px solid var(--line)", borderRadius: 8, fontFamily: "inherit", fontSize: 16, background: "#fff" }} />
      )}
      {block.kind === "longtext" && (
        <textarea rows="5" value={text} onChange={e => setText(e.target.value)} placeholder={block.placeholder || ""} style={{ width: "100%", padding: "10px 14px", border: "1px solid var(--line)", borderRadius: 8, fontFamily: "inherit", fontSize: 16, background: "#fff", lineHeight: 1.55, resize: "vertical" }} />
      )}
      {block.kind === "image" && (
        <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
          <div style={{ width: 180, height: 130, borderRadius: 10, overflow: "hidden", border: "1px dashed var(--rose)", background: "var(--paper-2)" }}>
            {imagePreview ? <img src={imagePreview} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} /> : <Placeholder label="no photo" variant="sage" />}
          </div>
          <div>
            <button type="button" className="btn btn-ghost btn-small" onClick={() => fileRef.current?.click()}>{imagePreview ? "Replace photo" : "Choose photo"}</button>
            <input type="file" accept="image/*" ref={fileRef} style={{ display: "none" }} onChange={handleImage} />
          </div>
        </div>
      )}
      <div style={{ marginTop: 10, display: "flex", gap: 8 }}>
        <button className="btn btn-small" onClick={save} disabled={busy}>{busy ? "Saving…" : "Save"}</button>
        {(current?.value || current?.image) && (
          <button className="btn btn-ghost btn-small" onClick={clear} style={{ color: "var(--rose-deep)" }}>Reset to default</button>
        )}
      </div>
    </div>
  );
}

// ---------- Settings ----------
const SETTING_GROUPS = [
  {
    label: "Order notifications",
    settings: [
      {
        key: "order_notify_email",
        label: "Email address for new order notifications",
        kind: "text",
        placeholder: "hazelbelleemb@gmail.com",
        help: "When a customer submits an upload, we send an email here with the reference number and details. Default: hazelbelleemb@gmail.com.",
      },
    ],
  },
  {
    label: "QuickBooks · Buy Now payments",
    settings: [
      {
        key: "buy_now_default_url",
        label: "Default QuickBooks payment link",
        kind: "text",
        placeholder: "https://connect.intuit.com/pay/...",
        help: "Shop items without their own Buy Now URL fall back to this. You can find this link in QuickBooks → Customers → Payment links. Leave blank to show 'Enquire' buttons instead.",
      },
      {
        key: "buy_now_blurb",
        label: "Buy Now footnote on shop cards",
        kind: "text",
        placeholder: "Secure payment via QuickBooks",
        help: "Short reassurance shown under each Buy Now button.",
      },
    ],
  },
  {
    label: "Reviews & feedback",
    settings: [
      {
        key: "google_review_url",
        label: "Google review link",
        kind: "text",
        placeholder: "https://g.page/r/...",
        help: "When an order is scanned to its final stage, we email the customer a few days later asking for a review. Paste your Google Business Profile review link here (in Google Business Profile → Ask for reviews → copy link). Paste a link to switch the feature on.",
      },
      {
        key: "facebook_url",
        label: "Facebook page link",
        kind: "text",
        placeholder: "https://facebook.com/hazelbelleemb",
        help: "Your Facebook page, offered as a second place to leave a review. Either or both links can be set.",
      },
      {
        key: "feedback_delay_days",
        label: "Days to wait before asking",
        kind: "text",
        placeholder: "5",
        help: "How long after an order is finished before the review email goes out. Default 5 days. Use 0 to send within minutes (handy for testing).",
      },
      {
        key: "feedback_enabled",
        label: "Pause review emails",
        kind: "text",
        placeholder: "(leave blank to keep on)",
        help: "Type off to pause review emails without losing your links. Leave blank (or anything else) to keep them on.",
      },
    ],
  },
];

function AdminSettings() {
  const app = useApp();
  return (
    <div>
      <h2>Settings</h2>
      <p style={{ color: "var(--ink-2)", margin: "4px 0 18px" }}>Behind-the-scenes bits — notification emails and payment links.</p>

      {SETTING_GROUPS.map(group => (
        <div key={group.label} className="stitched" style={{ marginBottom: 18 }}>
          <h3 style={{ marginBottom: 12 }}>{group.label}</h3>
          {group.settings.map(s => <SettingRow key={s.key} setting={s} current={app.adminSettings?.[s.key]} />)}
        </div>
      ))}

      <div className="stitched stitched-sage">
        <h3 style={{ marginBottom: 10 }}>QuickBooks · how to set up Buy Now</h3>
        <ol style={{ color: "var(--ink-2)", paddingLeft: 18, lineHeight: 1.7 }}>
          <li>Sign in to QuickBooks Online → <strong>Sales → Payment links</strong> (or <strong>+ New → Payment link</strong>).</li>
          <li>Create a payment link for the item (set the price &amp; description).</li>
          <li>Copy the share URL — it looks like <code className="mono">https://connect.intuit.com/pay/…</code>.</li>
          <li>Paste it into an item's <strong>Buy Now link</strong> field on the <em>Shop items</em> tab,
            or into the <strong>Default QuickBooks payment link</strong> above to use it as a fallback for every Ready-to-buy item.</li>
        </ol>
        <div className="mono" style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 12 }}>
          Payments are taken on QuickBooks' secure page — Hazelbelle never sees card numbers.
        </div>
      </div>
    </div>
  );
}

function SettingRow({ setting, current }) {
  const app = useApp();
  // adminSettings stores plain string values; tolerate an object shape too.
  const cur = (current && typeof current === "object") ? (current.value || "") : (current || "");
  const [val, setVal] = useState(cur);
  const [busy, setBusy] = useState(false);
  useEffect(() => { setVal(cur); }, [cur]);
  const save = async () => {
    setBusy(true);
    try {
      await app.setSetting(setting.key, val);
      app.toast("Saved.");
    } catch (err) {
      app.toast(err.message || "Couldn't save.");
    } finally {
      setBusy(false);
    }
  };
  return (
    <div style={{ paddingBottom: 14, marginBottom: 14, borderBottom: "1px dashed var(--line)" }}>
      <label style={{ display: "block", fontSize: 13, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: ".18em", marginBottom: 6 }}>{setting.label}</label>
      {setting.help && <div className="field-hint" style={{ marginBottom: 8 }}>{setting.help}</div>}
      <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
        <input
          value={val}
          onChange={e => setVal(e.target.value)}
          placeholder={setting.placeholder || ""}
          style={{ flex: 1, minWidth: 260, padding: "10px 14px", border: "1px solid var(--line)", borderRadius: 8, fontFamily: "inherit", fontSize: 16, background: "#fff" }}
        />
        <button className="btn btn-small" onClick={save} disabled={busy}>{busy ? "Saving…" : "Save"}</button>
      </div>
    </div>
  );
}

Object.assign(window, {
  VisitorCounterRow, CounterStat,
  AdminBlog, BlogPostForm,
  AdminContent, ContentBlockEditor,
  AdminSettings, SettingRow,
});
