/* organizer-content-library.jsx — Content Library for Arena Organizer
 * React 18 · in-browser Babel · no build step
 * Deps: window.GAME_MODULES, window.AdminApi, tc(), React, ReactDOM
 *
 * Part 1: CurationContext, helpers, View 1 (ModuleOverviewGrid), toolbar components
 */

// ── Curation Context ──────────────────────────────────────────────
var CurationContext = React.createContext(null);

function curationReducer(state, action) {
  switch (action.type) {
    case 'SELECT_EVENT':
      return Object.assign({}, state, { selectedEventId: action.eventId });

    case 'SELECT_MODULE':
      return Object.assign({}, state, { selectedModuleId: action.moduleId });

    case 'SET_LANGUAGE':
      return Object.assign({}, state, { language: action.language });

    case 'INIT_CONFIGS': {
      return Object.assign({}, state, { configs: action.configs || {} });
    }

    case 'TOGGLE_ITEM': {
      var moduleId = action.moduleId;
      var contentType = action.contentType;
      var itemId = action.itemId;

      var existingModuleConfig = state.configs[moduleId] || {};
      var existingTypeConfig = existingModuleConfig[contentType] || { included_ids: null, overrides: {} };
      var currentIds = existingTypeConfig.included_ids;

      var newIds;
      if (currentIds === null || currentIds === undefined) {
        // null means "all included" — initialize from allItemIds, then remove the toggled item
        var all = action.allItemIds || [];
        newIds = all.filter(function(id) { return id !== itemId; });
      } else if (currentIds.indexOf(itemId) !== -1) {
        newIds = currentIds.filter(function(id) { return id !== itemId; });
      } else {
        newIds = currentIds.concat([itemId]);
      }

      var newTypeConfig = Object.assign({}, existingTypeConfig, { included_ids: newIds });
      var newModuleConfig = Object.assign({}, existingModuleConfig);
      newModuleConfig[contentType] = newTypeConfig;
      var newConfigs = Object.assign({}, state.configs);
      newConfigs[moduleId] = newModuleConfig;
      return Object.assign({}, state, { configs: newConfigs });
    }

    case 'SELECT_ALL': {
      var moduleId = action.moduleId;
      var contentType = action.contentType;
      var itemIds = action.itemIds || [];

      var existingModuleConfig = state.configs[moduleId] || {};
      var existingTypeConfig = existingModuleConfig[contentType] || { overrides: {} };
      var newTypeConfig = Object.assign({}, existingTypeConfig, { included_ids: itemIds.slice() });
      var newModuleConfig = Object.assign({}, existingModuleConfig);
      newModuleConfig[contentType] = newTypeConfig;
      var newConfigs = Object.assign({}, state.configs);
      newConfigs[moduleId] = newModuleConfig;
      return Object.assign({}, state, { configs: newConfigs });
    }

    case 'DESELECT_ALL': {
      var moduleId = action.moduleId;
      var contentType = action.contentType;

      var existingModuleConfig = state.configs[moduleId] || {};
      var existingTypeConfig = existingModuleConfig[contentType] || { overrides: {} };
      var newTypeConfig = Object.assign({}, existingTypeConfig, { included_ids: [] });
      var newModuleConfig = Object.assign({}, existingModuleConfig);
      newModuleConfig[contentType] = newTypeConfig;
      var newConfigs = Object.assign({}, state.configs);
      newConfigs[moduleId] = newModuleConfig;
      return Object.assign({}, state, { configs: newConfigs });
    }

    case 'SET_OVERRIDE': {
      var moduleId = action.moduleId;
      var itemId = action.itemId;
      var field = action.field;
      var value = action.value;

      var existingModuleConfig = state.configs[moduleId] || {};
      var existingOverrides = existingModuleConfig.overrides || {};
      var existingItemOverrides = existingOverrides[itemId] || {};
      var newItemOverrides = Object.assign({}, existingItemOverrides);
      newItemOverrides[field] = value;
      var newOverrides = Object.assign({}, existingOverrides);
      newOverrides[itemId] = newItemOverrides;
      var newModuleConfig = Object.assign({}, existingModuleConfig, { overrides: newOverrides });
      var newConfigs = Object.assign({}, state.configs);
      newConfigs[moduleId] = newModuleConfig;
      return Object.assign({}, state, { configs: newConfigs });
    }

    case 'CACHE_I18N': {
      var newI18nCache = Object.assign({}, state.i18nCache);
      newI18nCache[action.key] = action.data;
      return Object.assign({}, state, { i18nCache: newI18nCache });
    }

    case 'SET_I18N_LOADING': {
      var newI18nLoading = Object.assign({}, state.i18nLoading);
      newI18nLoading[action.key] = action.loading;
      return Object.assign({}, state, { i18nLoading: newI18nLoading });
    }

    case 'BACK_TO_GRID':
      return Object.assign({}, state, { selectedModuleId: null });

    default:
      return state;
  }
}

function CurationProvider(props) {
  var ref = React.useReducer(curationReducer, {
    selectedEventId: null,
    selectedModuleId: null,
    language: 'en',
    configs: {},
    i18nCache: {},
    i18nLoading: {}
  });
  var state = ref[0], dispatch = ref[1];
  return React.createElement(CurationContext.Provider, { value: { state: state, dispatch: dispatch } }, props.children);
}

// ── Helper Functions ──────────────────────────────────────────────

function getModuleContentCounts(moduleData) {
  if (!moduleData) return { quiz: 0, tickets: 0, briefs: 0, curveballs: 0, buzzers: 0, total: 0 };

  var quizCount = 0, ticketsCount = 0, briefsCount = 0, curveballsCount = 0, buzzersCount = 0;

  try { var q = moduleData.quiz; quizCount = (q && q.length) ? q.length : 0; } catch(e) {}
  try { var t = moduleData.tickets; ticketsCount = (t && t.length) ? t.length : 0; } catch(e) {}
  try { var b = moduleData.briefs; briefsCount = (b && b.length) ? b.length : 0; } catch(e) {}
  try { var cb = moduleData.curveballs; curveballsCount = (cb && cb.length) ? cb.length : 0; } catch(e) {}
  try { var bz = moduleData.buzzers; buzzersCount = (bz && bz.length) ? bz.length : 0; } catch(e) {}

  var total = quizCount + ticketsCount + briefsCount + curveballsCount + buzzersCount;
  return { quiz: quizCount, tickets: ticketsCount, briefs: briefsCount, curveballs: curveballsCount, buzzers: buzzersCount, total: total };
}

function getContentTypeItems(moduleData, contentType) {
  if (!moduleData) return [];
  try {
    var items = moduleData[contentType];
    return Array.isArray(items) ? items : [];
  } catch(e) {
    return [];
  }
}

function getIncludedIds(configs, moduleId, contentType, allItems) {
  var moduleConfig = configs && configs[moduleId];
  if (!moduleConfig) {
    // No config means all items are included by default
    return allItems ? allItems.map(function(item) { return item.id; }) : [];
  }
  var typeConfig = moduleConfig[contentType];
  if (!typeConfig || typeConfig.included_ids === null || typeConfig.included_ids === undefined) {
    // null / undefined means all included
    return allItems ? allItems.map(function(item) { return item.id; }) : [];
  }
  return typeConfig.included_ids;
}

function getModuleEnabledCount(moduleData, configs, moduleId) {
  var enabledCount = 0;
  CONTENT_TABS.forEach(function(tab) {
    var typeItems = getContentTypeItems(moduleData, tab.key);
    enabledCount += getIncludedIds(configs, moduleId, tab.key, typeItems).length;
  });
  return enabledCount;
}

function hasAnyI18nLoading(i18nLoading) {
  var key;
  if (!i18nLoading) return false;
  for (key in i18nLoading) {
    if (Object.prototype.hasOwnProperty.call(i18nLoading, key) && i18nLoading[key]) {
      return true;
    }
  }
  return false;
}

function clibTranslate(text, moduleId, lang, i18nCache) {
  if (!text || typeof text !== 'string') return text;
  if (lang === 'en' || !lang) return text; // English is the source language
  var langSuffix = lang === 'es' ? 'es' : 'pt';
  var cacheKey = moduleId + '-' + langSuffix;
  var dict = i18nCache[cacheKey];
  if (!dict) return text; // Translation not loaded yet
  return dict[text] || text; // Translate or fallback to English
}

// ── Constants ─────────────────────────────────────────────────────

var QTYPE_LABELS = {
  single_select: 'Single Select',
  multi_select: 'Multi Select',
  true_false: 'True/False',
  cascade: 'Cascade',
  drag_match: 'Drag & Match',
  group_sort: 'Group Sort',
  rank_order: 'Rank Order',
  hotspot: 'Hotspot',
  numeric_slider: 'Slider',
  free_text: 'Free Text',
  structured_form: 'Form',
  text: 'Text',
  buzzer: 'Buzzer'
};

var CONTENT_TABS = [
  { key: 'quiz', label: 'Questions', icon: '❓' },
  { key: 'tickets', label: 'Tickets', icon: '🎫' },
  { key: 'briefs', label: 'Briefs', icon: '📋' },
  { key: 'curveballs', label: 'Curveballs', icon: '🎱' },
  { key: 'buzzers', label: 'Buzzers', icon: '🔔' }
];

var DIFFICULTY_ORDER = { easy: 0, medium: 1, hard: 2 };

function getItemSummary(item, contentType) {
  switch (contentType) {
    case 'tickets':
      return {
        label: item.title || '(untitled ticket)',
        category: '—',
        difficulty: '—',
        points: '—',
        timer: '—',
        qtype: 'ticket',
        qtypeLabel: 'Ticket',
        audiences: item.audiences || []
      };
    case 'briefs':
      return {
        label: (item.client || '?') + ' — ' + (item.industry || '?'),
        category: item.industry || '—',
        difficulty: '—',
        points: '—',
        timer: '—',
        qtype: 'brief',
        qtypeLabel: 'Brief',
        audiences: []
      };
    case 'curveballs':
      return {
        label: item.text || '(no text)',
        category: '—',
        difficulty: '—',
        points: '—',
        timer: '—',
        qtype: 'curveball',
        qtypeLabel: 'Curveball',
        audiences: []
      };
    case 'buzzers':
      var bPts = item.points;
      var bPtsStr = '—';
      if (bPts && typeof bPts === 'object') { bPtsStr = (bPts.first || 0) + '/' + (bPts.second || 0) + '/' + (bPts.third || 0); }
      else if (typeof bPts === 'number') { bPtsStr = bPts; }
      return {
        label: item.text || '(no text)',
        category: '—',
        difficulty: '—',
        points: bPtsStr,
        timer: '—',
        qtype: item.type || 'buzzer',
        qtypeLabel: 'Buzzer',
        audiences: []
      };
    default: // quiz
      return {
        label: item.prompt || '—',
        category: item.category || '—',
        difficulty: item.difficulty || '—',
        points: item.points || 0,
        timer: (item.timeSec || 0) + 's',
        qtype: item.type || 'text',
        qtypeLabel: QTYPE_LABELS[item.type] || item.type || 'Text',
        audiences: item.audiences || []
      };
  }
}

function filterContentItems(items, filters) {
  if (!items || !items.length) return [];

  var search = filters.search ? filters.search.toLowerCase().trim() : '';
  var category = filters.category || '';
  var qtype = filters.qtype || '';
  var difficulty = filters.difficulty || '';
  var audience = filters.audience || '';
  var showExcluded = filters.showExcluded !== false; // default true
  var includedIds = filters.includedIds || null;

  return items.filter(function(item) {
    // showExcluded filter
    if (!showExcluded && includedIds !== null) {
      if (includedIds.indexOf(item.id) === -1) return false;
    }

    // search filter
    if (search) {
      var prompt = (item.prompt || item.title || item.text || item.client || '').toLowerCase();
      var id = (item.id || '').toLowerCase();
      if (prompt.indexOf(search) === -1 && id.indexOf(search) === -1) return false;
    }

    // category filter — skip if item has no category field
    if (category) {
      if (item.category === undefined) { /* pass through */ }
      else if (item.category !== category) return false;
    }

    // qtype filter — skip if item has no type field
    if (qtype) {
      if (item.type === undefined) { /* pass through */ }
      else if (item.type !== qtype) return false;
    }

    // difficulty filter — skip if item has no difficulty field
    if (difficulty) {
      if (item.difficulty === undefined) { /* pass through */ }
      else if (item.difficulty !== difficulty) return false;
    }

    // audience filter
    if (audience) {
      var audiences = item.audiences || [];
      if (audiences.indexOf(audience) === -1) return false;
    }

    return true;
  });
}

// ── ModuleCard (View 1) ───────────────────────────────────────────

function ModuleCard(props) {
  var module = props.module;
  var counts = props.counts;
  var enabledCount = props.enabledCount;
  var onClick = props.onClick;

  return (
    <div className="mod-card" onClick={onClick}>
      <div className="mc-hd">
        <div className="mc-icon" style={{ background: module.color }}>
          {module.icon}
        </div>
        <div className="mc-info">
          <div className="mc-name">{module.name}</div>
          <div className="mc-full">{module.fullName}</div>
        </div>
        <div className="mc-enabled">{enabledCount} / {counts.total} enabled</div>
      </div>
      <div className="mc-stats">
        <div className="mc-stat">
          <span className="mc-sv">{counts.quiz}</span>
          <span className="mc-sl">Questions</span>
        </div>
        <div className="mc-stat">
          <span className="mc-sv">{counts.tickets}</span>
          <span className="mc-sl">Tickets</span>
        </div>
        <div className="mc-stat">
          <span className="mc-sv">{counts.briefs}</span>
          <span className="mc-sl">Briefs</span>
        </div>
        <div className="mc-stat">
          <span className="mc-sv">{counts.curveballs}</span>
          <span className="mc-sl">Curveballs</span>
        </div>
        <div className="mc-stat">
          <span className="mc-sv">{counts.buzzers}</span>
          <span className="mc-sl">Buzzers</span>
        </div>
        <div className="mc-stat">
          <span className="mc-sv" style={{ color: module.color }}>{counts.total}</span>
          <span className="mc-sl">Total</span>
        </div>
      </div>
      <div className="mc-bar" style={{ background: module.color }}></div>
    </div>
  );
}

// ── ModuleOverviewGrid (View 1) ───────────────────────────────────

function ModuleOverviewGrid(props) {
  var onSelectModule = props.onSelectModule;
  var configs = props.configs;

  var moduleKeys = (typeof GAME_MODULES !== 'undefined' && GAME_MODULES) ? Object.keys(GAME_MODULES) : [];

  if (!moduleKeys.length) {
    return (
      <div>
        <div className="pghd">
          <div>
            <div className="eyebrow">Arena</div>
            <div className="title">Content <em>Library</em></div>
            <div className="sub">Browse and curate game content across all modules. Select a module to explore its questions, tickets, briefs, curveballs, and buzzers.</div>
          </div>
        </div>
        <div className="mod-grid-empty">
          <p>No modules loaded. Ensure GAME_MODULES is available.</p>
        </div>
      </div>
    );
  }

  return (
    <div>
      <div className="pghd">
        <div>
          <div className="eyebrow">Arena</div>
          <div className="title">Content <em>Library</em></div>
          <div className="sub">Browse and curate game content across all modules. Select a module to explore its questions, tickets, briefs, curveballs, and buzzers.</div>
        </div>
      </div>
      <div className="mod-grid">
        {moduleKeys.map(function(key) {
          var mod = GAME_MODULES[key];
          if (!mod) return null;
          var counts = getModuleContentCounts(mod.data);
          var enabledCount = getModuleEnabledCount(mod.data, configs, mod.id);

          return (
            <ModuleCard
              key={mod.id}
              module={mod}
              counts={counts}
              enabledCount={enabledCount}
              onClick={function() { onSelectModule(mod.id); }}
            />
          );
        })}
      </div>
    </div>
  );
}

// ── EventContextBar (View 2 toolbar) ─────────────────────────────

function EventContextBar(props) {
  var module = props.module;
  var events = props.events || [];
  var state = props.state;
  var dispatch = props.dispatch;
  var enabledCount = props.enabledCount;
  var totalCount = props.totalCount;
  var wizardContext = props.wizardContext;
  var onDone = props.onDone;
  var translationsLoading = hasAnyI18nLoading(state && state.i18nLoading);
  var isWizardMode = !!wizardContext;

  return (
    <div className={"ctxbar" + (isWizardMode ? " ctxbar--wizard" : "")}>
      {isWizardMode ? (
        <React.Fragment>
          <button className="ctx-back btn ghost" onClick={onDone}>← Back to wizard</button>
          <div className="ctx-curation-label">
            <span className="ctx-curation-dot"></span>
            Curation mode
          </div>
          <div className="ctx-mod">
            <span style={{ marginRight: 6 }}>{module.icon}</span>
            {module.name}
          </div>
          <div className="ctx-sep"></div>
          <div className="ctx-evt-locked">
            {wizardContext.eventName || 'Event'}
          </div>
        </React.Fragment>
      ) : (
        <React.Fragment>
          <button className="ctx-back btn ghost" onClick={function() { dispatch({ type: 'BACK_TO_GRID' }); }}>← Back</button>
          <div className="ctx-mod">
            <span style={{ marginRight: 6 }}>{module.icon}</span>
            {module.name}
          </div>
          <div className="ctx-sep"></div>
          <select
            className="ctx-evt"
            value={state.selectedEventId || ''}
            onChange={function(e) { dispatch({ type: 'SELECT_EVENT', eventId: e.target.value || null }); }}
          >
            <option value="">No event (global view)</option>
            {events.map(function(ev) {
              return <option key={ev.id} value={ev.id}>{ev.name || ev.title}</option>;
            })}
          </select>
        </React.Fragment>
      )}
      <div className="ctx-sep"></div>
      <div className="ctx-lang">
        {['en', 'es', 'pt'].map(function(lang) {
          return (
            <label key={lang}>
              <input type="radio" name="clib-lang" value={lang} checked={state.language === lang}
                onChange={function() { dispatch({ type: 'SET_LANGUAGE', language: lang }); }} />
              <span>{lang.toUpperCase()}</span>
            </label>
          );
        })}
      </div>
      {translationsLoading && (
        <div className="ctx-i18n-loading" aria-live="polite">
          <span className="ctx-i18n-dot"></span>
          <span>Loading translations…</span>
        </div>
      )}
      <div className="ctx-count">
        <span style={{ color: 'var(--brand)', fontWeight: 600 }}>{enabledCount}</span>
        <span style={{ color: 'var(--i4)' }}>{' / ' + totalCount}</span>
        <span style={{ color: 'var(--i4)', marginLeft: 4 }}>enabled</span>
      </div>
      {isWizardMode && (
        <button className="btn pr ctx-done" onClick={onDone}>Done</button>
      )}
    </div>
  );
}

// ── ContentTabs ───────────────────────────────────────────────────

function ContentTabs(props) {
  var activeTab = props.activeTab;
  var counts = props.counts || {};
  var onTabChange = props.onTabChange;

  return (
    <div className="ctabs">
      {CONTENT_TABS.map(function(tab) {
        return (
          <button
            key={tab.key}
            className={activeTab === tab.key ? 'on' : ''}
            onClick={function() { onTabChange(tab.key); }}
          >
            {tab.icon} {tab.label}
            <span className="tab-ct">{counts[tab.key] || 0}</span>
          </button>
        );
      })}
    </div>
  );
}

// ── FilterRail ────────────────────────────────────────────────────

function FilterRail(props) {
  var filters = props.filters || {};
  var onFilterChange = props.onFilterChange;
  var categories = props.categories || [];
  var showExcluded = props.showExcluded;
  var onToggleExcluded = props.onToggleExcluded;
  var onSelectAll = props.onSelectAll;
  var onDeselectAll = props.onDeselectAll;
  var activeTab = props.activeTab;

  function handleChange(field) {
    return function(e) {
      onFilterChange(field, e.target.value);
    };
  }

  return (
    <div className="frail">
      <input
        placeholder="Search…"
        value={filters.search || ''}
        onChange={handleChange('search')}
      />
      {activeTab === 'quiz' && (
        <React.Fragment>
          <select value={filters.category || ''} onChange={handleChange('category')}>
            <option value="">All categories</option>
            {categories.map(function(cat) {
              return <option key={cat} value={cat}>{cat}</option>;
            })}
          </select>
          <select value={filters.qtype || ''} onChange={handleChange('qtype')}>
            <option value="">All types</option>
            {Object.keys(QTYPE_LABELS).map(function(key) {
              return <option key={key} value={key}>{QTYPE_LABELS[key]}</option>;
            })}
          </select>
          <select value={filters.difficulty || ''} onChange={handleChange('difficulty')}>
            <option value="">All difficulties</option>
            <option value="easy">Easy</option>
            <option value="medium">Medium</option>
            <option value="hard">Hard</option>
          </select>
          <select value={filters.audience || ''} onChange={handleChange('audience')}>
            <option value="">All audiences</option>
            <option value="sales">Sales</option>
            <option value="presales">Presales</option>
            <option value="deployment">Deployment</option>
          </select>
        </React.Fragment>
      )}
      <label className="fr-toggle">
        <input
          type="checkbox"
          checked={!!showExcluded}
          onChange={onToggleExcluded}
        />
        Show excluded
      </label>
      <div className="fr-acts">
        <button className="btn ghost" onClick={onSelectAll}>Select all</button>
        <button className="btn ghost" onClick={onDeselectAll}>Clear all</button>
      </div>
    </div>
  );
}

// --- END PART 1 --- (Part 2 continues with QuestionRow, ContentList, ModuleContentExplorer, and main page wrapper)
// --- PART 2: QuestionRow, ContentList, ModuleContentExplorer, OrgContentLibraryPage ---

// Safe render helper — prevents React error #31 when rendering object fields
function safeRender(val) {
  if (val === null || val === undefined) return '—';
  if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean') return String(val);
  if (Array.isArray(val)) return val.map(function(v) { return safeRender(v); }).join(', ');
  if (typeof val === 'object') return JSON.stringify(val, null, 2);
  return String(val);
}

function compactInlineText(val, maxLen) {
  var text = safeRender(val);
  var limit = maxLen || 140;
  text = String(text).replace(/\s+/g, ' ').trim();
  if (!text) return '—';
  if (text.length > limit) return text.slice(0, limit - 1) + '…';
  return text;
}

// ---------------------------------------------------------------------------
// TranslationBadge
// ---------------------------------------------------------------------------
function TranslationBadge(props) {
  var itemId = props.itemId;
  var i18nCache = props.i18nCache || {};
  var moduleId = props.moduleId;

  var esLoaded = !!(i18nCache['es'] && i18nCache['es'][moduleId]);
  var ptLoaded = !!(i18nCache['pt'] && i18nCache['pt'][moduleId]);

  return (
    <div className="ir-trans">
      <span className="tr-dot" title="EN" style={{background:'var(--ok)'}}></span>
      <span className={"tr-dot" + (esLoaded ? '' : ' missing')} title="ES"></span>
      <span className={"tr-dot" + (ptLoaded ? '' : ' missing')} title="PT"></span>
    </div>
  );
}

// ---------------------------------------------------------------------------
// QtypePreview — interactive QType renderer preview (proper component for hooks)
// ---------------------------------------------------------------------------
function QtypePreview(props) {
  var item = props.item;
  var tr = props.tr || function(t) { return t; };

  var renderer = window.RENDERERS && window.RENDERERS[item.type];
  if (!renderer || !renderer.Component) return null;

  var Comp = renderer.Component;
  var defaultVal = renderer.getDefaultValue ? renderer.getDefaultValue(item.spec) : null;

  var _v = React.useState(defaultVal);
  var previewVal = _v[0]; var setPreviewVal = _v[1];
  var _l = React.useState(false);
  var locked = _l[0]; var setLocked = _l[1];
  var _g = React.useState(false);
  var graded = _g[0]; var setGraded = _g[1];

  function handleLockIn() { setLocked(true); setGraded(true); }
  function handleReset() { setPreviewVal(defaultVal); setLocked(false); setGraded(false); }

  return (
    <div className="det-section" style={{marginTop:12}}>
      <div className="det-label" style={{marginBottom:8}}>Player Preview</div>
      <div className="qtr" data-theme="cisco" data-mode="dark" style={{background:'var(--bg-elev)', borderRadius:'var(--r-lg)', padding:16, border:'1px solid var(--line)'}}>
        <div className="tc-q">{tr(item.prompt || '')}</div>
        <Comp spec={item.spec} value={previewVal} onChange={setPreviewVal} locked={locked} graded={graded} />
        <div style={{marginTop:12, display:'flex', gap:8, justifyContent:'flex-end'}}>
          {!locked && <button className="btn ghost" onClick={handleLockIn} style={{fontSize:11, padding:'4px 12px'}}>Lock in</button>}
          {locked && <button className="btn ghost" onClick={handleReset} style={{fontSize:11, padding:'4px 12px'}}>Reset</button>}
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// renderAnswerSection — QType-specific answer rendering
// ---------------------------------------------------------------------------
function renderAnswerSection(item, tr) {
  var spec = item.spec || {};
  if (!tr) { tr = function(t) { return t; }; } // fallback passthrough

  switch (item.type) {
    case 'single_select':
    case 'multi_select': {
      var correctSet = Array.isArray(spec.correct) ? spec.correct : [spec.correct];
      return (
        <div className="det-section">
          <div className="det-label">Options</div>
          <div className="det-opts">
            {(spec.options || []).map(function(opt) {
              var isCorrect = correctSet.indexOf(opt.id) >= 0;
              return (
                <div key={opt.id} className={"det-opt" + (isCorrect ? " correct" : "")}>
                  <span className="opt-id">{opt.id}</span>
                  <span>{tr(opt.label)}</span>
                  {isCorrect && <span style={{marginLeft:'auto',color:'var(--ok)',fontFamily:'var(--f-m)',fontSize:'10px'}}>✓ CORRECT</span>}
                </div>
              );
            })}
          </div>
        </div>
      );
    }

    case 'true_false':
      return (
        <div className="det-section">
          <div className="det-label">Answer</div>
          <div className="det-opts">
            <div className={"det-opt" + (spec.correct === true || spec.correct === 'true' ? " correct" : "")}>
              <span className="opt-id">T</span><span>True</span>
              {(spec.correct === true || spec.correct === 'true') && <span style={{marginLeft:'auto',color:'var(--ok)',fontFamily:'var(--f-m)',fontSize:'10px'}}>✓</span>}
            </div>
            <div className={"det-opt" + (spec.correct === false || spec.correct === 'false' ? " correct" : "")}>
              <span className="opt-id">F</span><span>False</span>
              {(spec.correct === false || spec.correct === 'false') && <span style={{marginLeft:'auto',color:'var(--ok)',fontFamily:'var(--f-m)',fontSize:'10px'}}>✓</span>}
            </div>
          </div>
        </div>
      );

    case 'cascade':
      return (
        <div className="det-section">
          <div className="det-label">Cascade Stages</div>
          {(spec.stages || []).map(function(stage, i) {
            return (
              <div key={i} style={{marginBottom:8}}>
                <div style={{fontSize:11, color:'var(--i3)', fontFamily:'var(--f-m)', marginBottom:4}}>Stage {i+1}: {tr(stage.prompt || '')}</div>
                <div className="det-opts">
                  {(stage.options || []).map(function(opt) {
                    var isCorrect = stage.correct === opt.id;
                    return (
                      <div key={opt.id} className={"det-opt" + (isCorrect ? " correct" : "")}>
                        <span className="opt-id">{opt.id}</span>
                        <span>{tr(opt.label)}</span>
                        {isCorrect && <span style={{marginLeft:'auto',color:'var(--ok)',fontFamily:'var(--f-m)',fontSize:'10px'}}>✓</span>}
                      </div>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      );

    case 'drag_match':
      return (
        <div className="det-section">
          <div className="det-label">Matching Pairs</div>
          <div className="det-opts">
            {(spec.pairs || []).map(function(pair, i) {
              return (
                <div key={i} className="det-opt correct">
                  <span style={{fontWeight:600}}>{tr(pair.left)}</span>
                  <span style={{color:'var(--i4)', margin:'0 8px'}}>→</span>
                  <span>{tr(pair.right)}</span>
                </div>
              );
            })}
          </div>
        </div>
      );

    case 'group_sort':
      return (
        <div className="det-section">
          <div className="det-label">Groups</div>
          {(spec.groups || []).map(function(group, i) {
            return (
              <div key={i} style={{marginBottom:8}}>
                <div style={{fontSize:12, fontWeight:600, color:'var(--i1)', marginBottom:4}}>{tr(group.name)}</div>
                <div className="det-opts">
                  {(group.items || []).map(function(groupItem, j) {
                    return <div key={j} className="det-opt correct"><span>{tr(groupItem)}</span></div>;
                  })}
                </div>
              </div>
            );
          })}
        </div>
      );

    case 'rank_order':
      return (
        <div className="det-section">
          <div className="det-label">Correct Order</div>
          <div className="det-opts">
            {(spec.correct_order || []).map(function(rankItem, i) {
              return (
                <div key={i} className="det-opt correct">
                  <span className="opt-id" style={{fontWeight:700}}>{i+1}</span>
                  <span>{tr(typeof rankItem === 'string' ? rankItem : rankItem.label || rankItem.id)}</span>
                </div>
              );
            })}
          </div>
        </div>
      );

    case 'hotspot':
      return (
        <div className="det-section">
          <div className="det-label">Hotspot</div>
          <div style={{fontSize:12, color:'var(--i2)'}}>
            {spec.imageUrl && <div style={{marginBottom:4}}>Image: {spec.imageUrl}</div>}
            {(spec.regions || spec.hotspots || []).map(function(r, i) {
              return <div key={i} className="det-opt correct"><span>{tr(r.label || r.description || JSON.stringify(r))}</span></div>;
            })}
          </div>
        </div>
      );

    case 'numeric_slider':
      return (
        <div className="det-section">
          <div className="det-label">Slider</div>
          <div className="det-opts">
            <div className="det-opt correct">
              <span>Range: {spec.min} – {spec.max} {spec.unit || ''}</span>
            </div>
            <div className="det-opt correct">
              <span>Correct: {spec.correct} {spec.unit || ''} (±{spec.tolerance || 0})</span>
            </div>
          </div>
        </div>
      );

    case 'free_text':
      return (
        <div className="det-section">
          <div className="det-label">Expected Answer</div>
          <div className="det-expl">{tr(spec.sampleAnswer || spec.sample_answer || (spec.keywords || []).join(', ') || '(open-ended)')}</div>
        </div>
      );

    case 'structured_form':
      return (
        <div className="det-section">
          <div className="det-label">Form Fields</div>
          <div className="det-opts">
            {(spec.fields || []).map(function(f, i) {
              return (
                <div key={i} className="det-opt">
                  <span className="opt-id" style={{minWidth:120}}>{tr(f.label || f.name)}</span>
                  <span style={{color:'var(--i3)'}}>{f.type || 'text'}</span>
                  {f.correct && <span style={{marginLeft:'auto', color:'var(--ok)'}}>{tr(f.correct)}</span>}
                </div>
              );
            })}
          </div>
        </div>
      );

    case 'buzzer':
      return (
        <div className="det-section">
          <div className="det-label">Buzzer</div>
          <div style={{marginBottom:8}}>
            <div style={{fontSize:12, fontWeight:600, color:'var(--i1)', marginBottom:4}}>Question: {tr(spec.question || item.prompt)}</div>
          </div>
          {spec.hints && spec.hints.length > 0 && (
            <div style={{marginBottom:8}}>
              <div style={{fontSize:11, color:'var(--i3)', fontFamily:'var(--f-m)', marginBottom:4}}>HINTS</div>
              <div className="det-opts">
                {spec.hints.map(function(h, i) {
                  return <div key={i} className="det-opt"><span>Hint {i+1}: {tr(typeof h === 'string' ? h : h.text)}</span></div>;
                })}
              </div>
            </div>
          )}
          <div style={{marginBottom:8}}>
            <div style={{fontSize:11, color:'var(--i3)', fontFamily:'var(--f-m)', marginBottom:4}}>ANSWER</div>
            <div className="det-expl">{tr(typeof spec.answer === 'string' ? spec.answer : (spec.answer || []).join(', '))}</div>
          </div>
          {spec.judgingNotes && (
            <div>
              <div style={{fontSize:11, color:'var(--i3)', fontFamily:'var(--f-m)', marginBottom:4}}>JUDGING NOTES</div>
              <div className="det-expl">{tr(spec.judgingNotes)}</div>
            </div>
          )}
        </div>
      );

    default:
      // text type (tickets, briefs, curveballs)
      return (
        <div className="det-section">
          {spec.scenario && (
            <div style={{marginBottom:8}}>
              <div className="det-label">Scenario</div>
              <div style={{fontSize:12, color:'var(--i2)', lineHeight:1.5}}>{tr(spec.scenario)}</div>
            </div>
          )}
          {spec.tasks && spec.tasks.length > 0 && (
            <div style={{marginBottom:8}}>
              <div className="det-label">Tasks</div>
              <div className="det-opts">
                {spec.tasks.map(function(t, i) {
                  return <div key={i} className="det-opt"><span>{i+1}. {tr(typeof t === 'string' ? t : t.description || JSON.stringify(t))}</span></div>;
                })}
              </div>
            </div>
          )}
          {spec.rubric && (
            <div>
              <div className="det-label">Rubric</div>
              <div className="det-expl">{tr(typeof spec.rubric === 'string' ? spec.rubric : JSON.stringify(spec.rubric, null, 2))}</div>
            </div>
          )}
        </div>
      );
  }
}

// ---------------------------------------------------------------------------
// QuestionRowDetail — expanded detail panel
// ---------------------------------------------------------------------------
function QuestionRowDetail(props) {
  var item = props.item;
  var catColor = props.catColor;
  var moduleId = props.moduleId;
  var contentType = props.contentType || 'quiz';
  var spec = item.spec || {};

  var tCtx = React.useContext(CurationContext);
  var tLang = tCtx ? tCtx.state.language : 'en';
  var tCache = tCtx ? tCtx.state.i18nCache : {};
  function tr(text) { return clibTranslate(text, moduleId, tLang, tCache); }

  var fullPrompt = tr(item.prompt || item.title || item.text || (item.client ? item.client + ' — ' + (item.industry || '') : '') || (spec.scenario) || (spec.question) || '—');

  return (
    <div className="irow-det">
      <div className="det-prompt">{fullPrompt}</div>

      {contentType === 'quiz' && renderAnswerSection(item, tr)}

      {contentType === 'quiz' && <QtypePreview item={item} tr={tr} />}

      {contentType === 'tickets' && (
        <div className="det-section">
          {item.scenario && <div><div className="det-label">Scenario</div><div className="det-expl">{typeof item.scenario === 'string' ? tr(item.scenario) : safeRender(item.scenario)}</div></div>}
          {item.cliOutput && <div style={{marginTop:8}}><div className="det-label">CLI Output</div><pre style={{fontSize:11, color:'var(--i2)', fontFamily:'var(--f-m)', whiteSpace:'pre-wrap', background:'var(--s1)', padding:8, borderRadius:4}}>{safeRender(item.cliOutput)}</pre></div>}
          {item.symptoms && item.symptoms.length > 0 && <div style={{marginTop:8}}><div className="det-label">Symptoms</div><div className="det-opts">{item.symptoms.map(function(s,i){return <div key={i} className="det-opt"><span>{typeof s === 'string' ? tr(s) : safeRender(s)}</span></div>;})}</div></div>}
          {item.solution && <div style={{marginTop:8}}><div className="det-label">Solution</div><div className="det-expl">{typeof item.solution === 'string' ? tr(item.solution) : safeRender(item.solution)}</div></div>}
          {item.licensingAngle && <div style={{marginTop:8}}><div className="det-label">Licensing Angle</div><div className="det-expl">{typeof item.licensingAngle === 'string' ? tr(item.licensingAngle) : safeRender(item.licensingAngle)}</div></div>}
        </div>
      )}

      {contentType === 'briefs' && (
        <div className="det-section">
          <div style={{display:'flex', gap:16, flexWrap:'wrap', marginBottom:8}}>
            {item.employees && <span style={{fontSize:11, color:'var(--i3)'}}>👥 {safeRender(item.employees)} employees</span>}
            {item.sites && <span style={{fontSize:11, color:'var(--i3)'}}>🏢 {safeRender(item.sites)} sites</span>}
            {item.endpoints && <span style={{fontSize:11, color:'var(--i3)'}}>💻 {safeRender(item.endpoints)} endpoints</span>}
            {item.budget && <span style={{fontSize:11, color:'var(--i3)'}}>💰 {safeRender(item.budget)}</span>}
          </div>
          {item.context && <div><div className="det-label">Context</div><div className="det-expl">{typeof item.context === 'string' ? tr(item.context) : safeRender(item.context)}</div></div>}
          {item.painPoints && item.painPoints.length > 0 && <div style={{marginTop:8}}><div className="det-label">Pain Points</div><div className="det-opts">{item.painPoints.map(function(p,i){return <div key={i} className="det-opt"><span>{typeof p === 'string' ? tr(p) : safeRender(p)}</span></div>;})}</div></div>}
          {item.constraints && item.constraints.length > 0 && <div style={{marginTop:8}}><div className="det-label">Constraints</div><div className="det-opts">{item.constraints.map(function(c,i){return <div key={i} className="det-opt"><span>{typeof c === 'string' ? tr(c) : safeRender(c)}</span></div>;})}</div></div>}
          {item.trickRequirement && <div style={{marginTop:8}}><div className="det-label">Trick Requirement</div><div className="det-expl">{typeof item.trickRequirement === 'string' ? tr(item.trickRequirement) : safeRender(item.trickRequirement)}</div></div>}
        </div>
      )}

      {contentType === 'curveballs' && (
        <div className="det-section">
          {item.context && <div><div className="det-label">Context</div><div className="det-expl">{typeof item.context === 'string' ? tr(item.context) : safeRender(item.context)}</div></div>}
          {item.strongResponse && <div style={{marginTop:8}}><div className="det-label">Strong Response</div><div className="det-expl" style={{color:'var(--ok)'}}>{typeof item.strongResponse === 'string' ? tr(item.strongResponse) : safeRender(item.strongResponse)}</div></div>}
          {item.weakResponse && <div style={{marginTop:8}}><div className="det-label">Weak Response</div><div className="det-expl" style={{color:'var(--dn)'}}>{typeof item.weakResponse === 'string' ? tr(item.weakResponse) : safeRender(item.weakResponse)}</div></div>}
          {item.proctorGuide && <div style={{marginTop:8}}><div className="det-label">Proctor Guide</div><pre className="det-expl" style={{fontSize:11, fontFamily:'var(--f-m)', whiteSpace:'pre-wrap'}}>{safeRender(item.proctorGuide)}</pre></div>}
        </div>
      )}

      {contentType === 'buzzers' && (
        <div className="det-section">
          {item.answer && <div><div className="det-label">Answer</div><div className="det-expl" style={{color:'var(--ok)'}}>{typeof item.answer === 'string' ? tr(item.answer) : JSON.stringify(item.answer)}</div></div>}
          {item.points && typeof item.points === 'object' && <div style={{marginTop:8}}><div className="det-label">Points</div><div className="det-expl">🥇 {item.points.first || 0} · 🥈 {item.points.second || 0} · 🥉 {item.points.third || 0}</div></div>}
          {item.proctorGuide && <div style={{marginTop:8}}><div className="det-label">Proctor Guide</div><div className="det-expl">{typeof item.proctorGuide === 'string' ? tr(item.proctorGuide) : (item.proctorGuide.expectedAnswer ? tr(item.proctorGuide.expectedAnswer) : JSON.stringify(item.proctorGuide))}</div></div>}
        </div>
      )}

      {contentType === 'buzzers' && window.RENDERERS && window.RENDERERS.buzzer && (
        <QtypePreview item={Object.assign({}, item, { type: 'buzzer', spec: item.spec || { demoStandings: [] } })} tr={tr} />
      )}

      {contentType === 'quiz' && spec.explanation && (
        <div className="det-section">
          <div className="det-label">Explanation</div>
          <div className="det-expl">{tr(spec.explanation)}</div>
        </div>
      )}

      <div className="det-meta">
        <span>ID: {item.id}</span>
        <span>Source: {item.source || '—'}</span>
        <span>Tag: {item.tag || '—'}</span>
        <span>Phase: {item.phase || '—'}</span>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// QuestionRow — summary + expandable detail
// ---------------------------------------------------------------------------
function QuestionRow(props) {
  var item = props.item;
  var isIncluded = props.isIncluded;
  var onToggle = props.onToggle;
  var i18nCache = props.i18nCache;
  var moduleId = props.moduleId;
  var moduleColor = props.moduleColor;
  var categories = props.categories;

  var expandRef = React.useState(false);
  var expanded = expandRef[0];
  var setExpanded = expandRef[1];

  var tCtx = React.useContext(CurationContext);
  var tLang = tCtx ? tCtx.state.language : 'en';
  var tCache = tCtx ? tCtx.state.i18nCache : {};
  function tr(text) { return clibTranslate(text, moduleId, tLang, tCache); }

  var spec = item.spec || {};
  var contentType = props.contentType || 'quiz';
  var summary = getItemSummary(item, contentType);
  var qtype = summary.qtype;
  var qtypeLabel = summary.qtypeLabel;
  var difficulty = summary.difficulty;
  var category = summary.category;
  var prompt = summary.label;
  var audiences = summary.audiences;
  var points = summary.points;
  var timer = summary.timer;
  var phase = item.phase || '—';
  var tag = item.tag || '—';
  var rowClass = 'quiz-row';

  var catColor = 'var(--i4)';
  if (categories && categories[category]) {
    catColor = categories[category];
  }

  if (contentType === 'tickets') rowClass = 'ticket-row';
  else if (contentType === 'briefs') rowClass = 'brief-row';
  else if (contentType === 'curveballs') rowClass = 'curveball-row';
  else if (contentType === 'buzzers') rowClass = 'buzzer-row';

  function handleToggleClick(e) {
    e.stopPropagation();
    onToggle(item.id);
  }

  function handleExpandClick(e) {
    e.stopPropagation();
    setExpanded(!expanded);
  }

  function renderSummaryColumns() {
    if (contentType === 'tickets') {
      var ticketText = item.title || item.scenario || prompt;
      return (
        <React.Fragment>
          <span className="qt-pill qt-ticket">🎫 Ticket</span>
          <span className="ir-prompt ir-prompt-rich">{compactInlineText(typeof ticketText === 'string' ? tr(ticketText) : safeRender(ticketText), 140)}</span>
          <div className="ir-auds">
            {audiences.map(function(a) {
              return <span key={a} className="ir-aud">{a}</span>;
            })}
          </div>
          <span className="ir-meta-cell">{tr(safeRender(phase))}</span>
          <span className="ir-meta-cell">{tr(safeRender(tag))}</span>
        </React.Fragment>
      );
    }

    if (contentType === 'briefs') {
      var briefText = (item.client || '?') + ' — ' + (item.industry || '?');
      return (
        <React.Fragment>
          <span className="qt-pill qt-brief">📋 Brief</span>
          <span className="ir-prompt ir-prompt-rich">{compactInlineText(tr(briefText), 140)}</span>
          <span className="ir-meta-cell">{tr(safeRender(item.budget || '—'))}</span>
          <span className="ir-meta-cell">{tr(safeRender(phase))}</span>
          <span className="ir-meta-cell">{tr(safeRender(tag))}</span>
        </React.Fragment>
      );
    }

    if (contentType === 'curveballs') {
      var curveballText = item.text || prompt;
      return (
        <React.Fragment>
          <span className="qt-pill qt-curveball">🎱 Curveball</span>
          <span className="ir-prompt ir-prompt-rich">{compactInlineText(typeof curveballText === 'string' ? tr(curveballText) : safeRender(curveballText), 180)}</span>
          <span className="ir-meta-cell">{tr(safeRender(phase))}</span>
          <span className="ir-meta-cell">{tr(safeRender(tag))}</span>
        </React.Fragment>
      );
    }

    if (contentType === 'buzzers') {
      var buzzerText = item.text || prompt;
      return (
        <React.Fragment>
          <span className="qt-pill qt-buzzer">🔔 Buzzer</span>
          <span className="ir-prompt ir-prompt-rich">{compactInlineText(typeof buzzerText === 'string' ? tr(buzzerText) : safeRender(buzzerText), 180)}</span>
          <span className="ir-pts">{points}</span>
          <span className="ir-meta-cell">{tr(safeRender(item.type || 'buzzer'))}</span>
          <span className="ir-meta-cell">{tr(safeRender(tag))}</span>
        </React.Fragment>
      );
    }

    return (
      <React.Fragment>
        <span className={"qt-pill qt-" + qtype} data-col="qtype">{qtypeLabel}</span>
        <span className={"diff-pill diff-" + difficulty} data-col="diff">{difficulty}</span>
        <span className="ir-cat" data-col="cat">
          <span className="cat-dot" style={{background: catColor}}></span>
          {tr(category)}
        </span>
        <span className="ir-prompt" data-col="prompt">{tr(prompt)}</span>
        <div className="ir-auds" data-col="audiences">
          {audiences.map(function(a) {
            return <span key={a} className="ir-aud">{a}</span>;
          })}
        </div>
        <div data-col="trans"><TranslationBadge itemId={item.id} i18nCache={i18nCache} moduleId={moduleId} /></div>
        <span className="ir-pts" data-col="pts">{points}</span>
        <span className="ir-time" data-col="timer">{timer}</span>
      </React.Fragment>
    );
  }

  return (
    <div className={"irow" + (isIncluded ? '' : ' excluded')}>
      <div className={"irow-sum " + rowClass} onClick={function() { setExpanded(!expanded); }}>
        <div className="ir-tog" onClick={handleToggleClick}>
          <input type="checkbox" checked={isIncluded} readOnly />
          <span className="slider"></span>
        </div>
        {renderSummaryColumns()}
        <div className="ir-acts">
          <button title="Expand" onClick={handleExpandClick}>
            {expanded ? '▾' : '▸'}
          </button>
        </div>
      </div>

      {expanded && (
        <QuestionRowDetail
          item={item}
          catColor={catColor}
          moduleId={moduleId}
          contentType={contentType}
        />
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// QTypeGroup — collapsible group of quiz items by QType
// ---------------------------------------------------------------------------
function QTypeGroup(props) {
  var qtype = props.qtype;
  var items = props.items;
  var includedIds = props.includedIds;
  var onToggle = props.onToggle;
  var onBulkSelect = props.onBulkSelect;
  var onBulkDeselect = props.onBulkDeselect;
  var i18nCache = props.i18nCache;
  var moduleId = props.moduleId;
  var moduleColor = props.moduleColor;
  var categories = props.categories;
  var contentType = props.contentType;
  var hasEvent = props.hasEvent;
  var defaultOpen = props.defaultOpen;

  var _ex = React.useState(defaultOpen !== false);
  var expanded = _ex[0];
  var setExpanded = _ex[1];

  var enabledCount = 0;
  items.forEach(function(item) {
    if (includedIds.indexOf(item.id) >= 0) enabledCount++;
  });

  var label = QTYPE_LABELS[qtype] || qtype || 'Unknown';
  var qtBadgeClass = 'qt-badge ' + qtype;

  return (
    <div className={"clib-qgroup" + (expanded ? " open" : "")}>
      <div className="clib-qgroup__header" onClick={function() { setExpanded(!expanded); }}>
        <span className="clib-qgroup__chevron">{expanded ? '▾' : '▸'}</span>
        <span className={qtBadgeClass}>{label}</span>
        <span className="clib-qgroup__count">{items.length + ' items'}</span>
        {hasEvent && (
          <span className={"clib-qgroup__enabled" + (enabledCount === items.length ? " all" : enabledCount === 0 ? " none" : "")}>
            {enabledCount + ' enabled'}
          </span>
        )}
        <span className="clib-qgroup__spacer"></span>
        {hasEvent && (
          <span className="clib-qgroup__actions" onClick={function(e) { e.stopPropagation(); }}>
            <button className="btn ghost sm" onClick={function() { onBulkSelect(items); }}>Enable all</button>
            <button className="btn ghost sm" onClick={function() { onBulkDeselect(items); }}>Disable all</button>
          </span>
        )}
      </div>
      {expanded && (
        <div className="clib-qgroup__body">
          <div className="ilist-header quiz-row">
            <span>Toggle</span>
            <span>QType</span>
            <span data-col="diff">Difficulty</span>
            <span data-col="cat">Category</span>
            <span data-col="prompt">Prompt</span>
            <span data-col="audiences">Audiences</span>
            <span className="ilist-header-ghost"></span>
            <span data-col="pts">Points</span>
            <span data-col="timer">Timer</span>
            <span className="ilist-header-ghost"></span>
          </div>
          {items.map(function(item) {
            var isIncluded = includedIds.indexOf(item.id) >= 0;
            return (
              <QuestionRow
                key={item.id}
                item={item}
                isIncluded={isIncluded}
                onToggle={onToggle}
                i18nCache={i18nCache}
                moduleId={moduleId}
                moduleColor={moduleColor}
                categories={categories}
                contentType={contentType}
              />
            );
          })}
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// ContentList — renders list of QuestionRow items
// ---------------------------------------------------------------------------
function ContentList(props) {
  var items = props.items;
  var includedIds = props.includedIds;
  var onToggle = props.onToggle;
  var onBulkSelect = props.onBulkSelect;
  var onBulkDeselect = props.onBulkDeselect;
  var i18nCache = props.i18nCache;
  var moduleId = props.moduleId;
  var moduleColor = props.moduleColor;
  var categories = props.categories;
  var contentType = props.contentType;
  var hasEvent = props.hasEvent;

  if (!items || items.length === 0) {
    return <div className="ilist-empty">No items match your filters.</div>;
  }

  // For quiz content, group by QType with collapsible sections
  if (contentType === 'quiz') {
    var groups = {};
    var groupOrder = [];
    items.forEach(function(item) {
      var t = item.type || 'text';
      if (!groups[t]) {
        groups[t] = [];
        groupOrder.push(t);
      }
      groups[t].push(item);
    });

    return (
      <div className="ilist ilist--grouped">
        {groupOrder.map(function(qtype, idx) {
          return (
            <QTypeGroup
              key={qtype}
              qtype={qtype}
              items={groups[qtype]}
              includedIds={includedIds}
              onToggle={onToggle}
              onBulkSelect={onBulkSelect}
              onBulkDeselect={onBulkDeselect}
              i18nCache={i18nCache}
              moduleId={moduleId}
              moduleColor={moduleColor}
              categories={categories}
              contentType={contentType}
              hasEvent={hasEvent}
              defaultOpen={false}
            />
          );
        })}
      </div>
    );
  }

  // Non-quiz content: flat list as before
  return (
    <div className="ilist">
      {items.map(function(item) {
        var isIncluded = includedIds.indexOf(item.id) >= 0;
        return (
          <QuestionRow
            key={item.id}
            item={item}
            isIncluded={isIncluded}
            onToggle={onToggle}
            i18nCache={i18nCache}
            moduleId={moduleId}
            moduleColor={moduleColor}
            categories={categories}
            contentType={contentType}
          />
        );
      })}
    </div>
  );
}

// ---------------------------------------------------------------------------
// ModuleContentExplorer — View 2: drill-down into a module's content
// ---------------------------------------------------------------------------
function ModuleContentExplorer(props) {
  var module = props.module;
  var events = props.events;
  var state = props.state;
  var dispatch = props.dispatch;

  var tabRef = React.useState('quiz');
  var activeTab = tabRef[0];
  var setActiveTab = tabRef[1];

  var filterRef = React.useState({ search: '', category: '', qtype: '', difficulty: '', audience: '' });
  var filters = filterRef[0];
  var setFilters = filterRef[1];

  var excludedRef = React.useState(true);
  var showExcluded = excludedRef[0];
  var setShowExcluded = excludedRef[1];

  var moduleData = module.data;
  var counts = getModuleContentCounts(moduleData);

  var allItems = getContentTypeItems(moduleData, activeTab);
  var includedIds = getIncludedIds(state.configs, module.id, activeTab, allItems);

  var categories = module.categories || {};
  var categoryNames = Object.keys(categories);

  var filteredItems = filterContentItems(allItems, {
    search: filters.search,
    category: filters.category,
    qtype: filters.qtype,
    difficulty: filters.difficulty,
    audience: filters.audience,
    showExcluded: showExcluded,
    includedIds: includedIds
  });

  var enabledCount = includedIds.length;
  var totalCount = allItems.length;

  function handleToggle(itemId) {
    var ids = allItems.map(function(it) { return it.id; });
    dispatch({ type: 'TOGGLE_ITEM', moduleId: module.id, contentType: activeTab, itemId: itemId, allItemIds: ids });
  }

  function handleFilterChange(key, value) {
    var next = Object.assign({}, filters);
    next[key] = value;
    setFilters(next);
  }

  function handleSelectAll() {
    var ids = allItems.map(function(it) { return it.id; });
    dispatch({ type: 'SELECT_ALL', moduleId: module.id, contentType: activeTab, itemIds: ids });
  }

  function handleDeselectAll() {
    dispatch({ type: 'DESELECT_ALL', moduleId: module.id, contentType: activeTab });
  }

  function handleBulkSelect(groupItems) {
    var currentIds = getIncludedIds(state.configs, module.id, activeTab, allItems);
    var groupIds = groupItems.map(function(it) { return it.id; });
    var merged = currentIds.slice();
    groupIds.forEach(function(id) {
      if (merged.indexOf(id) === -1) merged.push(id);
    });
    dispatch({ type: 'SELECT_ALL', moduleId: module.id, contentType: activeTab, itemIds: merged });
  }

  function handleBulkDeselect(groupItems) {
    var currentIds = getIncludedIds(state.configs, module.id, activeTab, allItems);
    var groupIds = groupItems.map(function(it) { return it.id; });
    var filtered = currentIds.filter(function(id) { return groupIds.indexOf(id) === -1; });
    dispatch({ type: 'SELECT_ALL', moduleId: module.id, contentType: activeTab, itemIds: filtered });
  }

  return (
    <div>
      <EventContextBar
        module={module}
        events={events}
        state={state}
        dispatch={dispatch}
        enabledCount={enabledCount}
        totalCount={totalCount}
        wizardContext={props.wizardContext}
        onDone={props.onDone}
      />
      <ContentTabs
        activeTab={activeTab}
        counts={counts}
        onTabChange={setActiveTab}
      />
      <FilterRail
        filters={filters}
        onFilterChange={handleFilterChange}
        categories={categoryNames}
        showExcluded={showExcluded}
        onToggleExcluded={function() { setShowExcluded(!showExcluded); }}
        onSelectAll={handleSelectAll}
        onDeselectAll={handleDeselectAll}
        activeTab={activeTab}
      />
      <ContentList
        items={filteredItems}
        includedIds={includedIds}
        onToggle={handleToggle}
        onBulkSelect={handleBulkSelect}
        onBulkDeselect={handleBulkDeselect}
        i18nCache={state.i18nCache}
        moduleId={module.id}
        moduleColor={module.color}
        categories={categories}
        contentType={activeTab}
        hasEvent={!!state.selectedEventId}
      />
    </div>
  );
}

// ---------------------------------------------------------------------------
// ContentLibraryInner — reads context, routes between View 1 and View 2
// ---------------------------------------------------------------------------
function ContentLibraryInner(props) {
  var ctx = React.useContext(CurationContext);
  var state = ctx.state;
  var dispatch = ctx.dispatch;
  var saveTimerRef = React.useRef(null);
  var lastSavedRef = React.useRef(null);

  var selectedModule = state.selectedModuleId
    ? ((window.GAME_MODULES || {})[state.selectedModuleId] || null)
    : null;

  // Wizard context state
  var _wc = React.useState(null);
  var wizardContext = _wc[0];
  var setWizardContext = _wc[1];

  // Check for preselected module or wizard context on mount
  React.useEffect(function() {
    if (window.__clibWizardContext) {
      var ctx = window.__clibWizardContext;
      window.__clibWizardContext = null;
      setWizardContext(ctx);
      if (ctx.moduleId) dispatch({ type: 'SELECT_MODULE', moduleId: ctx.moduleId });
      if (ctx.eventId) dispatch({ type: 'SELECT_EVENT', eventId: String(ctx.eventId) });
    } else if (window.__clibPreselect) {
      var moduleId = window.__clibPreselect;
      window.__clibPreselect = null;
      dispatch({ type: 'SELECT_MODULE', moduleId: moduleId });
    }
  }, []);

  // Load module_configs when event selection changes
  React.useEffect(function() {
    if (!state.selectedEventId) {
      dispatch({ type: 'INIT_CONFIGS', configs: {} });
      return;
    }
    if (typeof AdminApi === 'undefined') return;
    AdminApi.getModuleConfigs(state.selectedEventId).then(function(res) {
      var mc = (res && res.module_configs) ? res.module_configs : {};
      dispatch({ type: 'INIT_CONFIGS', configs: mc });
      lastSavedRef.current = JSON.stringify(mc);
    }).catch(function(err) {
      console.error('[ContentLibrary] Failed to load module configs:', err);
      dispatch({ type: 'INIT_CONFIGS', configs: {} });
    });
  }, [state.selectedEventId]);

  // Auto-save configs when they change (debounced 1.5s)
  React.useEffect(function() {
    if (!state.selectedEventId) return;
    var serialized = JSON.stringify(state.configs);
    if (serialized === lastSavedRef.current) return; // no change
    if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
    saveTimerRef.current = setTimeout(function() {
      if (typeof AdminApi === 'undefined') return;
      AdminApi.saveModuleConfigs(state.selectedEventId, state.configs).then(function() {
        lastSavedRef.current = serialized;
        if (props.showToast) props.showToast('Curation saved', 'ok');
      }).catch(function(err) {
        console.error('[ContentLibrary] Failed to save module configs:', err);
        if (props.showToast) props.showToast('Save failed', 'error');
      });
    }, 1500);
    return function() {
      if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
    };
  }, [state.configs, state.selectedEventId]);

  // Lazy-load i18n JSON when language or module changes
  React.useEffect(function() {
    if (!state.selectedModuleId || state.language === 'en') return;
    var langSuffix = state.language === 'es' ? 'es' : 'pt';
    var cacheKey = state.selectedModuleId + '-' + langSuffix;
    if (state.i18nCache[cacheKey]) return; // Already cached
    if (state.i18nLoading[cacheKey]) return; // Already loading
    dispatch({ type: 'SET_I18N_LOADING', key: cacheKey, loading: true });
    var url = '/modules/i18n/' + state.selectedModuleId + '-' + langSuffix + '.json';
    fetch(url).then(function(r) {
      if (!r.ok) throw new Error('HTTP ' + r.status);
      return r.json();
    }).then(function(data) {
      dispatch({ type: 'CACHE_I18N', key: cacheKey, data: data });
      dispatch({ type: 'SET_I18N_LOADING', key: cacheKey, loading: false });
    }).catch(function(err) {
      console.warn('[ContentLibrary] Failed to load i18n:', url, err);
      dispatch({ type: 'SET_I18N_LOADING', key: cacheKey, loading: false });
    });
  }, [state.selectedModuleId, state.language]);

  function handleSelectModule(moduleId) {
    dispatch({ type: 'SELECT_MODULE', moduleId: moduleId });
  }

  function handleDone() {
    if (wizardContext && wizardContext.returnPage && props.onNavigate) {
      setWizardContext(null);
      props.onNavigate(wizardContext.returnPage);
    }
  }

  return (
    <div className={"clib page" + (wizardContext ? " clib--wizard" : "")}>
      {selectedModule ? (
        <ModuleContentExplorer
          module={selectedModule}
          events={props.games || []}
          state={state}
          dispatch={dispatch}
          wizardContext={wizardContext}
          onDone={handleDone}
        />
      ) : (
        <ModuleOverviewGrid
          onSelectModule={handleSelectModule}
          configs={state.configs}
        />
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// OrgContentLibraryPage — public entry point registered on window
// ---------------------------------------------------------------------------
window.OrgContentLibraryPage = function OrgContentLibraryPage(props) {
  return (
    <CurationProvider>
      <ContentLibraryInner games={props.games} showToast={props.showToast} onNavigate={props.onNavigate} />
    </CurationProvider>
  );
};

// --- END organizer-content-library.jsx ---
