const COURSE_STATUSES = [
  { id: "incomplete",  label: "Incomplete" },
  { id: "in_progress", label: "In Progress" },
  { id: "completed",   label: "Completed" },
];

// Right contextual panel: degree progress + timeline
function ContextPanel({ open, onClose, currentUser, setCurrentUser }) {
  const C = 2 * Math.PI * 38; // circumference for r=38

  const [progress, setProgress] = React.useState(null);
  const [progressLoading, setProgressLoading] = React.useState(true);

  const [planSemesters, setPlanSemesters] = React.useState([]);
  const [planLoading, setPlanLoading] = React.useState(true);

  const [openChip, setOpenChip] = React.useState(null); // key of the chip whose status popup is open
  const [statusSaving, setStatusSaving] = React.useState(false);
  const popupRef = React.useRef(null);

  const completedSet = React.useMemo(() => {
    const list = (currentUser && currentUser.completedCourses) || [];
    return new Set(list.map(c => (c || "").toUpperCase()));
  }, [currentUser]);

  const inProgressSet = React.useMemo(() => {
    const list = (currentUser && currentUser.inProgressCourses) || [];
    return new Set(list.map(c => (c || "").toUpperCase()));
  }, [currentUser]);

  // Close the status popup on any click outside it.
  React.useEffect(() => {
    if (!openChip) return;
    const onDocClick = (e) => {
      if (popupRef.current && !popupRef.current.contains(e.target)) setOpenChip(null);
    };
    document.addEventListener("mousedown", onDocClick);
    return () => document.removeEventListener("mousedown", onDocClick);
  }, [openChip]);

  const setCourseStatus = async (code, statusId) => {
    if (!currentUser) return;
    const upper = (code || "").toUpperCase();
    const nextCompleted = new Set(completedSet);
    const nextInProgress = new Set(inProgressSet);
    nextCompleted.delete(upper);
    nextInProgress.delete(upper);
    if (statusId === "completed") nextCompleted.add(upper);
    if (statusId === "in_progress") nextInProgress.add(upper);

    setOpenChip(null);
    setStatusSaving(true);
    try {
      const token = localStorage.getItem("token");
      const res = await fetch(`${window.API_BASE}/api/profile`, {
        method: "PUT",
        headers: { "Content-Type": "application/json", "Authorization": "Bearer " + token },
        body: JSON.stringify({
          completed_courses: [...nextCompleted],
          in_progress_courses: [...nextInProgress],
        }),
      });
      const data = await res.json();
      if (res.ok && setCurrentUser) {
        setCurrentUser({
          ...currentUser,
          completedCourses: data.completed_courses || [],
          inProgressCourses: data.in_progress_courses || [],
        });
      }
    } catch (e) {
      console.error("Failed to update course status", e);
    } finally {
      setStatusSaving(false);
    }
  };

  const hasLoadedRef = React.useRef(false);

  // Only show the "Loading…" placeholders on the very first load. Every later
  // refresh (e.g. after a course status change, or the Plan view saving an edit)
  // is a quiet background refresh — swap in the new data once it arrives, but
  // don't blank out the cards to a loading state in the meantime.
  const refreshPanelData = React.useCallback(() => {
    const token = localStorage.getItem("token");
    const isFirstLoad = !hasLoadedRef.current;
    hasLoadedRef.current = true;

    if (isFirstLoad) setProgressLoading(true);
    fetch(`${window.API_BASE}/api/profile/progress`, { headers: { "Authorization": "Bearer " + token } })
      .then(res => res.json())
      .then(setProgress)
      .catch(() => setProgress({ unavailable: true, notes: ["Couldn't load progress right now."] }))
      .finally(() => { if (isFirstLoad) setProgressLoading(false); });

    if (isFirstLoad) setPlanLoading(true);
    fetch(`${window.API_BASE}/api/plan`, { headers: { "Authorization": "Bearer " + token } })
      .then(res => res.json())
      .then(data => setPlanSemesters(data.semesters || []))
      .catch(() => setPlanSemesters([]))
      .finally(() => { if (isFirstLoad) setPlanLoading(false); });
  }, []);

  React.useEffect(() => {
    if (!currentUser) return;
    refreshPanelData();
  }, [currentUser, refreshPanelData]);

  // Exposed so the Plan view (a sibling, not a parent/child of this panel) can
  // trigger a refresh right after it saves an edit — otherwise this panel would
  // only pick up plan changes on the next full page load.
  React.useEffect(() => {
    window.__refreshPlanTimeline = refreshPanelData;
    return () => { if (window.__refreshPlanTimeline === refreshPanelData) delete window.__refreshPlanTimeline; };
  }, [refreshPanelData]);

  const pct = (progress && !progress.unavailable && progress.total_credits)
    ? Math.min(100, Math.round((progress.completed_credits / progress.total_credits) * 100))
    : 0;

  return (
    <aside className={`panel ${open ? "drawer-open" : ""}`}>
      <div className="panel-head">
        <h3>Context</h3>
        <button className="close-panel" onClick={onClose}><I.x /></button>
      </div>

      <div className="panel-scroll">
        {/* Progress */}
        <div className="panel-card">
          <div className="pc-head">
            <h4>Degree Progress</h4>
            {progress && !progress.unavailable && <span className="tag">{progress.completed_credits}/{progress.total_credits ?? "?"} cr</span>}
          </div>
          <div className="pc-body">
            {progressLoading && <small className="chip-empty">Loading progress…</small>}

            {!progressLoading && progress && progress.unavailable && (
              <small className="chip-empty">
                {currentUser && currentUser.major && currentUser.major !== "Not set"
                  ? `No detailed requirements on file yet for ${currentUser.major}.`
                  : "Set your major in your profile to see degree progress."}
              </small>
            )}

            {!progressLoading && progress && !progress.unavailable && (
              <React.Fragment>
                <div className="progress-wrap">
                  <div className="donut">
                    <svg viewBox="0 0 100 100">
                      <circle className="donut-bg" cx="50" cy="50" r="38" />
                      <circle
                        className="donut-fg"
                        cx="50" cy="50" r="38"
                        strokeDasharray={C}
                        strokeDashoffset={C * (1 - pct/100)}
                      />
                    </svg>
                    <div className="donut-label">{pct}%</div>
                  </div>
                  <div className="progress-meta">
                    <b>Credits completed</b>
                    <small>{currentUser ? [
                      currentUser.year !== "Not set" ? currentUser.year : null,
                      currentUser.major !== "Not set" ? currentUser.major : null,
                    ].filter(Boolean).join(" · ") : ""}</small>
                    <small style={{marginTop: 6, color: "var(--accent)"}}>{currentUser && currentUser.expectedGrad !== "Not set" ? `Expected grad · ${currentUser.expectedGrad}` : ""}</small>
                  </div>
                </div>
                {progress.groups.map(g => (
                  <div className="progress-row" key={g.label}>
                    <span>{g.label}</span>
                    <span>{g.completed}/{g.total}</span>
                  </div>
                ))}
                {progress.notes && progress.notes.map((n, i) => (
                  <small key={i} className="chip-empty" style={{ display: "block", marginTop: 6 }}>{n}</small>
                ))}
              </React.Fragment>
            )}
          </div>
        </div>

        {/* Timeline */}
        <div className="panel-card">
          <div className="pc-head">
            <h4>Plan Timeline</h4>
            <span className="tag">{planSemesters.filter(s => !s.unscheduled).length} terms</span>
          </div>
          <div className="pc-body">
            {planLoading && <small className="chip-empty">Loading plan…</small>}
            {!planLoading && planSemesters.length === 0 && (
              <small className="chip-empty">No plan yet — build one in the Plan tab.</small>
            )}
            {planSemesters.map((p, i) => (
              <div className="timeline-row" key={i}>
                <span className="timeline-term">{p.term}</span>
                <div className="timeline-courses">
                  {p.courses.map((c, ci) => {
                    // Completion is per-course, not per-semester — a semester only counts
                    // as fully "completed" once every course in it is done, but a single
                    // finished course should show as done immediately regardless of the
                    // rest of that semester's status. An explicit "in progress" mark
                    // overrides the semester's own inferred current/planned state too.
                    const code = c.code || "";
                    const upper = code.toUpperCase();
                    const isDone = completedSet.has(upper);
                    const isInProgress = inProgressSet.has(upper);
                    const statusClass = isDone ? "completed" : isInProgress ? "current" : (p.status === "current" ? "current" : "planned");
                    const chipKey = `${i}-${ci}`;
                    const currentStatusId = isDone ? "completed" : isInProgress ? "in_progress" : "incomplete";
                    return (
                      <span key={`${c.code}-${ci}`} style={{ position: "relative", display: "inline-block" }}>
                        <button
                          type="button"
                          className={`timeline-chip ${statusClass}`}
                          style={{ cursor: "pointer", border: "1px solid transparent" }}
                          onClick={() => setOpenChip(openChip === chipKey ? null : chipKey)}
                        >
                          {c.code}
                        </button>
                        {openChip === chipKey && (
                          <div
                            ref={popupRef}
                            className="status-popup"
                            style={{
                              position: "absolute", top: "calc(100% + 4px)", left: 0, zIndex: 30,
                              background: "var(--card)", border: "1px solid var(--line)", borderRadius: "var(--r-sm)",
                              boxShadow: "0 8px 24px -8px rgba(0,0,0,0.3)", padding: 4, display: "flex", flexDirection: "column",
                              minWidth: 130,
                            }}
                          >
                            {COURSE_STATUSES.map(s => (
                              <button
                                key={s.id}
                                type="button"
                                disabled={statusSaving}
                                onClick={() => setCourseStatus(code, s.id)}
                                style={{
                                  display: "flex", alignItems: "center", gap: 6,
                                  padding: "6px 8px", fontSize: 12, borderRadius: 4, textAlign: "left",
                                  background: currentStatusId === s.id ? "var(--card-2)" : "transparent",
                                  fontWeight: currentStatusId === s.id ? 600 : 400,
                                  color: "var(--ink-2)", cursor: statusSaving ? "default" : "pointer",
                                }}
                                onMouseEnter={(e) => { if (currentStatusId !== s.id) e.currentTarget.style.background = "var(--card-2)"; }}
                                onMouseLeave={(e) => { if (currentStatusId !== s.id) e.currentTarget.style.background = "transparent"; }}
                              >
                                <span className={`timeline-chip ${s.id === "completed" ? "completed" : s.id === "in_progress" ? "current" : "planned"}`} style={{ width: 8, height: 8, padding: 0, border: "none" }} />
                                {s.label}
                              </button>
                            ))}
                          </div>
                        )}
                      </span>
                    );
                  })}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </aside>
  );
}

window.ContextPanel = ContextPanel;
