// Poll page: same calendar widget, voters circle the offered days that work.

const pollID = location.pathname.split("/").pop();
const admin = new URLSearchParams(location.search).get("admin") || "";

let poll = null;
let cal = null;
const myPicks = new Set(); // option IDs the current visitor selected
const byDate = new Map();  // dateStr -> option

function $(id) { return document.getElementById(id); }

async function loadPoll() {
  const res = await fetch(`/api/polls/${pollID}` + (admin ? `?admin=${encodeURIComponent(admin)}` : ""));
  if (!res.ok) {
    $("not-found").hidden = false;
    return;
  }
  poll = await res.json();
  byDate.clear();
  for (const o of poll.options) byDate.set(o.date, o);
  renderAll();
}

function voteCount(optionID) {
  return poll.votes.filter((v) => v.optionIds.includes(optionID)).length;
}

function renderAll() {
  $("poll-view").hidden = false;
  $("poll-title").textContent = poll.title;
  if (poll.description) {
    $("poll-desc").textContent = poll.description;
    $("poll-desc").hidden = false;
  }
  document.title = "mediator — " + poll.title;

  const canVote = !poll.closed;
  $("vote-card").hidden = !canVote;
  $("vote-hint").hidden = !canVote;
  $("closed-banner").hidden = !poll.closed;
  if (poll.isAdmin) {
    $("admin-card").hidden = false;
    $("close-btn").disabled = poll.closed;
    if (poll.closed) $("close-btn").textContent = "Poll is closed";
  }

  if (!cal) {
    cal = new Calendar($("calendar"), {
      canClick: (ds) => canVote && byDate.has(ds),
      isOffered: (ds) => byDate.has(ds),
      months: () => {
        const counts = new Map();
        for (const ds of byDate.keys()) {
          const key = ds.slice(0, 7);
          counts.set(key, (counts.get(key) || 0) + 1);
        }
        return counts;
      },
      isPicked: (ds) => byDate.has(ds) && myPicks.has(byDate.get(ds).id),
      onToggle: (ds) => {
        const id = byDate.get(ds).id;
        if (myPicks.has(id)) myPicks.delete(id);
        else myPicks.add(id);
      },
      afterToggle: updateSummary,
      decorate: (ds, cell) => {
        const o = byDate.get(ds);
        if (!o) return;
        if (o.time) {
          const chip = document.createElement("span");
          chip.className = "timechip";
          chip.textContent = o.time;
          cell.appendChild(chip);
        }
        const n = voteCount(o.id);
        if (n > 0) {
          const badge = document.createElement("span");
          badge.className = "badge";
          badge.textContent = "\u2713" + n;
          cell.appendChild(badge);
        }
      },
    });
    if (poll.options.length > 0) cal.goTo(poll.options[0].date);
  } else {
    cal.render();
  }

  updateSummary();
  renderResults();
}

function updateSummary() {
  const n = myPicks.size;
  const total = poll.options.length;
  $("vote-summary").textContent =
    n === 0
      ? `No days circled yet — ${total} ${total === 1 ? "day" : "days"} offered.`
      : `${n} of ${total} offered days circled.`;
}

function renderResults() {
  const el = $("results");
  el.innerHTML = "";
  $("answer-count").textContent =
    poll.votes.length === 0 ? "" : `(${poll.votes.length} ${poll.votes.length === 1 ? "person" : "people"})`;

  if (poll.votes.length === 0) {
    el.innerHTML = '<p class="empty">No answers yet. Be the first!</p>';
    return;
  }

  const counts = poll.options.map((o) => voteCount(o.id));
  const best = Math.max(...counts);

  poll.options.forEach((o, i) => {
    const row = document.createElement("div");
    row.className = "result-row" + (counts[i] === best && best > 0 ? " best" : "");

    const when = document.createElement("span");
    when.className = "when";
    when.textContent = formatDate(o.date);
    if (o.time) {
      const t = document.createElement("span");
      t.className = "t";
      t.textContent = o.time;
      when.appendChild(t);
    }
    if (counts[i] === best && best > 0) {
      const tag = document.createElement("span");
      tag.className = "best-tag";
      tag.textContent = "works best";
      when.appendChild(tag);
    }

    const who = document.createElement("span");
    who.className = "who";
    const names = poll.votes.filter((v) => v.optionIds.includes(o.id)).map((v) => v.name);
    who.textContent = names.join(", ") || "\u2014";

    const count = document.createElement("span");
    count.className = "count";
    count.textContent = counts[i];

    row.append(when, who, count);
    el.appendChild(row);
  });
}

$("vote-btn").addEventListener("click", async () => {
  $("vote-error").textContent = "";
  $("vote-ok").hidden = true;
  const name = $("voter-name").value.trim();
  if (!name) { $("vote-error").textContent = "Enter your name first."; return; }

  const btn = $("vote-btn");
  btn.disabled = true;
  try {
    const res = await fetch(`/api/polls/${pollID}/votes`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ name, optionIds: [...myPicks] }),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(data.error || "Could not save your answer.");
    $("vote-ok").textContent = "Answer saved. You can change it any time by sending again with the same name.";
    $("vote-ok").hidden = false;
    await loadPoll();
  } catch (e) {
    $("vote-error").textContent = e.message;
  } finally {
    btn.disabled = false;
  }
});

async function adminAction(method, path, confirmMsg) {
  if (!confirm(confirmMsg)) return;
  $("admin-error").textContent = "";
  const res = await fetch(path, { method, headers: { "X-Admin-Token": admin } });
  const data = await res.json();
  if (!res.ok) { $("admin-error").textContent = data.error || "Action failed."; return false; }
  return true;
}

$("close-btn").addEventListener("click", async () => {
  if (await adminAction("POST", `/api/polls/${pollID}/close`,
    "Close this poll? Nobody will be able to answer anymore. This can't be undone.")) {
    await loadPoll();
  }
});

$("delete-btn").addEventListener("click", async () => {
  if (await adminAction("DELETE", `/api/polls/${pollID}`,
    "Delete this poll and all answers for good?")) {
    location.href = "/";
  }
});

loadPoll();

// Refresh results every 30s so the group sees answers roll in.
setInterval(async () => {
  if (!poll || document.hidden) return;
  const res = await fetch(`/api/polls/${pollID}` + (admin ? `?admin=${encodeURIComponent(admin)}` : ""));
  if (!res.ok) return;
  poll = await res.json();
  byDate.clear();
  for (const o of poll.options) byDate.set(o.date, o);
  cal.render();
  updateSummary();
  renderResults();
}, 30000);
