/* global React, ReactDOM, Icon, Avatar */
const { useState, useMemo, useEffect, useRef, useCallback } = React;

function FixedTooltip({ text, anchorRef }) {
  const [pos, setPos] = useState(null);
  useEffect(() => {
    if (!anchorRef.current) return;
    const rect = anchorRef.current.getBoundingClientRect();
    setPos({ top: rect.top + rect.height / 2, left: rect.right + 8 });
  }, [text]);
  if (!pos || !text) return null;
  return ReactDOM.createPortal(
    React.createElement(
      "div",
      {
        style: {
          position: "fixed",
          top: pos.top,
          left: pos.left,
          transform: "translateY(-50%)",
          background: "var(--ink)",
          color: "#fff",
          fontSize: 11.5,
          lineHeight: 1.4,
          fontWeight: 500,
          padding: "6px 10px",
          borderRadius: 6,
          whiteSpace: "pre-line",
          width: "max-content",
          maxWidth: 200,
          pointerEvents: "none",
          zIndex: 9999,
        },
      },
      text,
    ),
    document.body,
  );
}

function ScopeRing({ done, total }) {
  const ref = useRef(null);
  const [hover, setHover] = useState(false);
  const pct = total > 0 ? Math.round((done / total) * 100) : 0;
  const r = 8,
    strokeW = 2.5,
    sz = 22,
    c = sz / 2;
  const circ = 2 * Math.PI * r;
  const offset = circ - (pct / 100) * circ;
  return React.createElement(
    "span",
    {
      ref,
      className: "scope-ring",
      onMouseEnter: () => setHover(true),
      onMouseLeave: () => setHover(false),
    },
    React.createElement(
      "svg",
      {
        className: "scope-ring-svg",
        viewBox: `0 0 ${sz} ${sz}`,
        width: sz,
        height: sz,
      },
      React.createElement("circle", {
        cx: c,
        cy: c,
        r,
        fill: "none",
        stroke: "rgba(31,26,46,0.1)",
        strokeWidth: strokeW,
      }),
      React.createElement("circle", {
        cx: c,
        cy: c,
        r,
        fill: "none",
        stroke: "var(--ok)",
        strokeWidth: strokeW,
        strokeLinecap: "round",
        strokeDasharray: circ,
        strokeDashoffset: offset,
        transform: `rotate(-90 ${c} ${c})`,
        style: { transition: "stroke-dashoffset 600ms ease" },
      }),
    ),
    hover &&
      React.createElement(FixedTooltip, {
        text: `${pct}% — ${done} of ${total} checked in`,
        anchorRef: ref,
      }),
  );
}

// ── Profile panel (opens from user card) ──────────────────
function ProfilePanel({
  authUser,
  onClose,
  onSignOut,
  onProfileSave,
  onViewCheckins,
}) {
  const apiBase = window.PULSE_CONFIG?.apiBase || "http://localhost:8000";
  const authToken = localStorage.getItem("pulse_token");

  const [profile, setProfile] = useState(null);
  const [orgs, setOrgs] = useState([]);
  const [editing, setEditing] = useState(false);
  const [saving, setSaving] = useState(false);
  const [activeTheme, setActiveTheme] = useState(
    () =>
      document.documentElement.getAttribute("data-theme") ||
      localStorage.getItem("pulse_theme") ||
      "classic",
  );

  // Editable fields
  const [editName, setEditName] = useState("");
  const [editRole, setEditRole] = useState("");
  const [editRoleTag, setEditRoleTag] = useState("");
  const [editTz, setEditTz] = useState("");
  const [editRhythm, setEditRhythm] = useState("");
  const [editSquadId, setEditSquadId] = useState("");
  const [editSquadIds, setEditSquadIds] = useState([]);

  useEffect(() => {
    fetch(`${apiBase}/me`, {
      headers: { Authorization: `Bearer ${authToken}` },
    })
      .then((r) => r.json())
      .then((data) => {
        setProfile(data);
        setEditName(data.name || "");
        setEditRole(data.role || "");
        setEditRoleTag(data.role_tag || "");
        setEditTz(data.timezone || "Europe/London");
        setEditRhythm(data.rhythm || "daily");
        setEditSquadId(data.squad_id || "");
        setEditSquadIds(
          data.squad_ids || (data.squad_id ? [data.squad_id] : []),
        );
      })
      .catch(() => {});
    fetch(`${apiBase}/orgs`)
      .then((r) => r.json())
      .then(setOrgs)
      .catch(() => {});
  }, []);

  const ancestry = useMemo(() => {
    if (!profile || !orgs.length) return [];
    const sids = profile.squad_ids?.length
      ? profile.squad_ids
      : profile.squad_id
        ? [profile.squad_id]
        : [];
    if (!sids.length) return [];
    const chain = [];
    let current = orgs.find((o) => o.id === sids[0]);
    while (current) {
      chain.push(current);
      current = orgs.find((o) => o.id === current.parent_id);
    }
    return chain;
  }, [profile, orgs]);

  const profileSquadNames = useMemo(() => {
    if (!profile?.squad_ids?.length || !orgs.length) return [];
    return profile.squad_ids
      .map((sid) => orgs.find((o) => o.id === sid)?.name)
      .filter(Boolean);
  }, [profile, orgs]);

  const editAncestry = useMemo(() => {
    if (!editSquadId || !orgs.length) return [];
    const chain = [];
    let current = orgs.find((o) => o.id === editSquadId);
    while (current) {
      chain.push(current);
      current = orgs.find((o) => o.id === current.parent_id);
    }
    return chain;
  }, [editSquadId, orgs]);

  const squadOptions = orgs.filter((o) => o.type === "squad");

  const handleSave = async () => {
    setSaving(true);
    try {
      await fetch(`${apiBase}/me/profile`, {
        method: "PATCH",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${authToken}`,
        },
        body: JSON.stringify({
          name: editName,
          role: editRole,
          role_tag: editRoleTag || null,
          timezone: editTz,
          rhythm: editRhythm,
          squad_id: editSquadIds[0] || editSquadId || null,
          squad_ids: editSquadIds,
        }),
      });
      // Refresh profile
      const r = await fetch(`${apiBase}/me`, {
        headers: { Authorization: `Bearer ${authToken}` },
      });
      const data = await r.json();
      setProfile(data);
      setEditSquadIds(data.squad_ids || []);
      setEditing(false);
      // Update localStorage so the rest of the app sees changes
      localStorage.setItem(
        "pulse_user",
        JSON.stringify({
          id: data.id,
          name: data.name,
          email: data.email,
          role: data.role,
          squad_id: data.squad_id,
          timezone: data.timezone,
          rhythm: data.rhythm,
        }),
      );
      if (onProfileSave) onProfileSave();
    } catch {
    } finally {
      setSaving(false);
    }
  };

  const TYPE_LABELS = {
    squad: "Squad",
    team: "Team",
    group: "Group",
    function: "Function",
    business: "Business",
  };

  return (
    <div className="profile-panel">
      <div className="profile-panel-backdrop" onClick={onClose} />
      <div className="profile-panel-content">
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            marginBottom: 16,
          }}
        >
          <h3 style={{ margin: 0, fontSize: 15, fontWeight: 600 }}>Profile</h3>
          <button
            onClick={onClose}
            style={{
              border: 0,
              background: "transparent",
              cursor: "pointer",
              color: "var(--ink-3)",
              fontSize: 18,
              lineHeight: 1,
            }}
          >
            ×
          </button>
        </div>

        {!profile ? (
          <div
            style={{
              textAlign: "center",
              padding: 20,
              color: "var(--ink-3)",
              fontSize: 13,
            }}
          >
            Loading…
          </div>
        ) : editing ? (
          <>
            <div className="profile-field">
              <label>Name</label>
              <input
                type="text"
                value={editName}
                onChange={(e) => setEditName(e.target.value)}
              />
            </div>
            <div className="profile-field">
              <label>Job title</label>
              <input
                type="text"
                value={editRole}
                onChange={(e) => setEditRole(e.target.value)}
                placeholder="e.g. Product Lead"
              />
            </div>
            <div className="profile-field">
              <label>Role</label>
              <select
                value={editRoleTag}
                onChange={(e) => setEditRoleTag(e.target.value)}
              >
                <option value="">– Select –</option>
                <option value="Developer">Developer</option>
                <option value="Designer">Designer</option>
                <option value="Project Management">Project Management</option>
              </select>
            </div>
            <div className="profile-field">
              <label>Timezone</label>
              <select
                value={editTz}
                onChange={(e) => setEditTz(e.target.value)}
              >
                {[
                  "Europe/London",
                  "Europe/Dublin",
                  "Europe/Paris",
                  "Europe/Berlin",
                  "Europe/Bucharest",
                  "Asia/Kolkata",
                  "Asia/Singapore",
                  "America/New_York",
                  "America/Chicago",
                  "America/Denver",
                  "America/Los_Angeles",
                  "Australia/Sydney",
                ].map((tz) => (
                  <option key={tz} value={tz}>
                    {tz.replace(/_/g, " ")}
                  </option>
                ))}
              </select>
            </div>
            <div className="profile-field">
              <label>Check-in rhythm</label>
              <select
                value={editRhythm}
                onChange={(e) => setEditRhythm(e.target.value)}
              >
                <option value="daily">Daily</option>
                <option value="3x">3× per week</option>
                <option value="weekly">Weekly</option>
              </select>
            </div>
            <div className="profile-field">
              <label>Squads</label>
              <div className="squad-checklist">
                {squadOptions.map((s) => {
                  const checked = editSquadIds.includes(s.id);
                  return (
                    <label
                      key={s.id}
                      className={`squad-check${checked ? " on" : ""}`}
                    >
                      <input
                        type="checkbox"
                        checked={checked}
                        onChange={() => {
                          setEditSquadIds((ids) =>
                            ids.includes(s.id)
                              ? ids.filter((x) => x !== s.id)
                              : [...ids, s.id],
                          );
                        }}
                      />
                      <span>{s.name}</span>
                    </label>
                  );
                })}
              </div>
            </div>
            <div style={{ display: "flex", gap: 8, marginTop: 16 }}>
              <button
                className="btn accent"
                style={{ flex: 1, fontSize: 12 }}
                onClick={handleSave}
                disabled={saving}
              >
                {saving ? "Saving…" : "Save changes"}
              </button>
              <button
                className="btn"
                style={{ fontSize: 12 }}
                onClick={() => setEditing(false)}
              >
                Cancel
              </button>
            </div>
          </>
        ) : (
          <>
            <div
              style={{
                display: "flex",
                alignItems: "center",
                gap: 12,
                marginBottom: 16,
              }}
            >
              <Avatar name={profile.name} you size="lg" />
              <div>
                <div style={{ fontSize: 14, fontWeight: 600 }}>
                  {profile.name}
                </div>
                <div style={{ fontSize: 12, color: "var(--ink-3)" }}>
                  {profile.email}
                </div>
              </div>
            </div>

            <div className="profile-detail-grid">
              <div className="profile-detail-item">
                <span className="profile-detail-label">Job title</span>
                <span className="profile-detail-value">
                  {profile.role || "—"}
                </span>
              </div>
              <div className="profile-detail-item">
                <span className="profile-detail-label">Role</span>
                <span className="profile-detail-value">
                  {profile.role_tag || "—"}
                </span>
              </div>
              <div className="profile-detail-item">
                <span className="profile-detail-label">Timezone</span>
                <span className="profile-detail-value">
                  {(profile.timezone || "Europe/London").replace(/_/g, " ")}
                </span>
              </div>
              <div className="profile-detail-item">
                <span className="profile-detail-label">Rhythm</span>
                <span className="profile-detail-value">
                  {profile.rhythm || "daily"}
                </span>
              </div>
            </div>

            <div style={{ marginTop: 16 }}>
              <div
                style={{
                  fontSize: 11,
                  fontWeight: 600,
                  color: "var(--ink-4)",
                  textTransform: "uppercase",
                  letterSpacing: "0.05em",
                  marginBottom: 8,
                }}
              >
                Organisation
              </div>
              {profileSquadNames.length > 1 && (
                <div
                  style={{
                    fontSize: 12,
                    color: "var(--ink-2)",
                    marginBottom: 8,
                  }}
                >
                  Squads: {profileSquadNames.join(", ")}
                </div>
              )}
              {ancestry.length > 0 ? (
                <div className="profile-ancestry">
                  {ancestry.map((node) => (
                    <div key={node.id} className="profile-ancestry-item">
                      <span className="profile-ancestry-type">
                        {TYPE_LABELS[node.type] || node.type}
                      </span>
                      <span className="profile-ancestry-name">{node.name}</span>
                    </div>
                  ))}
                </div>
              ) : (
                <div
                  style={{
                    fontSize: 12,
                    color: "var(--ink-3)",
                    fontStyle: "italic",
                  }}
                >
                  No squad selected
                </div>
              )}
            </div>

            <div style={{ marginTop: 16 }}>
              <div
                style={{
                  fontSize: 11,
                  fontWeight: 600,
                  color: "var(--ink-4)",
                  textTransform: "uppercase",
                  letterSpacing: "0.05em",
                  marginBottom: 8,
                }}
              >
                Permissions
              </div>
              <div
                style={{
                  fontSize: 12,
                  color: "var(--ink-3)",
                  fontStyle: "italic",
                }}
              >
                Coming soon
              </div>
            </div>

            <div style={{ marginTop: 16 }}>
              <div
                style={{
                  fontSize: 11,
                  fontWeight: 600,
                  color: "var(--ink-4)",
                  textTransform: "uppercase",
                  letterSpacing: "0.05em",
                  marginBottom: 8,
                }}
              >
                Theme
              </div>
              <div
                className="theme-switcher"
                onClick={function (e) {
                  var pill = e.target.closest(".theme-pill");
                  if (!pill) return;
                  var id = pill.getAttribute("data-theme-id");
                  document.documentElement.setAttribute("data-theme", id);
                  localStorage.setItem("pulse_theme", id);
                  setActiveTheme(id);
                }}
              >
                <div
                  className={
                    activeTheme === "classic"
                      ? "theme-pill active"
                      : "theme-pill"
                  }
                  data-theme-id="classic"
                >
                  <span
                    className="theme-dot"
                    style={{ background: "#664FAD" }}
                  />
                  Classic
                </div>
                <div
                  className={
                    activeTheme === "wabi" ? "theme-pill active" : "theme-pill"
                  }
                  data-theme-id="wabi"
                >
                  <span
                    className="theme-dot"
                    style={{ background: "#5B8C5A" }}
                  />
                  Wabi
                </div>
                <div
                  className={
                    activeTheme === "nord" ? "theme-pill active" : "theme-pill"
                  }
                  data-theme-id="nord"
                >
                  <span
                    className="theme-dot"
                    style={{ background: "#88C0D0" }}
                  />
                  Nord
                </div>
                <div
                  className={
                    activeTheme === "ember" ? "theme-pill active" : "theme-pill"
                  }
                  data-theme-id="ember"
                >
                  <span
                    className="theme-dot"
                    style={{ background: "#B84C2A" }}
                  />
                  Ember
                </div>
                <div
                  className={
                    activeTheme === "horizon"
                      ? "theme-pill active"
                      : "theme-pill"
                  }
                  data-theme-id="horizon"
                >
                  <span
                    className="theme-dot"
                    style={{ background: "#0891B2" }}
                  />
                  Horizon
                </div>
              </div>
            </div>

            {onViewCheckins && (
              <button
                className="btn"
                style={{
                  width: "100%",
                  fontSize: 12,
                  marginTop: 20,
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  gap: 6,
                }}
                onClick={onViewCheckins}
              >
                <Icon.Clock style={{ width: 13, height: 13 }} />
                My Check-ins
              </button>
            )}

            <div style={{ display: "flex", gap: 8, marginTop: 10 }}>
              <button
                className="btn accent"
                style={{ flex: 1, fontSize: 12 }}
                onClick={() => setEditing(true)}
              >
                Edit profile
              </button>
              {onSignOut && (
                <button
                  className="btn"
                  style={{ fontSize: 12, color: "var(--danger)" }}
                  onClick={onSignOut}
                >
                  Sign out
                </button>
              )}
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ── Left rail ─────────────────────────────────────────────
function Rail({
  scope,
  setScope,
  squad,
  authUser,
  onSignOut,
  scopeCounts,
  userSquads,
  activeSquadId,
  setActiveSquadId,
  view,
  onProfileSave,
}) {
  const { SCOPES } = window.SEED;
  const apiBase = window.PULSE_CONFIG?.apiBase || "http://localhost:8000";
  const authToken = localStorage.getItem("pulse_token");

  const [groups, setGroups] = useState([]);
  const [showCreate, setShowCreate] = useState(false);
  const [newName, setNewName] = useState("");
  const [newIcon, setNewIcon] = useState("Hash");
  const [profileOpen, setProfileOpen] = useState(false);

  const [groupsOpen, setGroupsOpen] = useState(true);

  // [COMING SOON] Groups API — to be re-enabled once feature is approved
  // const refreshGroups = () => {
  //   if (!authToken) return;
  //   fetch(`${apiBase}/groups`, { headers: { Authorization: `Bearer ${authToken}` } })
  //     .then(r => r.ok ? r.json() : [])
  //     .then(setGroups)
  //     .catch(() => {});
  // };
  // useEffect(() => { refreshGroups(); }, [authToken]);
  const refreshGroups = () => {};

  // [COMING SOON] Group creation — to be re-enabled once feature is approved
  const handleCreate = () => {};
  // const handleCreate = () => {
  //   const name = newName.trim();
  //   if (!name) return;
  //   fetch(`${apiBase}/groups`, {
  //     method: 'POST',
  //     headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${authToken}` },
  //     body: JSON.stringify({ name, icon: newIcon }),
  //   })
  //     .then(r => r.ok ? r.json() : null)
  //     .then(g => {
  //       if (g) { refreshGroups(); setShowCreate(false); setNewName(''); setNewIcon('Hash'); }
  //     })
  //     .catch(() => {});
  // };

  // [COMING SOON] Group join/leave — to be re-enabled once feature is approved
  const handleJoinLeave = () => {};
  // const handleJoinLeave = (gid, isMember) => {
  //   fetch(`${apiBase}/groups/${gid}/${isMember ? 'leave' : 'join'}`, {
  //     method: 'POST',
  //     headers: { Authorization: `Bearer ${authToken}` },
  //   })
  //     .then(r => r.ok ? r.json() : null)
  //     .then(() => refreshGroups())
  //     .catch(() => {});
  // };

  return (
    <aside className="rail">
      {/* Squad switcher (only shown if user has multiple squads) */}
      {userSquads && userSquads.length > 1 && (
        <div className="rail-section" style={{ paddingBottom: 8 }}>
          <div className="rail-heading">
            <span>Active Squad</span>
          </div>
          <div className="squad-switcher">
            {userSquads.map((s) => (
              <button
                key={s.id}
                type="button"
                className="squad-switch-btn"
                aria-current={activeSquadId === s.id}
                onClick={() => setActiveSquadId(s.id)}
              >
                <Icon.Users style={{ width: 12, height: 12, flexShrink: 0 }} />
                {s.name}
              </button>
            ))}
          </div>
        </div>
      )}

      <div className="rail-section">
        <div className="rail-heading">
          <span>Scope</span>
        </div>
        {SCOPES.map((s) => {
          const I = Icon[s.icon];
          const active = scope === s.id;
          const counts = scopeCounts && scopeCounts[s.id];
          const done = counts ? counts.checked_in : 0;
          const total = counts ? counts.total : 0;
          return (
            <button
              key={s.id}
              className="scope-item"
              aria-current={active && view !== "wiki"}
              onClick={() => setScope(s.id)}
            >
              <I className="scope-icon" />
              <span className="scope-label">{s.label}</span>
              {total > 0 && <ScopeRing done={done} total={total} />}
            </button>
          );
        })}
      </div>

      <div className="rail-section coming-soon-wrap">
        <div className="coming-soon-overlay">
          <span>Coming soon</span>
        </div>
        <div
          className="rail-heading"
          onClick={() => setGroupsOpen((o) => !o)}
          style={{ cursor: "pointer", userSelect: "none" }}
        >
          <span>Groups</span>
          <Icon.Chevron
            style={{
              width: 12,
              height: 12,
              transition: "transform 0.15s",
              transform: groupsOpen ? "rotate(0deg)" : "rotate(-90deg)",
            }}
          />
        </div>
        {groupsOpen && (
          <>
            {groups.map((g) => {
              const I = Icon[g.icon] || Icon.Hash;
              const active = scope === g.id;
              const counts = scopeCounts && scopeCounts[g.id];
              const done = counts ? counts.checked_in : null;
              const total = counts ? counts.total : null;
              const hasCounts = done !== null && total !== null && total > 0;
              return (
                <div
                  key={g.id}
                  style={{ display: "flex", alignItems: "center", gap: 0 }}
                >
                  <button
                    className="scope-item"
                    style={{ flex: 1 }}
                    onClick={() => setScope(g.id)}
                    aria-current={active}
                  >
                    <I className="scope-icon" />
                    <span className="scope-label">{g.name}</span>
                    {hasCounts ? (
                      <span className="scope-meta">
                        <span className="mono">
                          {done}/{total}
                        </span>
                        <span className="scope-bar">
                          <span style={{ width: `${(done / total) * 100}%` }} />
                        </span>
                      </span>
                    ) : (
                      <span className="scope-meta">
                        <span className="mono">{g.member_count}</span>
                      </span>
                    )}
                  </button>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      handleJoinLeave(g.id, g.is_member);
                    }}
                    title={g.is_member ? "Leave group" : "Join group"}
                    style={{
                      border: 0,
                      background: "transparent",
                      cursor: "pointer",
                      padding: "2px 6px",
                      fontSize: 10,
                      fontWeight: 600,
                      borderRadius: 4,
                      flexShrink: 0,
                      lineHeight: 1,
                      color: g.is_member ? "var(--ink-4)" : "var(--accent)",
                    }}
                  >
                    {g.is_member ? "✓" : "Join"}
                  </button>
                </div>
              );
            })}

            {!showCreate ? (
              <button
                className="scope-item"
                style={{ color: "var(--ink-3)" }}
                onClick={() => setShowCreate(true)}
              >
                <Icon.Plus className="scope-icon" />
                <span className="scope-label">Add new group</span>
              </button>
            ) : (
              <div
                style={{
                  padding: "6px 10px",
                  display: "flex",
                  flexDirection: "column",
                  gap: 6,
                }}
              >
                <input
                  autoFocus
                  value={newName}
                  onChange={(e) => setNewName(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === "Enter") handleCreate();
                    if (e.key === "Escape") {
                      setShowCreate(false);
                      setNewName("");
                    }
                  }}
                  placeholder="Group name"
                  style={{
                    fontSize: 12,
                    padding: "5px 8px",
                    border: "1px solid var(--line)",
                    borderRadius: 6,
                    background: "var(--bg)",
                    color: "var(--ink-1)",
                    outline: "none",
                    fontFamily: "inherit",
                  }}
                />
                <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
                  <span style={{ fontSize: 10.5, color: "var(--ink-4)" }}>
                    Type:
                  </span>
                  <button
                    onClick={() => setNewIcon("Hash")}
                    style={{
                      border:
                        newIcon === "Hash"
                          ? "1.5px solid var(--accent)"
                          : "1px solid var(--line)",
                      background:
                        newIcon === "Hash"
                          ? "var(--accent-soft)"
                          : "transparent",
                      borderRadius: 4,
                      padding: "2px 6px",
                      fontSize: 10.5,
                      cursor: "pointer",
                      color: "var(--ink-2)",
                    }}
                  >
                    # Topic
                  </button>
                  <button
                    onClick={() => setNewIcon("Heart")}
                    style={{
                      border:
                        newIcon === "Heart"
                          ? "1.5px solid var(--accent)"
                          : "1px solid var(--line)",
                      background:
                        newIcon === "Heart"
                          ? "var(--accent-soft)"
                          : "transparent",
                      borderRadius: 4,
                      padding: "2px 6px",
                      fontSize: 10.5,
                      cursor: "pointer",
                      color: "var(--ink-2)",
                    }}
                  >
                    ♥ Interest
                  </button>
                </div>
                <div style={{ display: "flex", gap: 4 }}>
                  <button
                    className="btn accent"
                    style={{ fontSize: 11, padding: "3px 10px", flex: 1 }}
                    onClick={handleCreate}
                  >
                    Create
                  </button>
                  <button
                    className="btn"
                    style={{ fontSize: 11, padding: "3px 10px" }}
                    onClick={() => {
                      setShowCreate(false);
                      setNewName("");
                    }}
                  >
                    Cancel
                  </button>
                </div>
              </div>
            )}
          </>
        )}
      </div>

      <div
        className="user-card"
        onClick={() => setProfileOpen((o) => !o)}
        style={{ cursor: "pointer" }}
      >
        <Avatar name={authUser ? authUser.name : window.SEED.ME.name} you />
        <div style={{ minWidth: 0, flex: 1 }}>
          <div
            style={{ fontSize: 13, fontWeight: 600, letterSpacing: "-0.1px" }}
          >
            {authUser ? authUser.name : window.SEED.ME.name}
          </div>
          <div
            style={{
              fontSize: 11.5,
              color: "var(--ink-3)",
              whiteSpace: "nowrap",
              overflow: "hidden",
              textOverflow: "ellipsis",
            }}
          >
            {authUser ? authUser.role : window.SEED.ME.role}
          </div>
        </div>
        {onSignOut && (
          <button
            onClick={(e) => {
              e.stopPropagation();
              onSignOut();
            }}
            title="Sign out"
            style={{
              border: 0,
              background: "transparent",
              color: "var(--ink-4)",
              padding: 4,
              borderRadius: 6,
              cursor: "pointer",
              display: "grid",
              placeItems: "center",
              flexShrink: 0,
            }}
            onMouseEnter={(e) =>
              (e.currentTarget.style.color = "var(--danger)")
            }
            onMouseLeave={(e) => (e.currentTarget.style.color = "var(--ink-4)")}
          >
            <Icon.SignOut style={{ width: 14, height: 14 }} />
          </button>
        )}
      </div>

      {/* Profile panel */}
      {profileOpen && (
        <ProfilePanel
          authUser={authUser}
          onClose={() => setProfileOpen(false)}
          onSignOut={onSignOut}
          onProfileSave={onProfileSave}
          onViewCheckins={() => {
            setProfileOpen(false);
            setScope("checkins");
          }}
        />
      )}
    </aside>
  );
}

// ── Right rail ────────────────────────────────────────────
function RightRail({
  todos,
  setTodos,
  scope,
  onViewFull,
  authToken,
  showTodos = true,
}) {
  const { GOALS } = window.SEED;
  const [expanded, setExpanded] = useState(false);
  const [adding, setAdding] = useState(false);
  const [newText, setNewText] = useState("");
  const [newPriority, setNewPriority] = useState("medium");
  const [newDueDate, setNewDueDate] = useState("");
  const [sentimentData, setSentimentData] = useState(null);
  const LIMIT = 5;
  const apiBase = window.PULSE_CONFIG?.apiBase || "http://localhost:8000";

  useEffect(() => {
    if (!authToken || !showTodos) return;
    fetch(`${apiBase}/todos`, {
      headers: { Authorization: `Bearer ${authToken}` },
    })
      .then((r) => (r.ok ? r.json() : []))
      .then((data) => {
        if (data.length) setTodos(data);
      })
      .catch(() => {});
  }, [authToken]);

  // [COMING SOON] Sentiment API — disabled until feature is approved
  // useEffect(() => {
  //   if (!authToken) return;
  //   const scopeParam = scope || 'squad';
  //   fetch(`${apiBase}/sentiment?scope=${scopeParam}`, { headers: { Authorization: `Bearer ${authToken}` } })
  //     .then(r => r.ok ? r.json() : null)
  //     .then(data => { if (data) setSentimentData(data); })
  //     .catch(() => {});
  // }, [authToken, scope]);

  const [completing, setCompleting] = useState(new Set());

  const handleToggle = (id, currentDone) => {
    if (!currentDone) {
      // Completing: play the exit animation, then move to done after delay.
      setCompleting((s) => new Set(s).add(id));
      setTimeout(() => {
        setTodos((ts) =>
          ts.map((x) => (x.id === id ? { ...x, done: true } : x)),
        );
        setCompleting((s) => {
          const n = new Set(s);
          n.delete(id);
          return n;
        });
      }, 500);
    } else {
      // Un-completing: instant (no drama needed for restoring).
      setTodos((ts) =>
        ts.map((x) => (x.id === id ? { ...x, done: false } : x)),
      );
    }
    fetch(`${apiBase}/todos/${id}`, {
      method: "PATCH",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${authToken}`,
      },
      body: JSON.stringify({ done: !currentDone }),
    }).catch(() => {});
  };

  const handleAdd = () => {
    const text = newText.trim();
    if (!text) return;
    const tempId = `td-${Date.now()}`;
    setTodos((ts) => [
      {
        id: tempId,
        text,
        done: false,
        source: null,
        priority: newPriority,
        due_date: newDueDate || null,
      },
      ...ts,
    ]);
    setNewText("");
    setNewPriority("medium");
    setNewDueDate("");
    setAdding(false);
    fetch(`${apiBase}/todos`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${authToken}`,
      },
      body: JSON.stringify({
        text,
        priority: newPriority,
        due_date: newDueDate || null,
      }),
    })
      .then((r) => (r.ok ? r.json() : null))
      .then((data) => {
        if (data)
          setTodos((ts) =>
            ts.map((t) => (t.id === tempId ? { ...t, id: data.id } : t)),
          );
      })
      .catch(() => {});
  };

  const openTodos = todos.filter((t) => !t.done);
  const completedTodos = todos.filter((t) => t.done);
  const visibleOpen = expanded ? openTodos : openTodos.slice(0, LIMIT);
  const hasMore = openTodos.length > LIMIT;
  const [showCompleted, setShowCompleted] = useState(false);

  return (
    <aside className="right-rail">
      <div className="rr-card coming-soon-wrap">
        <div className="coming-soon-overlay">
          <span>Coming soon</span>
        </div>
        <div className="rr-head">
          <Icon.Target />
          <div className="rr-title">Goals &amp; progress</div>
        </div>
        {GOALS.map((g, i) => (
          <div className="goal" key={i}>
            <div className="goal-head">
              <span>{g.t}</span>
              <span className="pct">{g.pct}%</span>
            </div>
            <div className="goal-bar">
              <span style={{ width: `${g.pct}%` }} />
            </div>
            <div className="goal-sub">{g.sub}</div>
          </div>
        ))}
      </div>

      {showTodos && (
        <div className="rr-card">
          <div className="rr-head">
            <Icon.List />
            <div className="rr-title">To dos</div>
            <button
              onClick={() => setAdding((a) => !a)}
              style={{
                marginLeft: "auto",
                border: 0,
                background: "transparent",
                color: "var(--accent)",
                cursor: "pointer",
                fontSize: 18,
                lineHeight: 1,
                padding: "0 2px",
                borderRadius: 4,
              }}
              title="Add to-do"
            >
              +
            </button>
          </div>
          {adding && (
            <div
              style={{
                marginBottom: 10,
                border: "1px solid var(--line)",
                borderRadius: 8,
                padding: 8,
                background: "var(--bg)",
              }}
            >
              <input
                autoFocus
                placeholder="New to-do…"
                value={newText}
                onChange={(e) => setNewText(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") handleAdd();
                  if (e.key === "Escape") {
                    setAdding(false);
                    setNewText("");
                  }
                }}
                style={{
                  width: "100%",
                  fontSize: 12.5,
                  padding: "5px 8px",
                  border: "1px solid var(--line)",
                  borderRadius: 6,
                  background: "var(--surface)",
                  color: "var(--ink-1)",
                  outline: "none",
                  marginBottom: 6,
                }}
              />
              <div
                style={{
                  display: "grid",
                  gridTemplateColumns: "1fr 1fr",
                  gap: 6,
                  marginBottom: 6,
                }}
              >
                <div>
                  <label
                    style={{
                      fontSize: 10,
                      color: "var(--ink-4)",
                      display: "block",
                      marginBottom: 2,
                    }}
                  >
                    Priority
                  </label>
                  <select
                    value={newPriority}
                    onChange={(e) => setNewPriority(e.target.value)}
                    style={{
                      width: "100%",
                      fontSize: 11,
                      padding: "4px 6px",
                      border: "1px solid var(--line)",
                      borderRadius: 5,
                      background:
                        newPriority === "high"
                          ? "var(--danger-soft)"
                          : newPriority === "low"
                            ? "var(--line-2)"
                            : "var(--accent-soft)",
                    }}
                  >
                    <option value="high">High</option>
                    <option value="medium">Medium</option>
                    <option value="low">Low</option>
                  </select>
                </div>
                <div>
                  <label
                    style={{
                      fontSize: 10,
                      color: "var(--ink-4)",
                      display: "block",
                      marginBottom: 2,
                    }}
                  >
                    To do by
                  </label>
                  <input
                    type="date"
                    value={newDueDate}
                    onChange={(e) => setNewDueDate(e.target.value)}
                    style={{
                      width: "100%",
                      fontSize: 11,
                      padding: "4px 6px",
                      border: "1px solid var(--line)",
                      borderRadius: 5,
                      background: "var(--surface)",
                    }}
                  />
                </div>
              </div>
              <div style={{ display: "flex", justifyContent: "flex-end" }}>
                <button
                  onClick={handleAdd}
                  style={{
                    marginLeft: "auto",
                    fontSize: 11,
                    padding: "4px 10px",
                    borderRadius: 6,
                    border: 0,
                    background: "var(--accent)",
                    color: "#fff",
                    cursor: "pointer",
                    fontWeight: 500,
                  }}
                >
                  Add
                </button>
              </div>
            </div>
          )}
          {visibleOpen.length === 0 && completedTodos.length === 0 && (
            <div
              style={{
                fontSize: 12.5,
                color: "var(--ink-3)",
                padding: "4px 0",
              }}
            >
              No to-dos yet.
            </div>
          )}
          {visibleOpen.map((t) => {
            const isOverdue =
              t.due_date &&
              !t.done &&
              new Date(t.due_date) < new Date(new Date().toDateString());
            const prioColor =
              t.priority === "high"
                ? "var(--danger)"
                : t.priority === "low"
                  ? "var(--ink-4)"
                  : "var(--accent)";
            return (
              <div
                className={`todo${isOverdue ? " overdue" : ""}${completing.has(t.id) ? " completing" : ""}${t.priority === "high" ? " prio-high" : t.priority === "low" ? " prio-low" : " prio-medium"}`}
                key={t.id}
              >
                <input
                  id={t.id}
                  type="checkbox"
                  checked={false}
                  onChange={() => handleToggle(t.id, t.done)}
                />
                <label htmlFor={t.id}>
                  <span
                    style={{ display: "flex", alignItems: "center", gap: 5 }}
                  >
                    {t.priority && t.priority !== "medium" && (
                      <span
                        style={{
                          width: 6,
                          height: 6,
                          borderRadius: "50%",
                          background: prioColor,
                          flexShrink: 0,
                        }}
                        title={t.priority + " priority"}
                      />
                    )}
                    {t.text}
                  </span>
                  <span
                    style={{
                      display: "flex",
                      gap: 6,
                      flexWrap: "wrap",
                      marginTop: 2,
                    }}
                  >
                    {t.due_date && (
                      <span
                        className="todo-meta"
                        style={isOverdue ? { color: "var(--danger)" } : {}}
                      >
                        {isOverdue ? "Overdue · " : "Due "}
                        {t.due_date}
                      </span>
                    )}
                    {t.assigned_by_name && (
                      <span className="todo-meta">
                        Assigned by {t.assigned_by_name}
                      </span>
                    )}
                    {t.source && (
                      <span className="todo-meta">from {t.source}</span>
                    )}
                  </span>
                </label>
              </div>
            );
          })}
          {hasMore && (
            <button
              onClick={() => setExpanded((e) => !e)}
              style={{
                display: "flex",
                alignItems: "center",
                gap: 4,
                border: 0,
                background: "transparent",
                color: "var(--accent)",
                cursor: "pointer",
                fontSize: 12,
                fontWeight: 500,
                padding: "6px 0 0",
                width: "100%",
              }}
            >
              <Icon.Chevron
                style={{
                  width: 12,
                  height: 12,
                  transform: expanded ? "rotate(180deg)" : "rotate(0deg)",
                  transition: "transform 150ms ease",
                }}
              />
              {expanded ? "Show less" : `${openTodos.length - LIMIT} more`}
            </button>
          )}

          {/* Completed to-dos — collapsed by default */}
          {completedTodos.length > 0 && (
            <div
              style={{
                marginTop: 10,
                borderTop: "1px solid var(--line)",
                paddingTop: 8,
              }}
            >
              <button
                onClick={() => setShowCompleted((c) => !c)}
                style={{
                  display: "flex",
                  alignItems: "center",
                  gap: 4,
                  border: 0,
                  background: "transparent",
                  color: "var(--ink-3)",
                  cursor: "pointer",
                  fontSize: 12,
                  fontWeight: 500,
                  padding: 0,
                  width: "100%",
                }}
              >
                <Icon.Chevron
                  style={{
                    width: 11,
                    height: 11,
                    transform: showCompleted
                      ? "rotate(180deg)"
                      : "rotate(0deg)",
                    transition: "transform 150ms ease",
                  }}
                />
                Completed ({completedTodos.length})
              </button>
              {showCompleted &&
                completedTodos.map((t) => (
                  <div className="todo" key={t.id} style={{ opacity: 0.55 }}>
                    <input
                      id={t.id}
                      type="checkbox"
                      checked={true}
                      onChange={() => handleToggle(t.id, t.done)}
                    />
                    <label htmlFor={t.id}>{t.text}</label>
                  </div>
                ))}
            </div>
          )}
        </div>
      )}

      <div className="rr-card coming-soon-wrap">
        <div className="coming-soon-overlay">
          <span>Coming soon</span>
        </div>
        <div className="rr-head">
          <Icon.Wave />
          <div className="rr-title">
            Sentiment pulse
            {sentimentData
              ? ` · ${sentimentData.total_members} member${sentimentData.total_members !== 1 ? "s" : ""}`
              : ""}
          </div>
        </div>
        <div className="senti-grid">
          {(sentimentData
            ? sentimentData.days
            : Array(14).fill({ positive_pct: null })
          ).map((d, i) => {
            const pp = d.positive_pct;
            // null = no data (lightest), 100% positive = lightest, 0% positive (all negative) = darkest
            const stops = [
              "var(--accent-softer)",
              "var(--accent-soft)",
              "rgba(var(--accent-rgb),0.35)",
              "rgba(var(--accent-rgb),0.6)",
              "var(--accent)",
            ];
            let idx;
            if (pp === null || pp === undefined) idx = 0;
            else if (pp >= 80) idx = 0;
            else if (pp >= 60) idx = 1;
            else if (pp >= 40) idx = 2;
            else if (pp >= 20) idx = 3;
            else idx = 4;
            const label =
              pp === null || pp === undefined ? "No data" : `${pp}% positive`;
            return (
              <div
                key={i}
                className="senti-cell"
                style={{ background: stops[idx] }}
                title={`${d.date || ""} · ${label}`}
              />
            );
          })}
        </div>
        <div className="senti-legend">
          <span>2 wk ago</span>
          <span>Today</span>
        </div>
        <div
          style={{
            fontSize: 12,
            color: "var(--ink-3)",
            marginTop: 10,
            lineHeight: 1.5,
          }}
        >
          {sentimentData ? sentimentData.summary : "Loading…"}
        </div>
      </div>
    </aside>
  );
}

window.Rail = Rail;
window.RightRail = RightRail;
