// ============================================================
// LEARNING HUB — User content feed, viewer, quizzes + Admin CMS
// ============================================================
import {
  clearQuestionBlocks,
  destroyOptionEditor,
  destroyQuestionBlockEditors,
  getTpHTML,
  makeTpEditor
} from './learningHub/tiptapEditor.js';
import { esc, sanitizeHtml } from './learningHub/sanitize.js';
import { deleteJson, getJson, sendJson } from './learningHub/api.js';
import { createAiPanelController } from './learningHub/aiPanelController.js';
import {
  renderOptionRowShell,
  renderQuestionBlockShell
} from './learningHub/cmsRenderer.js';
import { createCmsController } from './learningHub/cmsController.js';
import { renderCategoryPills, renderEmptySearchMessage, renderFeed, renderSearchHeader } from './learningHub/feedRenderer.js';
import { createQuizController } from './learningHub/quizController.js';
import { createSlideController } from './learningHub/slideController.js';
import { buildViewerMeta, renderPresentationCard, renderProgressList } from './learningHub/viewerRenderer.js';
import { createWebdavController } from './learningHub/webdavController.js';

  var loaded = false;
  var cmsLoaded = false;
  var currentContent = null;
  var currentView = 'feed'; // 'feed' | 'category' | 'viewer'
  var _bodyEditor = null; // Tiptap Editor instance for body
  var slides = createSlideController({
    getMarkdown: getMarpMarkdown,
    getTitle: getPresentationTitle,
    showBusy: function(message) { showBusy(message); },
    hideBusy: function() { hideBusy(); },
    showToast: function(message, type) { showToast(message, type); }
  });
  var cms = createCmsController({
    refreshUserCategories: function() { loadCategories(); },
    showToast: function(message, type) { showToast(message, type); }
  });
  var quiz = createQuizController({
    getCurrentContent: function() { return currentContent; },
    showLoading: function(message) { showLoading(message); },
    hideLoading: function() { hideLoading(); },
    showToast: function(message, type) { showToast(message, type); }
  });
  var webdav = createWebdavController({});
  var aiPanel = createAiPanelController({
    browseWebdav: function(path) { webdav.browse(path); },
    getEditorType: function() { return (document.getElementById('lh-cms-edit-type') || {}).value; },
    getWebdavPath: function() { return webdav.getCurrentPath(); },
    setWebdavPath: function(path) { webdav.setCurrentPath(path); }
  });

  // ── Load when tab activated ────────────────────────────────
  document.addEventListener('tabChanged', function(e) {
    if (e.detail && e.detail.tab === 'learning') {
      if (!loaded) { loadFeed(); loadCategories(); loaded = true; wireSearch(); }
    }
    // Load CMS when Content Manager tab is opened
    if (e.detail && e.detail.tab === 'cms') {
      if (!cmsLoaded) { loadCms(); cmsLoaded = true; wireCmsFileInput(); wireCmsTypeSelect(); }
    }
  });

  // ── Event delegation ───────────────────────────────────────
  document.addEventListener('click', function(e) {
    // Slide preview modal controls (checked first — modal is outside CMS)
    if (e.target.closest('#slide-preview-close') || e.target.id === 'slide-preview-overlay') { slides.closeSlideModal(); return; }
    if (e.target.closest('#slide-nav-prev'))  { slides.slideStep(-1); return; }
    if (e.target.closest('#slide-nav-next'))  { slides.slideStep(1);  return; }
    var dot = e.target.closest('.slide-dot');
    if (dot) { slides.renderSlide(parseInt(dot.dataset.idx)); return; }


    // Feed item click
    var feedItem = e.target.closest('.lh-feed-item');
    if (feedItem && feedItem.dataset.slug) {
      loadContent(feedItem.dataset.slug);
      return;
    }

    // Category pill click
    var catPill = e.target.closest('.lh-cat-pill');
    if (catPill && catPill.dataset.slug) {
      if (catPill.dataset.slug === 'all') {
        loadFeed();
        setActiveCatPill('all');
      } else {
        loadCategoryContent(catPill.dataset.slug);
        setActiveCatPill(catPill.dataset.slug);
      }
      return;
    }

    // Back button
    if (e.target.closest('#lh-back')) {
      showFeed();
      return;
    }

    // Submit quiz
    if (e.target.closest('#lh-submit-quiz')) {
      quiz.submitQuiz();
      return;
    }

    // ── CMS events ─────────────────────────────
    if (e.target.closest('#btn-lh-refresh-content')) { cms.loadContent(); cms.loadStats(); return; }
    if (e.target.closest('#btn-lh-add-cat')) { cms.addCategory(); return; }
    if (e.target.closest('#btn-lh-new-content')) { openEditor(null, 'article'); return; }
    if (e.target.closest('#btn-lh-new-quiz')) { openEditor(null, 'quiz'); return; }
    if (e.target.closest('#btn-lh-new-pearl')) { openEditor(null, 'pearl'); return; }
    if (e.target.closest('#btn-lh-new-presentation')) { openEditor(null, 'presentation'); return; }
    if (e.target.closest('#btn-lh-close-editor')) { closeEditor(); return; }
    if (e.target.closest('#btn-lh-save-content')) { saveContent(); return; }
    if (e.target.closest('#btn-lh-delete-content')) { showDeleteConfirm(); return; }
    if (e.target.closest('#btn-lh-delete-yes'))     { confirmDelete(); return; }
    if (e.target.closest('#btn-lh-delete-cancel'))  { hideDeleteConfirm(); return; }
    if (e.target.closest('#btn-lh-add-question')) { addQuestionBlock(); return; }

    // Presentation
    if (e.target.closest('#btn-lh-preview-slides'))  { slides.previewCurrentSlides(); return; }
    if (e.target.closest('#btn-lh-download-pptx'))   { slides.downloadPptx(); return; }

    // AI panel
    if (e.target.closest('#btn-lh-ai-open'))        { aiPanel.open(); return; }
    if (e.target.closest('#btn-lh-ai-close'))        { aiPanel.close(); return; }
    if (e.target.closest('#btn-lh-ai-generate'))     { runAiGenerate(); return; }
    if (e.target.closest('#btn-lh-ai-refine-body'))  { toggleRefineBar(); return; }
    if (e.target.closest('#btn-lh-refine-submit'))   { submitRefineBody(); return; }
    if (e.target.closest('#btn-lh-refine-cancel'))   { toggleRefineBar(false); return; }
    if (e.target.closest('#btn-lh-webdav-refresh'))  { webdav.browse(webdav.getCurrentPath()); return; }
    if (e.target.closest('#btn-lh-webdav-deselect')) { webdav.deselectFile(); return; }

    // AI tabs
    var aiTab = e.target.closest('.lh-ai-tab');
    if (aiTab && aiTab.dataset.aitab) { aiPanel.switchTab(aiTab.dataset.aitab); return; }

    // WebDAV list items
    var wdItem = e.target.closest('.lh-webdav-item');
    if (wdItem) {
      webdav.openItem(wdItem);
      return;
    }

    // Rich text toggle for question or option
    var rtBtn = e.target.closest('.lh-richtext-btn');
    if (rtBtn) { toggleRichText(rtBtn); return; }

    // CMS content item edit
    var cmsItem = e.target.closest('.lh-cms-content-item');
    if (cmsItem && cmsItem.dataset.id) { openEditor(cmsItem.dataset.id); return; }

    // CMS delete category
    var delCat = e.target.closest('.lh-cms-del-cat');
    if (delCat) { cms.deleteCategory(delCat.dataset.id); return; }

    // CMS sidebar category filter
    var cmsCat = e.target.closest('.lh-cms-cat-filter');
    if (cmsCat && cmsCat.dataset.id) { cms.filterByCategory(cmsCat.dataset.id); return; }

    // Remove question block
    var rmQ = e.target.closest('.lh-rm-question');
    if (rmQ) { var qb = rmQ.closest('.lh-question-block'); if (qb) { destroyQuestionBlockEditors(qb); qb.remove(); } return; }

    // Add option to question
    var addOpt = e.target.closest('.lh-add-option');
    if (addOpt) {
      var qBlock = addOpt.closest('.lh-question-block');
      if (qBlock) addOptionRow(qBlock.querySelector('.lh-options-list'), null);
      return;
    }

    // Remove option
    var rmOpt = e.target.closest('.lh-rm-option');
    if (rmOpt) { var row = rmOpt.closest('.lh-option-row'); if (row) { destroyOptionEditor(row); row.remove(); } return; }
  });

  document.addEventListener('input', function(e) { cms.handleFilterInput(e); });
  document.addEventListener('change', function(e) { cms.handleFilterChange(e); });

  // wireSearch() called after component is in DOM
  var _searchTimeout = null;
  function wireSearch() {
    var searchEl = document.getElementById('lh-search');
    if (!searchEl || searchEl._wired) return;
    searchEl._wired = true;
    searchEl.addEventListener('input', function() {
      clearTimeout(_searchTimeout);
      var q = searchEl.value.trim();
      if (!q) { loadFeed(); return; }
      _searchTimeout = setTimeout(function() { searchContent(q); }, 350);
    });
    searchEl.addEventListener('keydown', function(e) {
      if (e.key === 'Escape') { searchEl.value = ''; loadFeed(); }
    });
  }

  // ============================================================
  // USER-FACING: FEED, CATEGORIES, CONTENT, QUIZZES
  // ============================================================

  function loadFeed() {
    var feedEl = document.getElementById('lh-feed');
    if (!feedEl) return;
    feedEl.innerHTML = '<p style="text-align:center;color:var(--g400);padding:24px;">Loading...</p>';
    showFeed();

    getJson('/api/learning/feed')
      .then(function(data) {
        if (!data.success) { feedEl.innerHTML = '<p style="text-align:center;color:var(--red);padding:24px;">Failed to load</p>'; return; }
        renderFeed(data.content, feedEl);
      })
      .catch(function() { feedEl.innerHTML = '<p style="text-align:center;color:var(--red);padding:24px;">Connection error</p>'; });
  }

  function loadCategories() {
    getJson('/api/learning/categories')
      .then(function(data) {
        if (!data.success) return;
        var bar = document.getElementById('lh-categories');
        if (!bar) return;
        bar.innerHTML = renderCategoryPills(data.categories);
      });
  }

  function loadCategoryContent(slug) {
    var feedEl = document.getElementById('lh-feed');
    if (!feedEl) return;
    feedEl.innerHTML = '<p style="text-align:center;color:var(--g400);padding:24px;">Loading...</p>';
    showFeed();

    getJson('/api/learning/category/' + encodeURIComponent(slug))
      .then(function(data) {
        if (!data.success) { feedEl.innerHTML = '<p style="text-align:center;color:var(--red);padding:24px;">Category not found</p>'; return; }
        renderFeed(data.content, feedEl);
      });
  }

  function searchContent(q) {
    var feedEl = document.getElementById('lh-feed');
    if (!feedEl) return;
    showFeed();
    feedEl.innerHTML =
      '<div style="padding:8px 0 12px;font-size:13px;color:var(--g500);">' +
        '<i class="fas fa-search"></i> Searching for <strong>"' + esc(q) + '"</strong>…' +
      '</div>';

    getJson('/api/learning/search?q=' + encodeURIComponent(q))
      .then(function(data) {
        if (!data.success) { feedEl.innerHTML = '<p style="color:var(--red);padding:12px;">Search failed</p>'; return; }
        var header = renderSearchHeader(data.content.length, q);

        if (data.content.length === 0) {
          feedEl.innerHTML = header + renderEmptySearchMessage();
        } else {
          var tempEl = document.createElement('div');
          renderFeed(data.content, tempEl);
          feedEl.innerHTML = header + tempEl.innerHTML;
        }

        var clearBtn = document.getElementById('lh-search-clear');
        if (clearBtn) {
          clearBtn.addEventListener('click', function() {
            var s = document.getElementById('lh-search');
            if (s) s.value = '';
            loadFeed();
          });
        }
      })
      .catch(function() { feedEl.innerHTML = '<p style="color:var(--red);padding:12px;">Search error</p>'; });
  }

  function loadContent(slug) {
    getJson('/api/learning/content/' + encodeURIComponent(slug))
      .then(function(data) {
        if (!data.success) { showToast(data.error || 'Content not found', 'error'); return; }
        currentContent = data.content;
        showViewer(data.content);
      })
      .catch(function() { showToast('Failed to load content', 'error'); });
  }

  function showFeed() {
    currentView = 'feed';
    var feedEl    = document.getElementById('lh-feed');
    var viewerEl  = document.getElementById('lh-viewer');
    var catsEl    = document.getElementById('lh-categories');
    var searchEl  = document.getElementById('lh-search');
    // Use style.display — classList.add('hidden') is overridden by .lh-feed{display:flex}
    // and .lh-category-bar{display:flex} which are defined later in CSS
    if (feedEl)   feedEl.style.display  = 'flex';
    if (viewerEl) viewerEl.style.display = 'none';
    if (catsEl)   catsEl.style.display  = 'flex';
    if (searchEl) { var sc = searchEl.closest('.card'); if (sc) sc.style.display = ''; }
  }

  function showViewer(item) {
    currentView = 'viewer';
    var feedEl    = document.getElementById('lh-feed');
    var viewerEl  = document.getElementById('lh-viewer');
    var catsEl    = document.getElementById('lh-categories');
    var searchEl  = document.getElementById('lh-search');
    if (feedEl)   feedEl.style.display  = 'none';
    if (viewerEl) viewerEl.style.display = 'block';
    if (catsEl)   catsEl.style.display  = 'none';
    if (searchEl) { var sc = searchEl.closest('.card'); if (sc) sc.style.display = 'none'; }

    var titleEl = document.getElementById('lh-viewer-title');
    var metaEl = document.getElementById('lh-viewer-meta');
    var bodyEl = document.getElementById('lh-viewer-body');
    var quizSection = document.getElementById('lh-quiz-section');
    var resultsSection = document.getElementById('lh-quiz-results');
    var progressSection = document.getElementById('lh-progress-section');

    if (titleEl) titleEl.textContent = item.title;
    if (metaEl) metaEl.textContent = buildViewerMeta(item);
    var presViewer = document.getElementById('lh-presentation-viewer');
    var bodyCard   = bodyEl ? bodyEl.closest('.card') : null;

    if (item.content_type === 'presentation') {
      // Hide body card, show presentation card with View Slides button
      if (bodyCard) bodyCard.style.display = 'none';
      if (presViewer) {
        presViewer.className = '';  // remove hidden
        presViewer.innerHTML = renderPresentationCard(item);

        // Auto-load and open slides
        document.getElementById('btn-lh-view-slides').addEventListener('click', function() {
          slides.openSlidesFromSlug(item.slug);
        });
        // Open automatically on load
        slides.openSlidesFromSlug(item.slug);
      }
      // Quiz for presentations (optional)
      if (quizSection) {
        if (item.questions && item.questions.length > 0) {
          quizSection.classList.remove('hidden');
          quiz.renderQuiz(item.questions);
        } else {
          quizSection.classList.add('hidden');
        }
      }
    } else {
      // Normal content — show body card, hide presentation card
      if (bodyCard) bodyCard.style.display = '';
      if (presViewer) presViewer.className = 'hidden';
      if (bodyEl) bodyEl.innerHTML = sanitizeHtml(item.body || '');

      if (quizSection) {
        if (item.questions && item.questions.length > 0) {
          quizSection.classList.remove('hidden');
          quiz.renderQuiz(item.questions);
        } else {
          quizSection.classList.add('hidden');
        }
      }
    }
    if (resultsSection) resultsSection.classList.add('hidden');

    // Progress
    if (progressSection && item.progress && item.progress.length > 0) {
      progressSection.classList.remove('hidden');
      document.getElementById('lh-progress-list').innerHTML = renderProgressList(item.progress);
    } else if (progressSection) {
      progressSection.classList.add('hidden');
    }
  }

  function setActiveCatPill(slug) {
    document.querySelectorAll('.lh-cat-pill').forEach(function(p) {
      p.classList.toggle('active', p.dataset.slug === slug);
    });
  }

  // ============================================================
  // ADMIN CMS
  // ============================================================

  function wireCmsTypeSelect() {
    var typeEl = document.getElementById('lh-cms-edit-type');
    if (typeEl) {
      typeEl.addEventListener('change', function() { toggleEditorMode(typeEl.value); });
    }
  }

  function wireCmsFileInput() {
    var fileInput = document.getElementById('lh-ai-file');
    var fileLabel = document.getElementById('lh-ai-file-label');
    var filesList = document.getElementById('lh-ai-files-list');
    var dropzone  = document.getElementById('lh-ai-dropzone');

    function updateFilesList() {
      if (!fileInput || !fileLabel || !filesList) return;
      var files = fileInput.files;
      if (files.length === 0) {
        fileLabel.textContent = 'Drop files here or click to browse';
        filesList.style.display = 'none';
        filesList.innerHTML = '';
      } else if (files.length === 1) {
        fileLabel.textContent = files[0].name;
        filesList.style.display = 'none';
        filesList.innerHTML = '';
      } else {
        fileLabel.textContent = files.length + ' files selected';
        filesList.style.display = 'block';
        filesList.innerHTML = '<ul style="list-style:none;padding:0;margin:0;font-size:0.9em;">' +
          Array.from(files).map(function(f) {
            return '<li style="padding:2px 0;"><i class="fas fa-file-pdf" style="color:var(--blue);margin-right:4px;"></i>' + f.name + '</li>';
          }).join('') + '</ul>';
      }
    }

    if (fileInput) {
      fileInput.addEventListener('change', updateFilesList);
    }
    if (dropzone) {
      dropzone.addEventListener('dragover', function(e) { e.preventDefault(); dropzone.style.borderColor = 'var(--blue)'; });
      dropzone.addEventListener('dragleave', function() { dropzone.style.borderColor = ''; });
      dropzone.addEventListener('drop', function(e) {
        e.preventDefault();
        dropzone.style.borderColor = '';
        var files = e.dataTransfer.files;
        if (files.length > 0 && fileInput) {
          // Transfer to file input via DataTransfer
          try {
            var dt = new DataTransfer();
            for (var i = 0; i < files.length && i < 10; i++) {
              dt.items.add(files[i]);
            }
            fileInput.files = dt.files;
            updateFilesList();
          } catch(ex) {}
        }
      });
    }
  }

  function loadCms() {
    cms.refreshAll();
  }

  // ============================================================
  // AI GENERATE PANEL
  // ============================================================

  // ── Generate ────────────────────────────────────────────────
  function runAiGenerate() {
    var activeTab = document.querySelector('.lh-ai-tab.active');
    var tabName = activeTab ? activeTab.dataset.aitab : 'topic';
    var model        = document.getElementById('lh-ai-model') ? document.getElementById('lh-ai-model').value : getSelectedModel();
    var contentType  = document.getElementById('lh-ai-ctype') ? document.getElementById('lh-ai-ctype').value : 'article';
    var refinement   = document.getElementById('lh-ai-refinement') ? document.getElementById('lh-ai-refinement').value.trim() : '';
    var toggleCb     = document.getElementById('lh-ai-q-toggle');
    var generateQs   = contentType === 'quiz' || (toggleCb && toggleCb.checked);
    var questionCount = generateQs ? (document.getElementById('lh-ai-q-count') ? document.getElementById('lh-ai-q-count').value : 5) : 0;
    var wordCount    = document.getElementById('lh-ai-word-count') ? document.getElementById('lh-ai-word-count').value : '';
    var slideCount   = document.getElementById('lh-ai-slide-count') ? document.getElementById('lh-ai-slide-count').value : '';

    var formData = new FormData();
    if (model) formData.append('model', model);
    formData.append('questionCount', questionCount);
    formData.append('contentType', contentType);
    if (refinement) formData.append('refinement', refinement);
    if (wordCount)  formData.append('wordCount', wordCount);
    if (slideCount) formData.append('slideCount', slideCount);

    if (tabName === 'topic') {
      var topic = document.getElementById('lh-ai-topic') ? document.getElementById('lh-ai-topic').value.trim() : '';
      if (!topic) { showToast('Describe what you want AI to create', 'error'); return; }
      formData.append('topic', topic);
    } else if (tabName === 'upload') {
      var fileInput = document.getElementById('lh-ai-file');
      if (!fileInput || fileInput.files.length === 0) { showToast('Select at least one file to upload', 'error'); return; }
      for (var i = 0; i < fileInput.files.length; i++) {
        formData.append('files', fileInput.files[i]);
      }
      var uploadCtx = document.getElementById('lh-ai-upload-context');
      if (uploadCtx && uploadCtx.value.trim()) formData.append('topic', uploadCtx.value.trim());
    } else if (tabName === 'webdav') {
      var webdavPath = webdav.getSelectedPath();
      if (!webdavPath) { showToast('Select a file from Nextcloud', 'error'); return; }
      formData.append('webdavPath', webdavPath);
      var webdavCtx = document.getElementById('lh-ai-webdav-context');
      if (webdavCtx && webdavCtx.value.trim()) formData.append('topic', webdavCtx.value.trim());
    }

    var btn = document.getElementById('btn-lh-ai-generate');
    if (btn) { btn.disabled = true; btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating...'; }
    showBusy('AI is generating content...');

    // FormData: no Content-Type header (browser sets it with boundary)
    var token = window.AUTH_TOKEN || localStorage.getItem('ped_scribe_token') || '';
    fetch('/api/admin/learning/ai-generate', {
      method: 'POST',
      headers: { 'Authorization': 'Bearer ' + token },
      body: formData
    })
    .then(function(r) { return r.json(); })
    .then(function(data) {
      hideBusy();
      if (btn) { btn.disabled = false; btn.innerHTML = '<i class="fas fa-wand-magic-sparkles"></i> Generate Content'; }
      if (!data.success) { showToast(data.error || 'Generation failed', 'error'); return; }
      // Presentation returns marpMarkdown directly; others return content{}
      var payload = data.contentType === 'presentation' ? data : data.content;
      return applyAiContent(payload, contentType).then(function() {
        aiPanel.close();
        showToast('Content generated! Review and save.', 'success');
      });
    })
    .catch(function(err) {
      hideBusy();
      if (btn) { btn.disabled = false; btn.innerHTML = '<i class="fas fa-wand-magic-sparkles"></i> Generate Content'; }
      showToast(err.message, 'error');
    });
  }

  function applyAiContent(content, contentType) {
    // Set content type first so toggleEditorMode works correctly
    var typeEl = document.getElementById('lh-cms-edit-type');
    if (typeEl && contentType) { typeEl.value = contentType; toggleEditorMode(contentType); }

    // Presentation: fill Marp textarea
    if (contentType === 'presentation' && content.marpMarkdown) {
      var marpTa = document.getElementById('lh-marp-editor');
      if (marpTa) marpTa.value = content.marpMarkdown;
      // Extract title from first # heading
      var titleMatch = content.marpMarkdown.match(/^#\s+(.+)$/m);
      var titleEl = document.getElementById('lh-cms-edit-title');
      if (titleEl && titleMatch) titleEl.value = titleMatch[1];
      // Fill questions if any were generated alongside slides
      var qContainerP = document.getElementById('lh-cms-questions');
      if (qContainerP) {
        clearQuestionBlocks(qContainerP);
        if (content.questions && Array.isArray(content.questions)) {
          content.questions.forEach(function(q) { addQuestionBlock(q); });
        }
      }
      return applyAiCategory(content.category_name || content.category);
    }

    // Fill title
    var titleEl2 = document.getElementById('lh-cms-edit-title');
    if (titleEl2 && content.title) titleEl2.value = content.title;

    // Fill subject
    var subjectEl = document.getElementById('lh-cms-edit-subject');
    if (subjectEl && content.subject) subjectEl.value = content.subject;

    // Fill body via Tiptap
    if (_bodyEditor && content.body) _bodyEditor.commands.setContent(content.body);

    // Replace questions
    var qContainer = document.getElementById('lh-cms-questions');
    if (qContainer) {
      clearQuestionBlocks(qContainer);
      if (content.questions && Array.isArray(content.questions)) {
        content.questions.forEach(function(q) { addQuestionBlock(q); });
      }
    }
    return applyAiCategory(content.category_name || content.category);
  }

  function applyAiCategory(categoryName) {
    categoryName = (categoryName || '').trim();
    if (!categoryName) return Promise.resolve();

    var sel = document.getElementById('lh-cms-edit-category');
    if (!sel) return Promise.resolve();

    var existing = findCategoryOption(sel, categoryName);
    if (existing) {
      sel.value = existing.value;
      return Promise.resolve();
    }

    return sendJson('/api/admin/learning/categories', 'POST', { name: categoryName })
      .then(function(data) {
        if (!data.success || !data.id) throw new Error(data.error || 'Category creation failed');
        var opt = document.createElement('option');
        opt.value = data.id;
        opt.textContent = categoryName;
        sel.appendChild(opt);
        sel.value = String(data.id);
        cms.loadCategories(String(data.id));
        loadCategories();
      })
      .catch(function(err) {
        showToast('Generated category was not created: ' + err.message, 'error');
      });
  }

  function findCategoryOption(sel, categoryName) {
    var wanted = categoryName.toLowerCase();
    for (var i = 0; i < sel.options.length; i++) {
      if ((sel.options[i].textContent || '').trim().toLowerCase() === wanted) return sel.options[i];
    }
    return null;
  }

  function toggleRefineBar(forceShow) {
    var bar   = document.getElementById('lh-ai-refine-bar');
    var input = document.getElementById('lh-ai-refine-input');
    if (!bar) return;
    var show = forceShow !== undefined ? forceShow : bar.style.display === 'none';
    bar.style.display = show ? 'flex' : 'none';
    if (show && input) { input.value = ''; input.focus(); }
  }

  function submitRefineBody() {
    var input = document.getElementById('lh-ai-refine-input');
    var instructions = input ? input.value.trim() : '';
    if (!instructions) { showToast('Enter instructions for refinement', 'error'); return; }

    var currentBody = _bodyEditor ? getTpHTML(_bodyEditor) : '';
    if (!currentBody) { showToast('No body content to refine', 'error'); return; }

    var model = document.getElementById('lh-ai-model') ? document.getElementById('lh-ai-model').value : getSelectedModel();
    toggleRefineBar(false);
    showBusy('Refining content...');

    sendJson('/api/admin/learning/ai-refine', 'POST', { content: currentBody, instructions: instructions, model: model })
    .then(function(data) {
      hideBusy();
      if (!data.success) { showToast(data.error || 'Refine failed', 'error'); return; }
      if (_bodyEditor) _bodyEditor.commands.setContent(data.refined);
      showToast('Body refined!', 'success');
    })
    .catch(function(err) { hideBusy(); showToast(err.message, 'error'); });
  }

  // ── Body editor ────────────────────────────────────────────
  function initBodyEditor() {
    var wrap = document.getElementById('lh-body-editor');
    if (!wrap || _bodyEditor) return;
    _bodyEditor = makeTpEditor(wrap, '', false, false);
  }

  // ── Rich text toggle for questions / options ───────────────
  function toggleRichText(btn) {
    var isActive = btn.classList.contains('active');
    var target = btn.dataset.target;
    var block = btn.closest(target === 'question' ? '.lh-question-block' : '.lh-option-row');
    if (!block) return;

    if (target === 'question') {
      var ta   = block.querySelector('.lh-q-text');
      var wrap = block.querySelector('.lh-q-richtext-wrap');

      if (!isActive) {
        var val = ta ? ta.value : '';
        btn.classList.add('active');
        btn.textContent = 'Plain Text';
        if (ta) ta.style.display = 'none';
        if (!wrap) {
          wrap = document.createElement('div');
          wrap.className = 'lh-q-richtext-wrap';
          ta.parentNode.insertBefore(wrap, ta.nextSibling);
        }
        wrap.style.display = '';
        if (!block._questionEditor) block._questionEditor = makeTpEditor(wrap, val, true, false);
      } else {
        btn.classList.remove('active');
        btn.textContent = 'Rich Text';
        if (block._questionEditor) {
          if (ta) { ta.value = getTpHTML(block._questionEditor); ta.style.display = ''; }
        }
        if (wrap) wrap.style.display = 'none';
      }

    } else {
      var row      = block;
      var optInput = row.querySelector('.lh-opt-text');
      var optWrap  = row.querySelector('.lh-opt-richtext-wrap');

      if (!isActive) {
        var curVal = optInput ? optInput.value : '';
        btn.classList.add('active');
        btn.textContent = 'Plain';
        if (optInput) optInput.style.display = 'none';
        if (!optWrap) {
          optWrap = document.createElement('div');
          optWrap.className = 'lh-opt-richtext-wrap';
          optInput.parentNode.insertBefore(optWrap, optInput.nextSibling);
        }
        optWrap.style.display = '';
        if (!row._optEditor) row._optEditor = makeTpEditor(optWrap, curVal, true, true);
      } else {
        btn.classList.remove('active');
        btn.textContent = 'Rich';
        if (row._optEditor) {
          if (optInput) { optInput.value = getTpHTML(row._optEditor); optInput.style.display = ''; }
        }
        if (optWrap) optWrap.style.display = 'none';
      }
    }
  }

  function getQText(block) {
    var wrap = block.querySelector('.lh-q-richtext-wrap');
    if (block._questionEditor && wrap && wrap.style.display !== 'none') return getTpHTML(block._questionEditor);
    var ta = block.querySelector('.lh-q-text');
    return ta ? ta.value.trim() : '';
  }

  function getOptText(row) {
    var wrap = row.querySelector('.lh-opt-richtext-wrap');
    if (row._optEditor && wrap && wrap.style.display !== 'none') return getTpHTML(row._optEditor);
    var inp = row.querySelector('.lh-opt-text');
    return inp ? inp.value.trim() : '';
  }

  function openEditor(contentId, contentType) {
    var editor = document.getElementById('lh-cms-editor');
    var listView = document.getElementById('cms-list-view');
    if (!editor) return;
    editor.classList.remove('hidden');
    if (listView) listView.classList.add('hidden');

    // Reset
    document.getElementById('lh-cms-edit-id').value = '';
    document.getElementById('lh-cms-edit-title').value = '';
    document.getElementById('lh-cms-edit-subject').value = '';
    document.getElementById('lh-cms-edit-category').value = '';
    document.getElementById('lh-cms-edit-type').value = contentType || 'article';
    document.getElementById('lh-cms-edit-published').value = 'false';
    clearQuestionBlocks(document.getElementById('lh-cms-questions'));
    document.getElementById('btn-lh-delete-content').classList.add('hidden');
    hideDeleteConfirm();
    toggleEditorMode(contentType || 'article');
    initBodyEditor();
    if (_bodyEditor) _bodyEditor.commands.clearContent(true);
    var marpTa = document.getElementById('lh-marp-editor');
    if (marpTa) marpTa.value = '';

    // For quiz type, add a starter question
    if (contentType === 'quiz' && !contentId) {
      addQuestionBlock();
    }

    if (!contentId) return;

    // Load existing content
    getJson('/api/admin/learning/content/' + contentId)
      .then(function(data) {
        if (!data.success) { showToast('Failed to load', 'error'); return; }
        var c = data.content;
        document.getElementById('lh-cms-edit-id').value = c.id;
        document.getElementById('lh-cms-edit-title').value = c.title;
        document.getElementById('lh-cms-edit-subject').value = c.subject || '';
        document.getElementById('lh-cms-edit-category').value = c.category_id || '';
        document.getElementById('lh-cms-edit-type').value = c.content_type || 'article';
        document.getElementById('lh-cms-edit-published').value = c.published ? 'true' : 'false';
        document.getElementById('btn-lh-delete-content').classList.remove('hidden');
        toggleEditorMode(c.content_type || 'article');

        if (c.content_type === 'presentation') {
          var marpEl = document.getElementById('lh-marp-editor');
          if (marpEl) marpEl.value = c.body || '';
        } else {
          if (_bodyEditor) _bodyEditor.commands.setContent(c.body || '');
        }

        // Load questions
        var qContainer = document.getElementById('lh-cms-questions');
        clearQuestionBlocks(qContainer);
        if (c.questions && c.questions.length > 0) {
          c.questions.forEach(function(q) { addQuestionBlock(q); });
        }

        editor.scrollIntoView({ behavior: 'smooth' });
      });
  }

  function toggleEditorMode(contentType) {
    var bodySection = document.getElementById('lh-body-section');
    var marpSection = document.getElementById('lh-marp-section');
    var isPresentation = contentType === 'presentation';
    if (bodySection) bodySection.classList.toggle('hidden', isPresentation);
    if (marpSection) marpSection.classList.toggle('hidden', !isPresentation);
  }

  function closeEditor() {
    var editor = document.getElementById('lh-cms-editor');
    var listView = document.getElementById('cms-list-view');
    if (editor) editor.classList.add('hidden');
    if (listView) listView.classList.remove('hidden');
    hideDeleteConfirm();
  }

  function saveContent() {
    var id = document.getElementById('lh-cms-edit-id').value;
    var title = document.getElementById('lh-cms-edit-title').value.trim();
    var subject = document.getElementById('lh-cms-edit-subject').value.trim();
    var content_type = document.getElementById('lh-cms-edit-type').value;
    var body = content_type === 'presentation'
      ? (document.getElementById('lh-marp-editor') ? document.getElementById('lh-marp-editor').value : '')
      : (_bodyEditor ? getTpHTML(_bodyEditor) : '');
    var category_id = document.getElementById('lh-cms-edit-category').value || null;
    var published = document.getElementById('lh-cms-edit-published').value === 'true';

    if (!title) { showToast('Title required', 'error'); return; }

    // Gather questions with validation
    var questions = [];
    var validationError = false;
    var qBlocks = document.querySelectorAll('#lh-cms-questions .lh-question-block');
    for (var qi = 0; qi < qBlocks.length; qi++) {
      var qBlock = qBlocks[qi];
      var qText = getQText(qBlock);
      if (!qText) continue;
      var qType = qBlock.querySelector('.lh-q-type').value;
      var qExpl = qBlock.querySelector('.lh-q-explanation').value.trim();
      var qId = qBlock.dataset.questionId || null;

      var options = [];
      qBlock.querySelectorAll('.lh-option-row').forEach(function(row) {
        var optText = getOptText(row);
        if (!optText) return;
        options.push({
          option_text: optText,
          is_correct: row.querySelector('.lh-opt-correct').checked,
          explanation: row.querySelector('.lh-opt-expl').value.trim()
        });
      });

      // Validate: must have a correct answer marked
      var hasCorrect = options.some(function(o) { return o.is_correct; });
      if (options.length > 0 && !hasCorrect) {
        showToast('Question "' + qText.substring(0, 50) + '..." needs a correct answer marked', 'error');
        qBlock.style.outline = '2px solid var(--red)';
        qBlock.scrollIntoView({ behavior: 'smooth', block: 'center' });
        validationError = true;
        break;
      }
      qBlock.style.outline = '';

      questions.push({
        id: qId,
        question_text: qText,
        question_type: qType,
        explanation: qExpl,
        options: options
      });
    }
    if (validationError) return;

    var payload = { title: title, body: body, category_id: category_id, subject: subject, content_type: content_type, published: published };

    var method = id ? 'PUT' : 'POST';
    var url = id ? '/api/admin/learning/content/' + id : '/api/admin/learning/content';

    showLoading('Saving...');

    sendJson(url, method, payload)
      .then(function(data) {
        if (!data.success) { hideLoading(); showToast(data.error || 'Save failed', 'error'); return; }
        var contentId = id || data.id;

        // Save questions sequentially
        saveQuestions(contentId, questions, 0, function() {
          hideLoading();
          showToast('Content saved', 'success');
          closeEditor();
          cms.refreshAll();
          loaded = false; // force refresh user feed
        });
      })
      .catch(function() { hideLoading(); showToast('Save failed', 'error'); });
  }

  function saveQuestions(contentId, questions, index, callback) {
    if (index >= questions.length) { callback(); return; }

    var q = questions[index];
    var qId = q.id;
    var method, url;

    if (qId) {
      method = 'PUT';
      url = '/api/admin/learning/questions/' + qId;
    } else {
      method = 'POST';
      url = '/api/admin/learning/content/' + contentId + '/questions';
    }

    sendJson(url, method, {
      question_text: q.question_text,
      question_type: q.question_type,
      explanation: q.explanation,
      options: q.options
    })
    .then(function() {
      saveQuestions(contentId, questions, index + 1, callback);
    })
    .catch(function() {
      saveQuestions(contentId, questions, index + 1, callback);
    });
  }

  function showDeleteConfirm() {
    var id = document.getElementById('lh-cms-edit-id').value;
    if (!id) return;
    var title     = (document.getElementById('lh-cms-edit-title').value || 'this content').substring(0, 60);
    var ctype     = (document.getElementById('lh-cms-edit-type') || {}).value || 'article';
    var bar       = document.getElementById('lh-delete-confirm-bar');
    var msgEl     = document.getElementById('lh-delete-confirm-msg');
    if (!bar) return;

    // Build wording based on content type
    var typeLabel = { article: 'article', quiz: 'quiz', pearl: 'clinical pearl', presentation: 'presentation' }[ctype] || 'content';
    var consequence = '';
    if (ctype === 'quiz')    consequence = ' All quiz questions will be permanently removed.';
    else if (ctype === 'article' || ctype === 'pearl') consequence = ' Any quiz questions attached to it will also be removed.';
    // Presentation has no questions → no extra wording

    if (msgEl) msgEl.innerHTML = 'Delete the ' + typeLabel + ' <strong>"' + esc(title) + '"</strong>?' + consequence + ' This cannot be undone.';
    bar.classList.remove('hidden');
    bar.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  }

  function hideDeleteConfirm() {
    var bar = document.getElementById('lh-delete-confirm-bar');
    if (bar) bar.classList.add('hidden');
  }

  function confirmDelete() {
    var id = document.getElementById('lh-cms-edit-id').value;
    if (!id) return;
    hideDeleteConfirm();
    deleteJson('/api/admin/learning/content/' + id)
      .then(function(data) {
        if (data.success) {
          showToast('Content deleted', 'info');
          closeEditor();
          cms.refreshAll();
          loaded = false;
        } else showToast(data.error || 'Failed', 'error');
      });
  }

  // ── Presentation / Marp ──────────────────────────────────────
  function getMarpMarkdown() {
    var ta = document.getElementById('lh-marp-editor');
    return ta ? ta.value.trim() : '';
  }

  function getPresentationTitle() {
    var titleEl = document.getElementById('lh-cms-edit-title');
    return titleEl ? titleEl.value : 'presentation';
  }

  function addQuestionBlock(existingQ) {
    var container = document.getElementById('lh-cms-questions');
    if (!container) return;

    var block = document.createElement('div');
    block.className = 'lh-question-block';
    if (existingQ && existingQ.id) block.dataset.questionId = existingQ.id;

    var qNum = container.querySelectorAll('.lh-question-block').length + 1;
    block.innerHTML = renderQuestionBlockShell(existingQ, qNum);

    container.appendChild(block);

    // Set textarea values after insertion (can't use value="" attr on textarea)
    block.querySelector('.lh-q-text').value = existingQ ? existingQ.question_text || '' : '';
    block.querySelector('.lh-q-explanation').value = existingQ ? existingQ.explanation || '' : '';

    var optList = block.querySelector('.lh-options-list');
    if (existingQ && existingQ.options && existingQ.options.length > 0) {
      existingQ.options.forEach(function(opt) { addOptionRow(optList, opt); });
    } else if (existingQ && existingQ.question_type === 'true_false') {
      addOptionRow(optList, { option_text: 'True', is_correct: false, explanation: '' });
      addOptionRow(optList, { option_text: 'False', is_correct: false, explanation: '' });
    } else {
      // Add 4 blank MCQ options
      for (var i = 0; i < 4; i++) addOptionRow(optList, null);
    }
  }

  function addOptionRow(container, opt) {
    if (!container) return;
    var row = document.createElement('div');
    row.className = 'lh-option-row';
    row.innerHTML = renderOptionRowShell(opt);
    container.appendChild(row);
    // Set option text value after insertion (can't use value="" on nested input via innerHTML)
    row.querySelector('.lh-opt-text').value = opt ? opt.option_text || '' : '';
  }
