(() => {
  if (!document.getElementById("time-remaining")) {
    // Likely on the login page; skip tracker script.
    return;
  }
  const tz = (window.initialState && window.initialState.tz) || "America/New_York";

  const el = (id) => document.getElementById(id);
  const state = {
    active: window.initialState.active,
    stats: window.initialState.stats,
    history: window.initialState.history,
  };

  const $timeRemaining = el("time-remaining");
  const $endsAt = el("ends-at");
  const $elapsedTimer = el("elapsed-timer");
  const $progressFill = el("progress-fill");
  const $progressPercent = el("progress-percent");
  const $elapsedTime = el("elapsed-time");
  const $remainingTime = el("remaining-time");
  const $startedAt = el("started-at");
  const $goalLabel = el("goal-label");
  const $statusLabel = el("status-label");
  const $donut = el("donut");
  const $donutValue = el("donut-value");

  const startInput = el("start-time-input");
  const goalInput = el("goal-hours-input");

  const statFields = {
    avg: el("avg-duration"),
    median: el("median-duration"),
    streak: el("longest-streak"),
    count: el("completed-count"),
  };

  const historyList = el("history-list");
  const chartCanvas = el("history-chart");
  const chartCtx = chartCanvas ? chartCanvas.getContext("2d") : null;

  function renderHistoryChart() {
    if (!chartCtx || !chartCanvas) return;
    // Ensure canvas matches CSS size for crisp drawing.
    const desiredWidth = chartCanvas.clientWidth || chartCanvas.width;
    const desiredHeight = chartCanvas.clientHeight || chartCanvas.height;
    if (chartCanvas.width !== desiredWidth) chartCanvas.width = desiredWidth;
    if (chartCanvas.height !== desiredHeight) chartCanvas.height = desiredHeight;
    const hist = (state.history || []).slice().reverse(); // oldest -> newest
    chartCtx.clearRect(0, 0, chartCanvas.width, chartCanvas.height);
    if (!hist.length) {
      chartCtx.fillStyle = "#6b7380";
      chartCtx.font = "14px Segoe UI, Arial";
      chartCtx.fillText("No completed fasts yet.", 16, 40);
      return;
    }

    const durations = hist.map((h) => h.duration_hours);
    const goals = hist.map((h) => h.goal_hours || 0);
    const labels = hist.map((h) =>
      new Intl.DateTimeFormat("en-US", {
        timeZone: tz,
        month: "short",
        day: "numeric",
      }).format(new Date(h.end_et))
    );

    const padding = { top: 20, right: 12, bottom: 30, left: 40 };
    const w = chartCanvas.width;
    const h = chartCanvas.height;
    const x0 = padding.left;
    const x1 = w - padding.right;
    const y0 = h - padding.bottom;
    const y1 = padding.top;

    const maxY = Math.max(...durations, ...goals, 1);
    const minY = 0;
    const rangeY = maxY - minY || 1;

    const count = durations.length;
    const gap = 8;
    const barArea = x1 - x0 - (count - 1) * gap;
    const barWidth = Math.max(12, barArea / count);

    // Axes
    chartCtx.strokeStyle = "#dfe3ea";
    chartCtx.lineWidth = 1;
    chartCtx.beginPath();
    chartCtx.moveTo(x0, y0);
    chartCtx.lineTo(x1, y0);
    chartCtx.moveTo(x0, y0);
    chartCtx.lineTo(x0, y1);
    chartCtx.stroke();

    // Y ticks (0, max)
    chartCtx.fillStyle = "#6b7380";
    chartCtx.font = "12px Segoe UI, Arial";
    chartCtx.fillText(`${maxY.toFixed(0)}h`, 4, y1 + 4);
    chartCtx.fillText("0h", 12, y0);

    // Bars
    durations.forEach((val, idx) => {
      const goalVal = goals[idx];
      const x = x0 + idx * (barWidth + gap);

      // Goal bar (background)
      const goalHeight = ((goalVal - minY) / rangeY) * (y0 - y1);
      const goalY = y0 - goalHeight;
      chartCtx.fillStyle = "#e2e6ee";
      chartCtx.fillRect(x, goalY, barWidth, goalHeight);

      // Completed bar (foreground)
      const barHeight = ((val - minY) / rangeY) * (y0 - y1);
      const y = y0 - barHeight;
      const overGoal = val > goalVal;
      chartCtx.fillStyle = overGoal ? "#2fa36b" : "#3c7cf3";
      chartCtx.fillRect(x, y, barWidth, barHeight);
    });

    // X labels
    chartCtx.fillStyle = "#6b7380";
    chartCtx.font = "11px Segoe UI, Arial";
    labels.forEach((lbl, idx) => {
      const x = x0 + idx * (barWidth + gap) + barWidth / 2;
      chartCtx.save();
      chartCtx.textAlign = "center";
      chartCtx.fillText(lbl, x, y0 + 18);
      chartCtx.restore();
    });
  }

  function toET(dateStr) {
    if (!dateStr) return null;
    const d = new Date(dateStr);
    return new Intl.DateTimeFormat("en-US", {
      timeZone: tz,
      year: "numeric",
      month: "short",
      day: "2-digit",
      hour: "2-digit",
      minute: "2-digit",
    }).format(d);
  }

  function formatHM(totalMinutes) {
    const h = Math.floor(totalMinutes / 60);
    const m = Math.floor(totalMinutes % 60);
    return `${h}h ${m}m`;
  }

  function formatHMS(totalSeconds) {
    const s = Math.max(0, Math.floor(totalSeconds));
    const hh = String(Math.floor(s / 3600)).padStart(2, "0");
    const mm = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
    const ss = String(s % 60).padStart(2, "0");
    return `${hh}:${mm}:${ss}`;
  }

  function renderStats() {
    const { stats } = state;
    statFields.avg.textContent = `${stats.average_hours}h`;
    statFields.median.textContent = `${stats.median_hours}h`;
    statFields.streak.textContent = stats.longest_streak;
    statFields.count.textContent = stats.completed_count;
  }

  function renderHistory() {
    historyList.innerHTML = "";
    if (!state.history || state.history.length === 0) {
      const li = document.createElement("li");
      li.textContent = "No completed fasts yet.";
      historyList.appendChild(li);
      renderHistoryChart();
      return;
    }

    state.history.forEach((item) => {
      const li = document.createElement("li");
      const row1 = document.createElement("div");
      row1.className = "row";
      row1.innerHTML = `<span>${toET(item.start_et)} → ${toET(
        item.end_et
      )}</span><strong>${item.duration_hours}h</strong>`;

      li.appendChild(row1);
      const row2 = document.createElement("div");
      row2.className = "row";
      row2.innerHTML = `<span>Goal: ${item.goal_hours}h</span>`;
      li.appendChild(row2);
      if (item.note) {
        const note = document.createElement("div");
        note.className = "note";
        note.textContent = item.note;
        li.appendChild(note);
      }
      historyList.appendChild(li);
    });
    renderHistoryChart();
  }

  function updateDonut(pct) {
    const clamped = Math.max(0, Math.min(100, pct));
    $donut.style.background = `conic-gradient(var(--blue) 0deg, var(--blue) ${clamped}%, #e6e8ef ${clamped}%)`;
    $donutValue.textContent = `${Math.round(clamped)}%`;
  }

  function renderActive() {
    const active = state.active;
    if (!active) {
      $statusLabel.textContent = "Not started";
      $timeRemaining.textContent = "0h 0m";
      $elapsedTime.textContent = "0h 0m";
      $remainingTime.textContent = "0h 0m";
      $progressFill.style.width = "0%";
      $progressPercent.textContent = "0%";
      $goalLabel.textContent = "—";
      $startedAt.textContent = "—";
      $endsAt.textContent = "—";
      $elapsedTimer.textContent = "00:00:00";
      updateDonut(0);
      return;
    }

    const now = new Date();
    const start = new Date(active.start_utc);
    const end = active.end_utc ? new Date(active.end_utc) : null;
    const goalSeconds = active.goal_hours * 3600;
    const targetEnd = end || new Date(start.getTime() + goalSeconds * 1000);
    const elapsedSeconds = ((end || now) - start) / 1000;
    const remainingSeconds = goalSeconds - elapsedSeconds;
    const pct = Math.min(100, (elapsedSeconds / goalSeconds) * 100);

    $statusLabel.textContent = end ? "Completed" : "In progress";
    $timeRemaining.textContent = formatHM(Math.max(0, remainingSeconds / 60));
    $elapsedTime.textContent = formatHM(elapsedSeconds / 60);
    $remainingTime.textContent = formatHM(Math.max(0, remainingSeconds / 60));
    $progressFill.style.width = `${pct}%`;
    $progressPercent.textContent = `${Math.round(pct)}%`;
    $goalLabel.textContent = `${active.goal_hours}h`;
    $startedAt.textContent = toET(active.start_utc) || "—";
    $endsAt.textContent = toET(targetEnd.toISOString()) || "—";
    $elapsedTimer.textContent = formatHMS(elapsedSeconds);
    updateDonut(pct);
  }

  function tick() {
    renderActive();
  }

  async function postForm(url, data) {
    const body = new URLSearchParams(data);
    const res = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body,
    });
    if (!res.ok) {
      const msg = await res.text();
      throw new Error(msg || "Request failed");
    }
    return res.json();
  }

  function mergeResponse(payload) {
    if (payload.active_fast !== undefined) state.active = payload.active_fast;
    if (payload.stats) state.stats = payload.stats;
    if (payload.history) state.history = payload.history;
    renderStats();
    renderHistory();
    renderActive();
  }

  function wireEvents() {
    document.querySelectorAll(".chip").forEach((btn) => {
      btn.addEventListener("click", () => {
        goalInput.value = btn.dataset.goal;
      });
    });

    el("start-now").addEventListener("click", async () => {
      try {
        const data = {
          goal_hours: goalInput.value || "16",
          note: "",
        };
        const payload = await postForm("/fasts/start", data);
        mergeResponse(payload);
      } catch (err) {
        alert(err);
      }
    });

    el("use-start").addEventListener("click", async () => {
      const startVal = startInput.value;
      if (!startVal) {
        alert("Pick a start time first.");
        return;
      }
      try {
        const data = {
          goal_hours: goalInput.value || "16",
          start_time: startVal,
          note: "",
        };
        const payload = await postForm("/fasts/start", data);
        mergeResponse(payload);
      } catch (err) {
        alert(err);
      }
    });

    el("reset").addEventListener("click", async () => {
      try {
        const payload = await postForm("/fasts/reset", {});
        mergeResponse(payload);
      } catch (err) {
        alert(err);
      }
    });

    const clearBtn = el("clear-history");
    if (clearBtn) {
      clearBtn.addEventListener("click", async () => {
        if (!confirm("This will remove all fasting history. Continue?")) return;
        try {
          const payload = await postForm("/fasts/clear", {});
          mergeResponse(payload);
        } catch (err) {
          alert(err);
        }
      });
    }
  }

  // Initialize defaults
  renderStats();
  renderHistory();
  renderActive();
  wireEvents();
  setInterval(tick, 1000);
})();
