
const { useState, useEffect, useRef } = React;

const API_BASE = 'https://transfer-lens.onrender.com';

const STEPS = [
  { id: 'cc',      label: 'Your College' },
  { id: 'term',    label: 'Timeline' },
  { id: 'schools', label: 'Target Schools' },
  { id: 'majors',  label: 'Majors' },
  { id: 'calgetc', label: 'Cal-GETC' },
  { id: 'review',  label: 'Review' },
];

const GE_AREAS = [
  {
    id: '1A',
    name: 'English Composition',
    description: 'Pick one course to satisfy Area 1A — English Composition.',
    pick: 1,
    courses: ['ENGL C1000', 'ENGL C1000H'],
  },
  {
    id: '1B',
    name: 'Critical Thinking',
    description: 'Pick one course to satisfy Area 1B — Critical Thinking.',
    pick: 1,
    courses: ['ENGL C1001', 'ENGL C1001H', 'LIB 20'],
  },
  {
    id: '1C',
    name: 'Oral Communication',
    description: 'Pick one course to satisfy Area 1C — Oral Communication.',
    pick: 1,
    courses: ['COMM C1000', 'COMM C1000H'],
  },
  {
    id: '3A',
    name: 'Arts',
    description: 'Pick one course to satisfy Area 3A — Arts.',
    pick: 1,
    courses: [
      'ART HIST 1', 'ART HIST 4', 'ART HIST 20',
      'DANCE 77', 'DANCE 78',
      'MUS 1', 'MUS 20', 'MUS 28',
      'THEATRE ARTS 20', 'THEATRE ARTS 21', 'THEATRE ARTS 22',
      'THEATRE ARTS 25', 'THEATRE ARTS 26', 'THEATRE ARTS 27',
    ],
  },
  {
    id: '3B',
    name: 'Humanities',
    description: 'Pick one course to satisfy Area 3B — Humanities.',
    pick: 1,
    courses: [
      'FILM 70', 'FILM 71', 'FILM 72',
      'FREN 2', 'FREN 3', 'FREN 4',
      'HIST 1', 'HIST 2', 'HIST 10', 'HIST 11', 'HIST 20', 'HIST 21',
      'JA 2', 'JA 3', 'JA 4',
      'LIT 1', 'LIT 7', 'LIT 16', 'LIT 20', 'LIT 21', 'LIT 22', 'LIT 23',
      'PHIL 1', 'PHIL 2', 'PHIL 10', 'PHIL 11',
      'SPAN 2', 'SPAN 3', 'SPAN 4',
    ],
  },
  {
    id: '4',
    name: 'Social & Behavioral Sciences',
    description: 'Pick 2 courses from 2 different disciplines to satisfy Area 4.',
    pick: 2,
    twoDisciplines: true,
    disciplines: {
      'Anthropology':      ['ANTHRO 2', 'ANTHRO 3', 'ANTHRO 4'],
      'Economics':         ['ECON 1', 'ECON 2'],
      'Geography':         ['GEOG 2', 'GEOG 3', 'GEOG 20'],
      'History':           ['HIST 1', 'HIST 2', 'HIST 20', 'HIST 21'],
      'Political Science': ['POLS C1000'],
      'Psychology':        ['PSYC C1000', 'PSYC 2', 'PSYC 5'],
      'Sociology':         ['SOCI 1', 'SOCI 2', 'SOCI 3'],
    },
  },
  {
    id: '5A',
    name: 'Physical Science',
    description: 'Pick one course to satisfy Area 5A — Physical Science.',
    pick: 1,
    courses: [
      'ASTRON 20', 'ASTRON 20H', 'ASTRON 25',
      'BIO 10',
      'CHEM 1A', 'CHEM 1AH', 'CHEM 1B', 'CHEM 3', 'CHEM 4', 'CHEM 12A', 'CHEM 12B',
      'EARTH SCI 20',
      'GEOG 1', 'GEOG 10', 'GEOG 10H',
      'GEOL 1', 'GEOL 2', 'GEOL 3', 'GEOL 22', 'GEOL 23',
      'MARINE SCI 20',
      'PHYS 2A', 'PHYS 2B', 'PHYS 4A', 'PHYS 4B', 'PHYS 4C', 'PHYS 20',
    ],
  },
  {
    id: '5B',
    name: 'Biological Science',
    description: 'Pick one course to satisfy Area 5B — Biological Science.',
    pick: 1,
    courses: [
      'ANTHRO 1', 'ANTHRO 1H',
      'BIO 1', 'BIO 2', 'BIO 3', 'BIO 5', 'BIO 11', 'BIO 12', 'BIO 15', 'BIO 16',
      'BIO 19', 'BIO 19H', 'BIO 21', 'BIO 30', 'BIO 43', 'BIO 44', 'BIO 55',
      'BIO 71', 'BIO 72', 'BIO 80', 'BIO 80H', 'BIO 81', 'BIO 81H', 'BIO 82', 'BIO 83',
      'BIOTECH 70',
      'PSYC 3', 'PSYC 3H',
    ],
  },
  {
    id: '6',
    name: 'Ethnic Studies',
    description: 'Pick one course to satisfy Area 6 — Ethnic Studies.',
    pick: 1,
    courses: ['ETHN 10', 'ETHN 20', 'ETHN 30', 'ETHN 40'],
  },
];

// Default GE picks: the first course in each area (and the first course from
// two distinct disciplines for Area 4) — the same first-in-list GE_AREAS
// defaults the Cal-GETC tab uses. The wizard no longer asks the student to pick
// GE, so this seeds ge_selections and keeps the ge_selections → generate-plan
// flow populated; the Cal-GETC tab refines it plan-aware after generation.
// Science areas 5A/5B are deliberately omitted: STEM majors already cover them
// with their own science courses (a static default like ASTRON 20 / ANTHRO 1
// would double-schedule), and the Cal-GETC tab fills science areas plan-aware.
const GE_DEFAULT_SKIP = new Set(['5A', '5B']);
const DEFAULT_GE_SELECTIONS = (() => {
  const sel = {};
  for (const area of GE_AREAS) {
    if (GE_DEFAULT_SKIP.has(area.id)) continue;
    if (area.twoDisciplines) {
      const discs = Object.values(area.disciplines);
      sel[area.id] = [discs[0] && discs[0][0], discs[1] && discs[1][0]].filter(Boolean);
    } else {
      sel[area.id] = area.courses.length ? [area.courses[0]] : [];
    }
  }
  return sel;
})();

function StepDots({ current }) {
  return (
    <div className="wiz-dots">
      {STEPS.map((s, i) => (
        <div key={s.id} className={`wiz-dot-item ${i === current ? 'active' : ''} ${i < current ? 'done' : ''}`}>
          <div className="wiz-dot"></div>
        </div>
      ))}
      <div className="wiz-step-label">{current + 1} / {STEPS.length}</div>
    </div>
  );
}

/* ─── Step 1: Community College ─── */
function StepCC({ value, onChange }) {
  const [query, setQuery] = useState('');
  const inputRef = useRef(null);
  useEffect(() => { inputRef.current?.focus(); }, []);

  const filtered = query.length > 0
    ? window.MOCK_CCS.filter(c => c.name.toLowerCase().includes(query.toLowerCase()) || c.city.toLowerCase().includes(query.toLowerCase()))
    : window.MOCK_CCS;

  return (
    <div className="wiz-step">
      <div className="wiz-q">Which community college do you attend?</div>
      <div className="wiz-hint">We'll use this to look up your articulation agreements.</div>
      {value && (
        <div className="wiz-selected-banner">
          <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8l3.5 3.5L13 5" stroke="var(--green)" strokeWidth="2" strokeLinecap="round"/></svg>
          <span>{value.name}</span>
          <button className="wiz-selected-clear" onClick={() => onChange(null)}>Change</button>
        </div>
      )}
      {!value && (
        <div className="wiz-search-wrap">
          <svg className="wiz-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="6.5" cy="6.5" r="4" stroke="currentColor" strokeWidth="1.5"/><path d="M10 10l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
          <input ref={inputRef} className="wiz-search" placeholder="Search colleges…" value={query} onChange={e => setQuery(e.target.value)} />
        </div>
      )}
      {!value && (
        <div className="wiz-list">
          {filtered.map(cc => (
            <button key={cc.id} className={`wiz-list-item ${cc.id === 'ivc' ? 'default' : ''}`} onClick={() => onChange(cc)}>
              <div className="wiz-list-item-left">
                <div className="wiz-list-name">{cc.name}</div>
                <div className="wiz-list-sub">{cc.city}</div>
              </div>
              {cc.id === 'ivc' && <span className="wiz-default-badge">Default</span>}
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

/* ─── Step 2: Transfer Term ─── */
function StepTerm({ value, onChange }) {
  return (
    <div className="wiz-step">
      <div className="wiz-q">When do you plan to transfer?</div>
      <div className="wiz-hint">This determines how many semesters you have to complete your coursework.</div>
      <div className="wiz-term-grid">
        {window.TRANSFER_TERMS.map(t => (
          <button key={t.id} className={`wiz-term-btn ${value.term === t.id ? 'active' : ''}`} onClick={() => onChange({ ...value, term: t.id })}>
            {t.label}
          </button>
        ))}
      </div>
      <div className="wiz-divider"></div>
      <div className="wiz-q-small">Would you like to use summer semesters?</div>
      <div className="wiz-toggle-row">
        <button className={`wiz-toggle-btn ${value.useSummer ? 'active' : ''}`} onClick={() => onChange({ ...value, useSummer: true })}>Yes — I'm open to it</button>
        <button className={`wiz-toggle-btn ${!value.useSummer ? 'active' : ''}`} onClick={() => onChange({ ...value, useSummer: false })}>No, keep it to fall & spring</button>
      </div>
      <div className={`wiz-reveal ${value.useSummer ? 'wiz-reveal-open' : ''}`}>
        <div className="wiz-reveal-inner">
          <div className="wiz-q-small" style={{ marginTop: 20 }}>Summer load preference</div>
          <div className="wiz-toggle-row">
            <button className={`wiz-toggle-btn ${value.summerLoad === 'light' ? 'active' : ''}`} onClick={() => onChange({ ...value, summerLoad: 'light' })}>Light — 1 course</button>
            <button className={`wiz-toggle-btn ${value.summerLoad === 'full' ? 'active' : ''}`} onClick={() => onChange({ ...value, summerLoad: 'full' })}>Full — up to 4 courses</button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ─── Step 3: Target Schools (API) ─── */
function StepSchools({ value, onChange }) {
  const [query, setQuery] = useState('');
  const [allSchools, setAllSchools] = useState({ UC: [], CSU: [] });
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const inputRef = useRef(null);

  useEffect(() => { inputRef.current?.focus(); }, []);

  const loadSchools = () => {
    setLoading(true);
    setError(null);
    Promise.all([
      fetch(`${API_BASE}/api/institutions?category=UC`).then(r => r.ok ? r.json() : Promise.reject('UC fetch failed')),
      fetch(`${API_BASE}/api/institutions?category=CSU`).then(r => r.ok ? r.json() : Promise.reject('CSU fetch failed')),
    ]).then(([uc, csu]) => {
      const mapSchool = (s, type) => ({ id: s.id, name: s.name, abbr: s.code, type });
      setAllSchools({ UC: uc.map(s => mapSchool(s, 'UC')), CSU: csu.map(s => mapSchool(s, 'CSU')) });
      setLoading(false);
    }).catch(err => {
      setError(typeof err === 'string' ? err : 'Failed to load schools. Please check your connection.');
      setLoading(false);
    });
  };

  useEffect(() => { loadSchools(); }, []);

  const all = [...allSchools.UC, ...allSchools.CSU];
  const filtered = query.length > 1
    ? { UC: all.filter(s => s.type === 'UC' && (s.name.toLowerCase().includes(query.toLowerCase()) || s.abbr.toLowerCase().includes(query.toLowerCase()))),
        CSU: all.filter(s => s.type === 'CSU' && (s.name.toLowerCase().includes(query.toLowerCase()) || s.abbr.toLowerCase().includes(query.toLowerCase()))) }
    : allSchools;

  const toggle = (school) => {
    const exists = value.find(s => s.id === school.id);
    if (exists) onChange(value.filter(s => s.id !== school.id));
    else onChange([...value, school]);
  };

  // "Select All UCs / CSUs" bulk toggles. Operate on the whole system for that
  // type (not the filtered view) so the label means what it says. Checked only
  // when every school of that type is already selected.
  const allOfTypeSelected = (type) => {
    const list = allSchools[type] || [];
    return list.length > 0 && list.every(s => value.find(v => v.id === s.id));
  };
  const toggleAllOfType = (type) => {
    const list = allSchools[type] || [];
    if (allOfTypeSelected(type)) {
      const ids = new Set(list.map(s => s.id));
      onChange(value.filter(s => !ids.has(s.id)));
    } else {
      const have = new Set(value.map(s => s.id));
      onChange([...value, ...list.filter(s => !have.has(s.id))]);
    }
  };

  return (
    <div className="wiz-step">
      <div className="wiz-q">Which schools are you applying to?</div>
      <div className="wiz-hint">Select all that apply — we'll find overlapping courses that satisfy multiple schools at once.</div>
      {value.length > 0 && (
        <div className="wiz-pills-row">
          {value.map(s => (
            <span key={s.id} className="wiz-pill-tag">
              {s.abbr}
              <button className="wiz-pill-remove" onClick={() => toggle(s)}>×</button>
            </span>
          ))}
        </div>
      )}
      <div className="wiz-search-wrap">
        <svg className="wiz-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="6.5" cy="6.5" r="4" stroke="currentColor" strokeWidth="1.5"/><path d="M10 10l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/></svg>
        <input ref={inputRef} className="wiz-search" placeholder="Search schools…" value={query} onChange={e => setQuery(e.target.value)} />
      </div>
      {!loading && !error && (
        <div className="wiz-select-all-row">
          {[['UC', 'Select all UCs'], ['CSU', 'Select all CSUs']].map(([type, label]) => {
            const checked = allOfTypeSelected(type);
            return (
              <button
                key={type}
                className={`wiz-select-all ${checked ? 'checked' : ''}`}
                onClick={() => toggleAllOfType(type)}
                aria-pressed={checked}
              >
                <span className={`wiz-check-box ${checked ? 'checked' : ''}`}>
                  {checked && <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2 6l2.5 2.5L10 3" stroke="white" strokeWidth="1.8" strokeLinecap="round"/></svg>}
                </span>
                {label}
              </button>
            );
          })}
        </div>
      )}
      {loading && <div style={{ padding: '24px', textAlign: 'center', color: 'var(--text-3)', fontSize: '0.9rem' }}>Loading schools…</div>}
      {error && (
        <div style={{ padding: '16px', textAlign: 'center' }}>
          <div style={{ color: 'var(--red)', marginBottom: 12, fontSize: '0.88rem' }}>{error}</div>
          <button className="wiz-nav-sm" onClick={loadSchools}>Retry</button>
        </div>
      )}
      {!loading && !error && (
        <div className="wiz-school-groups">
          {[['UC', 'UC System'], ['CSU', 'CSU System']].map(([type, label]) => {
            const list = (filtered[type] || []);
            if (!list.length) return null;
            return (
              <div key={type} className="wiz-school-group">
                <div className="wiz-school-group-label">{label}</div>
                {list.map(s => {
                  const selected = value.find(v => v.id === s.id);
                  return (
                    <button key={s.id} className={`wiz-list-item ${selected ? 'selected' : ''}`} onClick={() => toggle(s)}>
                      <div className="wiz-list-item-left">
                        <div className="wiz-list-name">{s.name}</div>
                      </div>
                      <div className={`wiz-check-box ${selected ? 'checked' : ''}`}>
                        {selected && <svg width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M2 6l2.5 2.5L10 3" stroke="white" strokeWidth="1.8" strokeLinecap="round"/></svg>}
                      </div>
                    </button>
                  );
                })}
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

/* ─── Step 4: Majors (API per school) ─── */
function MajorSearchSelect({ school, value, onChange }) {
  const [query, setQuery] = React.useState('');
  const [open, setOpen] = React.useState(false);
  const [majors, setMajors] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const ref = React.useRef(null);

  React.useEffect(() => {
    setLoading(true);
    fetch(`${API_BASE}/api/institutions/${school.id}/majors`)
      .then(r => r.ok ? r.json() : [])
      .then(data => { setMajors(Array.isArray(data) ? data : []); setLoading(false); })
      .catch(() => setLoading(false));
  }, [school.id]);

  // Collapse whitespace runs on both sides: ASSIST labels carry doubled
  // spaces ('Aerospace  Engineering/B.S') that defeat a plain includes().
  const normLabel = s => s.toLowerCase().replace(/\s+/g, ' ').trim();
  const filtered = query
    ? majors.filter(m => normLabel(m.label).includes(normLabel(query)))
    : majors;

  React.useEffect(() => {
    function handleClick(e) {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    }
    document.addEventListener('mousedown', handleClick);
    return () => document.removeEventListener('mousedown', handleClick);
  }, []);

  const select = (m) => { onChange(m); setQuery(''); setOpen(false); };
  const displayValue = value?.label || '';

  return (
    <div ref={ref} style={{ flex: 1, position: 'relative' }}>
      <div
        style={{
          display: 'flex', alignItems: 'center',
          padding: '10px 14px', border: `1.5px solid ${open ? 'var(--accent)' : 'var(--divider)'}`,
          borderRadius: 'var(--radius)', background: 'var(--bg)', cursor: 'text',
          gap: 8, transition: 'border-color 0.15s',
        }}
        onClick={() => { if (!loading) setOpen(true); }}
      >
        <svg width="13" height="13" viewBox="0 0 13 13" fill="none" style={{ color: 'var(--text-3)', flexShrink: 0 }}>
          <circle cx="5.5" cy="5.5" r="3.5" stroke="currentColor" strokeWidth="1.4"/>
          <path d="M8.5 8.5l2.5 2.5" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round"/>
        </svg>
        <input
          style={{ flex: 1, border: 'none', background: 'transparent', fontFamily: 'var(--font)', fontSize: '0.9rem', color: 'var(--text)', outline: 'none' }}
          placeholder={loading ? 'Loading majors…' : (displayValue || '— Search a major —')}
          value={open ? query : displayValue}
          onChange={e => { setQuery(e.target.value); setOpen(true); }}
          onFocus={() => { if (!loading) { setOpen(true); setQuery(''); } }}
          readOnly={loading}
        />
        <span style={{ color: 'var(--text-3)', fontSize: '0.7rem', flexShrink: 0 }}>▾</span>
      </div>
      {open && !loading && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 4px)', left: 0, right: 0, zIndex: 200,
          background: 'var(--bg)', border: '1px solid var(--divider)', borderRadius: 'var(--radius)',
          boxShadow: 'var(--shadow)', maxHeight: 240, overflowY: 'auto',
        }}>
          {filtered.length === 0 && (
            <div style={{ padding: '12px 14px', fontSize: '0.82rem', color: 'var(--text-3)' }}>No matches</div>
          )}
          {filtered.map(m => (
            <button key={m.id}
              style={{
                display: 'block', width: '100%', textAlign: 'left', padding: '10px 14px',
                border: 'none', background: value?.id === m.id ? 'var(--accent-bg)' : 'none',
                color: value?.id === m.id ? 'var(--accent)' : 'var(--text)',
                fontFamily: 'var(--font)', fontSize: '0.88rem', fontWeight: value?.id === m.id ? 600 : 400,
                cursor: 'pointer', transition: 'background 0.1s',
              }}
              onMouseEnter={e => { if (value?.id !== m.id) e.currentTarget.style.background = 'var(--surface)'; }}
              onMouseLeave={e => { if (value?.id !== m.id) e.currentTarget.style.background = 'none'; }}
              onClick={() => select(m)}
            >{m.label}</button>
          ))}
        </div>
      )}
    </div>
  );
}

function StepMajors({ schools, value, onChange }) {
  const [intent, setIntent] = React.useState('');
  const [resolving, setResolving] = React.useState(false);
  const [resolveError, setResolveError] = React.useState(false);
  // school_id -> { outcome: 'direct'|'adjacent'|'none', major, reason }
  const [results, setResults] = React.useState(null);
  const [resolvedIntent, setResolvedIntent] = React.useState('');

  const handleResolve = async () => {
    const want = intent.trim();
    if (!want || resolving) return;
    setResolving(true);
    setResolveError(false);
    try {
      const res = await fetch(`${API_BASE}/api/resolve-major`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ intent: want, school_ids: schools.map(s => s.id) }),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const data = await res.json();
      const byId = {};
      const picks = { ...value };
      for (const r of data.results) {
        byId[r.institution_id] = r;
        // Direct and adjacent matches are pre-selected (overridable below);
        // "none" clears the slot so the student must choose by hand.
        picks[r.institution_id] = r.major || null;
      }
      setResults(byId);
      setResolvedIntent(want);
      onChange(picks);
    } catch (e) {
      console.error('Major resolution failed:', e);
      setResolveError(true);
    } finally {
      setResolving(false);
    }
  };

  const outcomeLine = (school) => {
    if (!results || !results[school.id]) return null;
    const r = results[school.id];
    if (r.outcome === 'direct') {
      return <div className="wiz-match-note wiz-match-direct">✓ {school.abbr} offers this</div>;
    }
    if (r.outcome === 'adjacent') {
      // Domain-similarity framing only — we have no usage data yet.
      // FUTURE HOOK: once real usage data exists, this copy can upgrade to
      // "students who selected {resolvedIntent} most often chose {r.major.label}
      // at {school.abbr}" — keep the honest fallback for thin data.
      return (
        <div className="wiz-match-note wiz-match-adjacent">
          {school.abbr} doesn't offer {resolvedIntent} — {r.reason} Closest match pre-selected; change it if it's not right.
        </div>
      );
    }
    return <div className="wiz-match-note wiz-match-none">No strong match — please choose from {school.abbr}'s majors.</div>;
  };

  return (
    <div className="wiz-step">
      <div className="wiz-q">What do you want to study?</div>
      <div className="wiz-hint">Tell us once — we'll find the matching major at each of your schools. You can override any of them.</div>
      <div className="wiz-intent-row">
        <input
          className="wiz-intent-input"
          placeholder="e.g. Computer Science, Aerospace Engineering, Nursing…"
          value={intent}
          onChange={e => setIntent(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') handleResolve(); }}
        />
        <button className="wiz-resolve-btn" onClick={handleResolve} disabled={resolving || !intent.trim()}>
          {resolving ? 'Matching…' : 'Find my majors'}
        </button>
      </div>
      {resolveError && (
        <div className="wiz-match-note wiz-match-none">Couldn't run the match — pick majors manually below or try again.</div>
      )}
      <div className="wiz-majors-list">
        {schools.map(school => (
          <div key={school.id} className="wiz-major-block">
            <div className="wiz-major-row">
              <div className="wiz-major-school">{school.abbr}</div>
              <MajorSearchSelect
                school={school}
                value={value[school.id] || null}
                onChange={m => onChange({ ...value, [school.id]: m })}
              />
            </div>
            {outcomeLine(school)}
          </div>
        ))}
      </div>
    </div>
  );
}

/* ─── Step 5: Cal-GETC ─── */
function StepCalGETC({ value, onChange }) {
  return (
    <div className="wiz-step">
      <div className="wiz-q">Cal-GETC or 7-Course Breadth?</div>
      <div className="wiz-hint">Cal-GETC is the California community college general education pattern. Your choice depends on your target schools.</div>
      <div className="wiz-getc-options">
        <button className={`wiz-getc-card ${value === 'full' ? 'active' : ''}`} onClick={() => onChange('full')}>
          <div className="wiz-getc-title">Full Cal-GETC</div>
          <div className="wiz-getc-sub">All 11 areas · Required for most CSU transfers and preferred by UC</div>
          <div className="wiz-getc-tag">Recommended for most students</div>
        </button>
        <button className={`wiz-getc-card ${value === 'breadth' ? 'active' : ''}`} onClick={() => onChange('breadth')}>
          <div className="wiz-getc-title">7-Course Breadth</div>
          <div className="wiz-getc-sub">Minimum UC requirement · 7 courses across 3 subject areas</div>
          <div className="wiz-getc-tag">UC minimum only</div>
        </button>
      </div>
    </div>
  );
}

/* ─── Step 6: Review ─── */
function StepReview({ state }) {
  const { cc, term, schools, majors, calgetcMode, geSelections, useSummer } = state;
  const termLabel = (window.TRANSFER_TERMS.find(t => t.id === term) || {}).label || term;
  const geAreasDone = GE_AREAS.filter(a => (geSelections[a.id] || []).length > 0).length;
  const geCourseCount = Object.values(geSelections).reduce((sum, sel) => sum + (sel?.length || 0), 0);
  return (
    <div className="wiz-step">
      <div className="wiz-q">You're all set — let's build your plan.</div>
      <div className="wiz-hint">Here's a summary of what we'll use. You can change anything inside the plan builder.</div>
      <div className="wiz-review-card">
        <div className="wiz-review-row"><span className="wiz-review-label">Community College</span><span className="wiz-review-val">{cc?.name || 'Not set'}</span></div>
        <div className="wiz-review-row"><span className="wiz-review-label">Transfer Term</span><span className="wiz-review-val">{termLabel}</span></div>
        <div className="wiz-review-row"><span className="wiz-review-label">Summer Semesters</span><span className="wiz-review-val">{useSummer ? 'Yes' : 'No'}</span></div>
        <div className="wiz-review-row">
          <span className="wiz-review-label">Target Schools</span>
          <span className="wiz-review-val">
            {schools.length === 0 ? 'None selected' : schools.map(s => s.abbr).join(', ')}
          </span>
        </div>
        <div className="wiz-review-row">
          <span className="wiz-review-label">Majors</span>
          <div className="wiz-review-majors">
            {schools.map(s => (
              <div key={s.id} className="wiz-review-major-row">
                <span className="wiz-review-school-tag">{s.abbr}</span>
                <span className="wiz-review-major-name">{majors[s.id]?.label || 'Not set'}</span>
              </div>
            ))}
          </div>
        </div>
        <div className="wiz-review-row"><span className="wiz-review-label">Cal-GETC Pattern</span><span className="wiz-review-val">{calgetcMode === 'full' ? 'Full Cal-GETC (11 areas)' : '7-Course Breadth'}</span></div>
        <div className="wiz-review-row"><span className="wiz-review-label">GE Courses</span><span className="wiz-review-val">{geCourseCount} courses · {geAreasDone} of {GE_AREAS.length} areas</span></div>
      </div>
      <div className="wiz-review-note">
        The smart scheduler will place your courses in the ideal order based on prerequisites, unit caps, and difficulty balance.
      </div>
    </div>
  );
}

/* ─── Wizard Shell ─── */
function Wizard({ onComplete }) {
  const [step, setStep] = useState(0);
  const [animDir, setAnimDir] = useState(1);
  const [animating, setAnimating] = useState(false);

  const [cc, setCC] = useState(window.MOCK_CCS[0]);
  const [termState, setTermState] = useState({ term: 'fall-2027', useSummer: false, summerLoad: 'light' });
  const [schools, setSchools] = useState([]);
  const [majors, setMajors] = useState({});
  const [calgetcMode, setCalgetcMode] = useState('full');
  // The wizard no longer has a GE picker step; ge_selections is seeded with the
  // GE_AREAS defaults so generate-plan still receives populated GE coursework.
  const [geSelections] = useState(DEFAULT_GE_SELECTIONS);

  const canNext = () => {
    if (step === 0) return !!cc;
    if (step === 2) return schools.length > 0;
    if (step === 3) return schools.every(s => !!majors[s.id]);
    return true;
  };

  const go = (dir) => {
    if (animating) return;
    const next = step + dir;
    if (next < 0 || next >= STEPS.length) return;
    setAnimDir(dir);
    setAnimating(true);
    setTimeout(() => {
      setStep(next);
      setAnimating(false);
    }, 180);
  };

  const generate = () => {
    onComplete({
      cc,
      ...termState,
      selections: schools.map(s => ({ school: s, major: majors[s.id] || null })),
      calgetcMode,
      geSelections,
    });
  };

  const stepState = { cc, term: termState.term, schools, majors, calgetcMode, geSelections, useSummer: termState.useSummer };

  const steps = [
    <StepCC key="cc" value={cc} onChange={setCC} />,
    <StepTerm key="term" value={termState} onChange={setTermState} />,
    <StepSchools key="schools" value={schools} onChange={setSchools} />,
    <StepMajors key="majors" schools={schools} value={majors} onChange={setMajors} />,
    <StepCalGETC key="calgetc" value={calgetcMode} onChange={setCalgetcMode} />,
    <StepReview key="review" state={stepState} />,
  ];

  return (
    <div className="wizard-overlay">
      <div className="wizard-inner">
        <StepDots current={step} />
        <div className={`wizard-body ${animating ? (animDir > 0 ? 'wiz-out-left' : 'wiz-out-right') : 'wiz-in'}`}>
          {steps[step]}
        </div>
        <div className="wizard-nav">
          <button className="wiz-back-btn" onClick={() => go(-1)} disabled={step === 0}>
            ← Back
          </button>
          <div className="wiz-nav-right">
            {step < STEPS.length - 1 ? (
              <button className={`wiz-next-btn ${!canNext() ? 'disabled' : ''}`} onClick={() => canNext() && go(1)}>
                Continue →
              </button>
            ) : (
              <button className="wiz-generate-btn" onClick={generate}>
                ✦ Generate My Plan
              </button>
            )}
            {canNext() && step < STEPS.length - 1 && (
              <div className="wiz-enter-hint">press Enter to continue</div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Wizard });
