---
import AdminLayout from "../../layouts/AdminLayout.astro";

// Convenience list for the target-page picker. The agent can reach any page;
// this is just the common set plus "new page".
const PAGES = [
  { value: "/", label: "Home" },
  { value: "/about", label: "About" },
  { value: "/services", label: "Services" },
  { value: "/services/website-design", label: "Services — Website design" },
  { value: "/projects", label: "Projects (index)" },
  { value: "/resume", label: "Resume" },
  { value: "/contact", label: "Contact" },
  { value: "/changelog", label: "Changelog" },
  { value: "/faq", label: "FAQ" },
];
---

<AdminLayout title="Web Designer">
  <h1>Web Designer</h1>
  <p class="lead">Give the design agent a task for any page — instructions, a draft, images, and short-video links. Tasks queue up and publish themselves one at a time; you review the results here.</p>

  <section class="panel">
    <div class="two">
      <div>
        <label for="f-page">Page</label>
        <div class="sel">
          <select id="f-page">
            {PAGES.map((p) => <option value={p.value}>{p.label}</option>)}
            <option value="__new">＋ New page…</option>
          </select>
        </div>
      </div>
      <div id="newWrap" hidden>
        <label for="f-slug">New page path</label>
        <div class="slug"><span>/</span><input type="text" id="f-slug" placeholder="accounting" /></div>
      </div>
    </div>

    <label for="f-title" class="mt">Task title <span class="opt">optional — for the queue list</span></label>
    <input type="text" id="f-title" placeholder="Tighten the About intro" />

    <label for="f-prompt" class="mt">What should the Web Designer do?</label>
    <textarea id="f-prompt" rows="4" placeholder="e.g. Rebuild the hero: shorter headline, add a one-line pull-quote, and place the photo to the right. Keep it on brand."></textarea>

    <label for="f-draft" class="mt">Draft content <span class="opt">optional</span></label>
    <textarea id="f-draft" rows="4" placeholder="Any copy or notes to work from — rough is fine."></textarea>

    <div class="mt">
      <div class="head"><label>Images <span class="opt">optional</span></label><button type="button" class="btn ghost sm" id="addImg">+ Add image</button></div>
      <div id="gallery" class="grid"></div>
    </div>

    <div class="mt">
      <div class="head"><label>Short video links <span class="opt">optional</span></label><button type="button" class="btn ghost sm" id="addVid">+ Add link</button></div>
      <div id="videos" class="rows"></div>
    </div>

    <div class="submit">
      <button type="button" class="btn" id="submit">Add to queue &amp; run</button>
      <p class="msg" id="msg" role="status" aria-live="polite"></p>
    </div>
  </section>

  <section class="queue">
    <div class="head"><h2>Queue</h2><button type="button" class="btn ghost sm" id="runBtn">Run queue</button></div>
    <div id="list" class="tasks">Loading…</div>
  </section>

  <style>
    h2 { font-family:var(--serif); font-weight:400; font-size:1.3rem; margin:0; }
    .panel { border:1px solid var(--rule); border-radius:2px; padding:1.5rem; margin-bottom:2.5rem; }
    .two { display:grid; grid-template-columns:1fr 1fr; gap:1.25rem 2rem; }
    .mt { margin-top:1.4rem; }
    .opt { font-size:.55rem; color:var(--ink4); letter-spacing:.08em; }
    .head { display:flex; align-items:center; gap:1rem; margin-bottom:.9rem; }
    .head label, .head h2 { margin:0; }
    textarea { width:100%; border:1px solid var(--rule); background:transparent; border-radius:2px;
      padding:.6rem .7rem; font-size:.9rem; color:var(--ink); font-family:var(--sans); line-height:1.55; resize:vertical; }
    textarea:focus { outline:none; border-color:var(--seal); }
    .sel select { width:100%; border:0; border-bottom:1px solid var(--rule); background:var(--paper);
      padding:.5rem 0; font-size:.95rem; color:var(--ink); font-family:var(--sans); }
    .sel select:focus { outline:none; border-bottom-color:var(--seal); }
    .sel select option { background:var(--paper); color:var(--ink); }
    .slug { display:flex; align-items:baseline; gap:.15rem; border-bottom:1px solid var(--rule); }
    .slug span { color:var(--ink4); font-family:var(--mono); }
    .slug input { border:0; }
    .btn.sm { padding:.35rem .7rem; font-size:.7rem; }

    .rows { display:flex; flex-direction:column; gap:.5rem; }
    .row { display:flex; gap:.5rem; align-items:center; }
    .row input { flex:1; }
    .row .rm { flex:0 0 auto; width:1.9rem; height:1.9rem; border:1px solid var(--rule); background:transparent;
      color:var(--ink3); border-radius:2px; cursor:pointer; }
    .row .rm:hover { color:var(--seal); border-color:var(--seal); }

    .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(9rem,1fr)); gap:.75rem; }
    .slot { border:1px solid var(--rule); border-radius:2px; overflow:hidden; }
    .thumb { position:relative; aspect-ratio:4/3; background:var(--card); display:flex; align-items:center; justify-content:center; overflow:hidden; }
    .thumb img { width:100%; height:100%; object-fit:cover; }
    .thumb .empty { font-family:var(--mono); font-size:.55rem; letter-spacing:.1em; text-transform:uppercase; color:var(--ink4); }
    .thumb.busy::after { content:"…"; position:absolute; inset:0; display:flex; align-items:center; justify-content:center; background:color-mix(in srgb,var(--paper) 80%,transparent); }
    .slot .acts { display:flex; border-top:1px solid var(--rule); }
    .slot .acts label, .slot .acts button { flex:1; text-align:center; padding:.4rem; font-family:var(--mono); font-size:.55rem; letter-spacing:.06em; text-transform:uppercase; color:var(--ink3); cursor:pointer; background:none; border:0; }
    .slot .acts label { border-right:1px solid var(--rule); }
    .slot .acts input { display:none; }

    .submit { display:flex; align-items:center; gap:1.25rem; margin-top:1.75rem; padding-top:1.25rem; border-top:1px solid var(--rule); }

    .tasks { display:flex; flex-direction:column; }
    .task { display:flex; align-items:center; gap:1rem; padding:.9rem 0; border-top:1px solid var(--rule); }
    .task:last-child { border-bottom:1px solid var(--rule); }
    .task .t { font-family:var(--sans); font-size:.95rem; }
    .task .tgt { font-family:var(--mono); font-size:.62rem; color:var(--ink4); letter-spacing:.04em; }
    .task .sp { margin-left:auto; display:flex; align-items:center; gap:1rem; }
    .badge { font-family:var(--mono); font-size:.58rem; letter-spacing:.1em; text-transform:uppercase; padding:.2rem .5rem; border:1px solid var(--rule); border-radius:2px; color:var(--ink3); white-space:nowrap; }
    .badge.running { color:var(--seal); border-color:var(--seal); }
    .badge.published { color:var(--ink); }
    .badge.failed { color:var(--seal); border-color:var(--seal); }
    .task a.view { font-family:var(--mono); font-size:.6rem; letter-spacing:.08em; text-transform:uppercase; color:var(--ink3); text-decoration:none; }
    .task a.view:hover { color:var(--ink); }
    .task .err { font-size:.78rem; color:var(--seal); }
    .task .cancel { font-family:var(--mono); font-size:.58rem; letter-spacing:.06em; text-transform:uppercase; color:var(--ink4); background:none; border:0; cursor:pointer; }
    .task .cancel:hover { color:var(--seal); }
  </style>

  <script>
    const $ = (id) => document.getElementById(id);
    const msg = $("msg");
    const setMsg = (t, cls = "") => { msg.textContent = t; msg.className = "msg " + cls; };
    let images = [];   // [{src, alt}]
    let videos = [];   // [string]

    // ---- target page: reveal slug input for "new page" --------------------
    $("f-page").addEventListener("change", (e) => { $("newWrap").hidden = e.target.value !== "__new"; });

    // ---- images (upload) --------------------------------------------------
    function renderImages() {
      const g = $("gallery"); g.innerHTML = "";
      images.forEach((it, i) => {
        const slot = document.createElement("div");
        slot.className = "slot";
        slot.innerHTML = `
          <div class="thumb" data-thumb>${it.src ? `<img src="${it.src}" alt="">` : `<span class="empty">No image</span>`}</div>
          <div class="acts">
            <label>${it.src ? "Replace" : "Upload"}<input type="file" accept="image/*" data-file></label>
            <button type="button" data-rm>Remove</button>
          </div>`;
        slot.querySelector("[data-rm]").addEventListener("click", () => { images.splice(i, 1); renderImages(); });
        slot.querySelector("[data-file]").addEventListener("change", (e) => uploadImg(e.target.files[0], i, slot));
        g.appendChild(slot);
      });
    }
    async function uploadImg(file, i, slot) {
      if (!file) return;
      const thumb = slot.querySelector("[data-thumb]"); thumb.classList.add("busy");
      try {
        const fd = new FormData(); fd.append("file", file);
        const r = await fetch("/api/media/upload", { method: "POST", credentials: "same-origin", body: fd });
        const d = await r.json();
        if (r.ok && d?.data?.url) { images[i].src = d.data.url; renderImages(); }
        else setMsg(d?.error?.message || "Upload failed.", "error");
      } catch { setMsg("Upload failed.", "error"); }
      finally { thumb.classList.remove("busy"); }
    }
    $("addImg").addEventListener("click", () => { images.push({ src: "", alt: "" }); renderImages(); });

    // ---- video links ------------------------------------------------------
    function renderVideos() {
      const v = $("videos"); v.innerHTML = "";
      videos.forEach((url, i) => {
        const row = document.createElement("div");
        row.className = "row";
        row.innerHTML = `<input type="url" placeholder="https://instagram.com/reel/…" value="${(url || "").replace(/"/g, "&quot;")}" data-url>
          <button type="button" class="rm" title="Remove" data-rm>×</button>`;
        row.querySelector("[data-url]").addEventListener("input", (e) => { videos[i] = e.target.value; });
        row.querySelector("[data-rm]").addEventListener("click", () => { videos.splice(i, 1); renderVideos(); });
        v.appendChild(row);
      });
    }
    $("addVid").addEventListener("click", () => { videos.push(""); renderVideos(); });

    // ---- submit -----------------------------------------------------------
    $("submit").addEventListener("click", async () => {
      const prompt = $("f-prompt").value.trim();
      if (!prompt) { setMsg("Say what you'd like done.", "error"); return; }
      let target = $("f-page").value;
      if (target === "__new") {
        const slug = $("f-slug").value.trim().replace(/^\/+/, "");
        if (!slug) { setMsg("Give the new page a path.", "error"); return; }
        target = "new:" + slug;
      }
      const btn = $("submit"); btn.disabled = true; setMsg("Queuing…");
      try {
        const payload = {
          title: $("f-title").value.trim(),
          target_page: target,
          prompt,
          draft: $("f-draft").value,
          assets: { images: images.filter((i) => i.src).map((i) => ({ url: i.src, alt: i.alt || "" })), videos: videos.filter(Boolean) },
        };
        const r = await fetch("/api/admintasks/create", {
          method: "POST", credentials: "same-origin",
          headers: { "content-type": "application/json" }, body: JSON.stringify(payload),
        });
        const d = await r.json();
        if (!r.ok || !d?.data?.ok) { setMsg(d?.error?.message || "Couldn't queue the task.", "error"); btn.disabled = false; return; }
        await fetch("/devconsole/tasks/run", { method: "POST", credentials: "same-origin" });
        // reset the brief
        $("f-prompt").value = ""; $("f-draft").value = ""; $("f-title").value = "";
        images = []; videos = []; renderImages(); renderVideos();
        setMsg("Queued — the Web Designer is on it.", "ok");
        load();
      } catch { setMsg("Something went wrong.", "error"); }
      finally { btn.disabled = false; }
    });

    $("runBtn").addEventListener("click", async () => {
      try { await fetch("/devconsole/tasks/run", { method: "POST", credentials: "same-origin" }); setMsg("Queue kicked.", "ok"); load(); } catch {}
    });

    // ---- queue list (poll) ------------------------------------------------
    const badge = (s) => {
      const label = s === "running" ? "running…" : s;
      return `<span class="badge ${s}">${label}</span>`;
    };
    async function load() {
      try {
        const r = await fetch("/api/admintasks/list", { credentials: "same-origin" });
        const d = await r.json();
        const tasks = d?.data?.tasks || [];
        const list = $("list");
        if (!tasks.length) { list.textContent = "No tasks yet."; return; }
        list.innerHTML = "";
        for (const t of tasks) {
          const row = document.createElement("div");
          row.className = "task";
          let right = badge(t.status);
          if (t.status === "published") {
            right += ` <a class="view" href="${t.live || "/"}" target="_blank">View live ↗</a>`;
            if (t.commit) right += ` <span class="tgt">${t.commit}</span>`;
          } else if (t.status === "failed" && t.error) {
            right = `<span class="err">${t.error}</span> ` + right;
          } else if (t.status === "queued") {
            right += ` <button class="cancel" data-cancel="${t.id}">Cancel</button>`;
          }
          row.innerHTML = `<span class="t">${t.title || "(untitled)"}</span><span class="tgt">${t.target}</span><span class="sp">${right}</span>`;
          const cx = row.querySelector("[data-cancel]");
          if (cx) cx.addEventListener("click", async () => {
            await fetch("/api/admintasks/cancel", { method: "POST", credentials: "same-origin", headers: { "content-type": "application/json" }, body: JSON.stringify({ id: Number(cx.dataset.cancel) }) });
            load();
          });
          list.appendChild(row);
        }
      } catch { $("list").textContent = "Couldn't load the queue."; }
    }

    load();
    setInterval(load, 4000);
  </script>
</AdminLayout>
