// Map-page bookmark UI: a star toggle in the results "share" row, and a
// compact "Saved" pill + dropdown near the Find button for jumping between
// saved spots without retyping. Pure DOM glue over bookmarks.js, which is the
// only place bookmark data actually lives — this module holds no state of its
// own beyond references to the elements it built.
//
// Loaded as an extra module alongside app.js rather than merged into it: app.js
// owns #results' markup (it rewrites results.innerHTML wholesale on every grade
// via its own render()), so a MutationObserver on #results is what lets this
// module re-attach the star after every re-render without needing a hook
// app.js doesn't expose. selectLocation() is module-private to app.js, so
// jumping to a saved spot goes through the same hash the app already treats as
// authoritative on load (see nav.js: "a hash always wins") via a reload —
// the same path opening a shared link takes, so the normal grade flow runs.
import * as bookmarks from "./bookmarks.js";

const STAR_OUTLINE = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>`;
const STAR_FILLED = `<svg viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>`;
const CHEV_IC = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>`;
const CLOSE_X = `<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`;
const PENCIL_IC = `<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg>`;

function esc(s) {
  return String(s == null ? "" : s).replace(/[&<>"']/g, (c) =>
    ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
}

function injectStyle() {
  if (document.getElementById("tg-bookmarks-style")) return;
  const style = document.createElement("style");
  style.id = "tg-bookmarks-style";
  style.textContent = `
.bkm-star[aria-pressed="true"] { color: var(--accent); border-color: var(--accent); }
.bkm-pill-wrap { position: relative; display: inline-flex; align-self: center; }
.bkm-pill {
  border-radius: 10px; border: 1px solid var(--border); cursor: pointer;
  background: var(--surface-2); color: var(--text); font-weight: 600; font-size: 13px;
  padding: 9px 12px; min-height: 40px; display: inline-flex; align-items: center; gap: 6px;
}
.bkm-pill:hover { border-color: var(--accent); }
.bkm-pill[hidden] { display: none; }
.bkm-drop {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 1100; min-width: 260px;
  max-width: min(340px, 90vw); max-height: 60vh; overflow-y: auto;
  display: flex; flex-direction: column; padding: 6px; margin: 0; list-style: none;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .45);
}
.bkm-drop[hidden] { display: none; }
.bkm-item { display: flex; align-items: center; gap: 2px; border-radius: 8px; }
.bkm-item:hover { background: var(--surface-2); }
.bkm-item-go {
  flex: 1 1 auto; min-width: 0; text-align: left; background: none; border: 0; cursor: pointer;
  color: var(--text); font: inherit; font-size: 13.5px; padding: 9px 8px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bkm-item-btn {
  flex-shrink: 0; background: none; border: 0; color: var(--muted); cursor: pointer;
  padding: 7px; border-radius: 6px; display: inline-flex;
}
.bkm-item-btn:hover { color: var(--text); background: var(--border); }
.bkm-empty { padding: 10px 8px; font-size: 12.5px; color: var(--muted); }
.bkm-import-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 12px; padding: 10px 14px; margin: 0 0 16px; font-size: 13.5px;
}
.bkm-import-banner .bkm-import-actions { display: flex; gap: 8px; flex-shrink: 0; }
.bkm-import-banner button {
  border-radius: 8px; border: 1px solid var(--border); cursor: pointer;
  padding: 7px 12px; font-size: 12.5px; font-weight: 600; background: var(--surface); color: var(--text);
}
.bkm-import-banner button.bkm-import-yes { background: var(--accent); color: #1a1206; border-color: var(--accent); }
@media (max-width: 480px) { .bkm-drop { left: auto; right: 0; } }
`;
  document.head.appendChild(style);
}

function parseHash() {
  const p = new URLSearchParams(location.hash.slice(1));
  const lat = parseFloat(p.get("lat")), lon = parseFloat(p.get("lon"));
  if (isNaN(lat) || isNaN(lon)) return null;
  return { lat, lon };
}

function jumpTo(lat, lon) {
  const dateInput = document.getElementById("date-input");
  const date = dateInput && dateInput.value ? dateInput.value : "";
  let h = `#lat=${lat.toFixed(5)}&lon=${lon.toFixed(5)}`;
  if (date) h += `&date=${date}`;
  location.hash = h;
  location.reload();
}

function currentLabel() {
  const h2 = document.querySelector("#results .loc-title h2");
  return (h2 && h2.textContent.trim()) || null;
}

// ---- star toggle in the .share row ----
function buildStar() {
  const btn = document.createElement("button");
  btn.type = "button";
  btn.id = "btn-bookmark";
  btn.className = "bkm-star";
  btn.addEventListener("click", async () => {
    const loc = parseHash();
    if (!loc) return;
    const existing = bookmarks.find(loc.lat, loc.lon);
    btn.disabled = true;
    try {
      if (existing) await bookmarks.remove(existing.id);
      else await bookmarks.add(loc.lat, loc.lon, currentLabel());
    } catch (e) {
      // A real server rejection (e.g. the per-user cap) — bookmarks.add() no
      // longer fakes a local save for this, so say why nothing changed.
      alert(e.message || "Couldn't save this location.");
    } finally {
      btn.disabled = false;
    }
  });
  return btn;
}

function paintStar() {
  const share = document.querySelector("#results .share");
  if (!share) return;
  let btn = share.querySelector("#btn-bookmark");
  if (!btn) {
    btn = buildStar();
    share.insertBefore(btn, share.firstChild);
  }
  const loc = parseHash();
  const saved = loc ? !!bookmarks.find(loc.lat, loc.lon) : false;
  btn.setAttribute("aria-pressed", saved ? "true" : "false");
  btn.title = saved ? "Remove this saved location" : "Save this location";
  btn.setAttribute("aria-label", btn.title);
  btn.innerHTML = (saved ? STAR_FILLED : STAR_OUTLINE) + `<span>${saved ? "Saved" : "Save"}</span>`;
}

const resultsEl = document.getElementById("results");
if (resultsEl) {
  new MutationObserver(() => paintStar()).observe(resultsEl, { childList: true });
}

// ---- "Saved" dropdown near the Find button ----
let dropEl = null, pillEl = null;

function buildSavedControl() {
  const findBar = document.querySelector(".find-bar");
  if (!findBar) return;
  const wrap = document.createElement("div");
  wrap.className = "bkm-pill-wrap";
  wrap.innerHTML = `
    <button type="button" class="bkm-pill" id="bkm-pill" hidden aria-haspopup="true" aria-expanded="false">
      <span>Saved</span>${CHEV_IC}
    </button>
    <ul class="bkm-drop" id="bkm-drop" hidden aria-label="Saved locations"></ul>`;
  findBar.appendChild(wrap);
  pillEl = wrap.querySelector("#bkm-pill");
  dropEl = wrap.querySelector("#bkm-drop");

  pillEl.addEventListener("click", () => {
    const open = dropEl.hidden;
    dropEl.hidden = !open;
    pillEl.setAttribute("aria-expanded", open ? "true" : "false");
  });
  document.addEventListener("click", (e) => {
    if (!wrap.contains(e.target) && !dropEl.hidden) {
      dropEl.hidden = true;
      pillEl.setAttribute("aria-expanded", "false");
    }
  });
  document.addEventListener("keydown", (e) => {
    if (e.key === "Escape" && !dropEl.hidden) {
      dropEl.hidden = true;
      pillEl.setAttribute("aria-expanded", "false");
      pillEl.focus();
    }
  });
}

function renderDropdown(list) {
  if (!pillEl || !dropEl) return;
  pillEl.hidden = list.length === 0;   // new visitors see nothing extra at all
  if (!list.length) { dropEl.hidden = true; return; }
  dropEl.innerHTML = list.map((b) => {
    const label = b.label || `${b.lat.toFixed(3)}, ${b.lon.toFixed(3)}`;
    return `
    <li class="bkm-item">
      <button type="button" class="bkm-item-go" data-id="${esc(b.id)}" title="${esc(label)}">${esc(label)}</button>
      <button type="button" class="bkm-item-btn bkm-item-rename" data-id="${esc(b.id)}" title="Rename" aria-label="Rename ${esc(label)}">${PENCIL_IC}</button>
      <button type="button" class="bkm-item-btn bkm-item-remove" data-id="${esc(b.id)}" title="Remove" aria-label="Remove ${esc(label)}">${CLOSE_X}</button>
    </li>`;
  }).join("");
  dropEl.querySelectorAll(".bkm-item-go").forEach((el) => {
    el.addEventListener("click", () => {
      const b = list.find((x) => x.id === el.dataset.id);
      if (b) { dropEl.hidden = true; jumpTo(b.lat, b.lon); }
    });
  });
  dropEl.querySelectorAll(".bkm-item-rename").forEach((el) => {
    el.addEventListener("click", (e) => {
      e.stopPropagation();
      const b = list.find((x) => x.id === el.dataset.id);
      if (!b) return;
      const next = window.prompt("Rename this saved location:", b.label || "");
      if (next && next.trim()) bookmarks.rename(b.id, next.trim());
    });
  });
  dropEl.querySelectorAll(".bkm-item-remove").forEach((el) => {
    el.addEventListener("click", (e) => {
      e.stopPropagation();
      const b = list.find((x) => x.id === el.dataset.id);
      if (b) bookmarks.remove(b.id);
    });
  });
}

// ---- import prompt banner (non-blocking, shown once until dismissed) ----
let bannerEl = null;
function renderBanner() {
  const n = bookmarks.pendingImportCount();
  if (!n) { if (bannerEl) bannerEl.hidden = true; return; }
  const controls = document.querySelector(".controls");
  if (!bannerEl && controls) {
    bannerEl = document.createElement("div");
    bannerEl.className = "bkm-import-banner";
    controls.insertAdjacentElement("afterend", bannerEl);
  }
  if (!bannerEl) return;
  bannerEl.hidden = false;
  bannerEl.innerHTML = `
    <span>Import ${n} saved location${n === 1 ? "" : "s"} into your account?</span>
    <span class="bkm-import-actions">
      <button type="button" class="bkm-import-yes">Import</button>
      <button type="button" class="bkm-import-no">Not now</button>
    </span>`;
  bannerEl.querySelector(".bkm-import-yes").onclick = async () => {
    const btn = bannerEl.querySelector(".bkm-import-yes");
    btn.disabled = true;
    try { await bookmarks.importPending(); } catch (e) { btn.disabled = false; }
  };
  bannerEl.querySelector(".bkm-import-no").onclick = () => bookmarks.dismissImportPrompt();
}

// ---- boot ----
injectStyle();
buildSavedControl();
bookmarks.subscribe((list) => {
  renderDropdown(list);
  paintStar();
  renderBanner();
});
renderDropdown(bookmarks.list());
renderBanner();
