/* global React, window */
const { useState, useEffect, useMemo, useRef } = React;

// --- Small helpers ---
function cx(...xs) { return xs.filter(Boolean).join(" "); }

function useLocalStorage(key, initial) {
  const [v, setV] = useState(() => {
    try {
      const raw = localStorage.getItem(key);
      return raw ? JSON.parse(raw) : initial;
    } catch { return initial; }
  });
  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(v)); } catch {}
  }, [key, v]);
  return [v, setV];
}

// ---- Editable inline text ----
function Editable({ value, onChange, placeholder, className }) {
  const ref = useRef(null);
  const onBlur = () => {
    const t = ref.current.innerText.trim();
    onChange(t || placeholder || "");
  };
  const onKeyDown = (e) => {
    if (e.key === "Enter") { e.preventDefault(); ref.current.blur(); }
    if (e.key === "Escape") { ref.current.innerText = value; ref.current.blur(); }
  };
  return (
    <span
      ref={ref}
      className={cx("editable", className)}
      contentEditable
      suppressContentEditableWarning
      spellCheck={false}
      onBlur={onBlur}
      onKeyDown={onKeyDown}
    >{value}</span>
  );
}

// ---- Milestone card ----
function Milestone({ m, done, onToggle, onOpen, dimmed }) {
  const Icon = window.Icons[m.icon] || window.Icons.Target;
  return (
    <button
      className={cx("milestone", done && "done", m.accent && "accent")}
      style={dimmed ? {opacity: 0.28} : undefined}
      onClick={(e) => { e.stopPropagation(); onOpen(m); }}
    >
      <span
        className="milestone-check"
        role="checkbox"
        aria-checked={done}
        onClick={(e) => { e.stopPropagation(); onToggle(m.id); }}
      >
        <window.Icons.Check size={10} />
      </span>
      <span className="milestone-icon"><Icon size={14} /></span>
      <span className="milestone-body">
        <span className="milestone-label">{m.label}</span>
        {m.meta ? <span className="milestone-meta">{m.meta}</span> : null}
      </span>
    </button>
  );
}

// ---- Drawer ----
function Drawer({ m, onClose, done, onToggle }) {
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
  const open = !!m;
  const Icon = m ? (window.Icons[m.icon] || window.Icons.Target) : null;
  const yearRange = m
    ? (m.from === m.to ? `${m.from}th grade` : `${m.from}th – ${m.to}th grade`)
    : "";
  return (
    <>
      <div className={cx("drawer-scrim", open && "open")} onClick={onClose} />
      <aside className={cx("drawer", open && "open")} aria-hidden={!open}>
        {m && (
          <>
            <button className="drawer-close" onClick={onClose} aria-label="Close">
              <window.Icons.Close size={16} />
            </button>
            <header className="drawer-header">
              <div className="drawer-stage-tag">
                <span>{m.stage || "Milestone"}</span>
                <span className="divider" />
                <span>{yearRange}</span>
              </div>
              <h2 className={cx("drawer-title", m.accent && "accent")}>
                {m.label}
              </h2>
              {m.meta ? <div className="drawer-year-range">{m.meta}</div> : null}
            </header>
            <div className="drawer-body">
              {m.blurb ? (
                <section className="drawer-section">
                  <h4>The idea</h4>
                  <p>{m.blurb}</p>
                </section>
              ) : null}
              {m.details && m.details.length ? (
                <section className="drawer-section">
                  <h4>What it looks like</h4>
                  <ul>{m.details.map((d, i) => <li key={i}>{d}</li>)}</ul>
                </section>
              ) : null}
              <button className={cx("drawer-toggle", done && "done")} onClick={() => onToggle(m.id)}>
                <window.Icons.Check size={12} />
                {done ? "Mark as not done" : "Mark complete"}
              </button>
            </div>
          </>
        )}
      </aside>
    </>
  );
}

// ---- Grid renderer ----
function RoadmapGrid({ years, bands, milestones, done, onToggle, onOpen, focusYear, focusTrack }) {
  // Build rows per band. Inside each band, we layout by placing milestones into rows
  // so that nothing overlaps. Simple greedy row assignment.
  const bandsWithRows = useMemo(() => {
    return bands.map(band => {
      const bandMs = milestones.filter(m => m.band === band.id);
      // Assign each milestone to a row (first row where it fits)
      const rows = []; // each row: array of milestones with occupied ranges
      bandMs.forEach(m => {
        let placed = false;
        for (const row of rows) {
          const overlaps = row.some(x => !(m.to < x.from || m.from > x.to));
          if (!overlaps) { row.push(m); placed = true; break; }
        }
        if (!placed) rows.push([m]);
      });
      return { ...band, rows };
    });
  }, [bands, milestones]);

  const filtered = !!(focusYear || focusTrack);

  return (
    <div className={cx("grid", filtered && "filtered")}>
      {/* Header row: empty corner + 4 year columns */}
      <div className="col-header-empty" />
      {years.map((y, i) => {
        const isCurrent = y.id === window.ROADMAP_STATE?.current_grade;
        const dim = focusYear && focusYear !== y.id;
        return (
          <div key={y.id} className={cx("year-header", isCurrent && "current", dim && "dim")}>
            <div className="year-num">{y.id}<sup>{y.id === 11 || y.id === 12 ? "th" : (y.id === 10 ? "th" : "th")}</sup></div>
            <span className="year-label">{i === 0 ? "Discovery" : i === 3 ? "Planning" : "Growth"}</span>
          </div>
        );
      })}

      {/* Bands */}
      {bandsWithRows.map(band => {
        const trackDim = focusTrack && focusTrack !== band.track;
        return (
          <React.Fragment key={band.id}>
            {band.rows.map((row, rowIdx) => (
              <React.Fragment key={rowIdx}>
                {/* lane label only on first row of band */}
                {rowIdx === 0 ? (
                  <div className={cx("lane-label", trackDim && "dim")} style={trackDim ? {opacity: 0.35} : null}>
                    <span className="lane-eyebrow">{band.eyebrow}</span>
                    <span className="lane-name">{band.name}</span>
                    <span className="lane-sub">{band.sub}</span>
                  </div>
                ) : (
                  <div className="lane-label continuation" style={{opacity: trackDim ? 0.35 : 1}} />
                )}
                {/* Render 4 cells per year, with spanning */}
                {(() => {
                  const cells = [];
                  let col = years[0].id;
                  const rowSorted = [...row].sort((a,b) => a.from - b.from);
                  let idx = 0;
                  while (col <= years[years.length - 1].id) {
                    const m = rowSorted[idx];
                    if (m && m.from === col) {
                      const span = m.to - m.from + 1;
                      const isCurrent = window.ROADMAP_STATE?.current_grade >= m.from && window.ROADMAP_STATE?.current_grade <= m.to;
                      const cellDim = (focusYear && (focusYear < m.from || focusYear > m.to)) || trackDim;
                      cells.push(
                        <div key={`${band.id}-${rowIdx}-${col}`}
                          className={cx("cell", span > 1 && `span-${span}`, isCurrent && "current-year", cellDim && "dim")}
                          style={trackDim ? {opacity: 0.35} : null}>
                          <Milestone
                            m={m}
                            done={!!done[m.id]}
                            onToggle={onToggle}
                            onOpen={onOpen}
                          />
                        </div>
                      );
                      col += span;
                      idx += 1;
                    } else {
                      const isCurrent = window.ROADMAP_STATE?.current_grade === col;
                      const cellDim = (focusYear && focusYear !== col) || trackDim;
                      cells.push(
                        <div key={`${band.id}-${rowIdx}-${col}-empty`}
                          className={cx("cell", isCurrent && "current-year", cellDim && "dim")}
                          style={trackDim ? {opacity: 0.35} : null} />
                      );
                      col += 1;
                    }
                  }
                  return cells;
                })()}
              </React.Fragment>
            ))}
          </React.Fragment>
        );
      })}
    </div>
  );
}

window.Milestone = Milestone;
window.Drawer = Drawer;
window.RoadmapGrid = RoadmapGrid;
window.Editable = Editable;
window.useLocalStorage = useLocalStorage;
window.cx = cx;
