import { useState, useEffect, useRef, lazy, Suspense } from 'react'
import { useNavigate } from 'react-router-dom'
import { useAuth } from '../context/AuthContext'
import api from '../api/client'
import Dialog from '../components/Dialog'
import { useDialog } from '../hooks/useDialog'

const TeachChat = lazy(() => import('../components/TeachChat'))
const RichEditor = lazy(() => import('../components/RichEditor'))

/** Strip HTML tags for plain text display (truncated cards). */
function stripHtml(html) {
  if (!html) return ''
  return html.replace(/<[^>]+>/g, ' ').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/\s+/g, ' ').trim()
}

function QuestionStudyModal({ question, onClose, isFavorited, onToggleFavorite }) {
  const [answered, setAnswered] = useState(null)
  return (
    <>
      <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.55)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}
        onClick={e => e.target === e.currentTarget && onClose()}>
        <div style={{ background: 'var(--card-bg)', borderRadius: 'var(--card-radius)', padding: 24, maxWidth: 600, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: '0 20px 60px rgba(0,0,0,0.3)' }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
            <span style={{ fontSize: '0.75rem', fontWeight: 600, color: 'var(--text-muted)', textTransform: 'uppercase' }}>
              {question.quiz_title}{question.question_category_name ? ` · ${question.question_category_name}` : ''}
            </span>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              {onToggleFavorite && (
                <button onClick={() => onToggleFavorite(question.id)}
                  title={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
                  style={{ background: 'none', border: 'none', cursor: 'pointer', fontSize: '1.4rem', padding: 2, lineHeight: 1 }}>
                  {isFavorited ? '⭐' : '☆'}
                </button>
              )}
              <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontSize: '1.2rem' }}>✕</button>
            </div>
          </div>
          <div style={{ fontWeight: 600, fontSize: '0.95rem', lineHeight: 1.6, marginBottom: 16 }} dangerouslySetInnerHTML={{ __html: question.question_text }} />
          {question.image_path && (
            <div style={{ margin: '0 0 14px' }}>
              <img src={`/uploads/${question.image_path}`} alt="Question illustration"
                style={{ maxWidth: '100%', maxHeight: 280, borderRadius: 8, border: '1px solid var(--border)' }}
                onError={e => e.target.style.display = 'none'} />
            </div>
          )}
          {question.options && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 16 }}>
              {question.options.map((opt, i) => {
                const isSelected = answered === opt
                const hasAnswered = !!answered
                const isCorrectOpt = opt === question.correct_answer
                return (
                  <div key={i}
                    className={`option ${isSelected && !hasAnswered ? 'selected' : ''} ${hasAnswered && isCorrectOpt ? 'correct' : ''} ${hasAnswered && isSelected && !isCorrectOpt ? 'incorrect' : ''}`}
                    onClick={() => !hasAnswered && setAnswered(opt)}
                    style={{ cursor: hasAnswered ? 'default' : 'pointer' }}>
                    <span className="option-letter">{String.fromCharCode(65 + i)}</span>
                    <span style={{ flex: 1 }}>{opt}</span>
                    {hasAnswered && isCorrectOpt && <span style={{ marginLeft: 'auto', fontSize: '0.8rem', fontWeight: 700, color: 'var(--correct-fg)' }}>✓ {isSelected ? 'Your answer' : 'Correct'}</span>}
                    {hasAnswered && isSelected && !isCorrectOpt && <span style={{ marginLeft: 'auto', fontSize: '0.8rem', fontWeight: 700, color: 'var(--wrong-fg)' }}>✗ Wrong</span>}
                  </div>
                )
              })}
            </div>
          )}
          {answered && question.explanation && (
            <div className="explanation"><strong>Explanation:</strong><div style={{ marginTop: 8 }}>{question.explanation}</div></div>
          )}
          {answered && <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
            <button className="btn btn-secondary btn-sm" onClick={() => setAnswered(null)}>Try again</button>
            <button className="btn btn-secondary btn-sm" onClick={onClose}>Close</button>
          </div>}
        </div>
      </div>
      {/* AI Tutor — z-index above the modal */}
      <Suspense fallback={null}>
        <TeachChat question={question} elevated />
      </Suspense>
    </>
  )
}

function CreateQuizModal({ selectedIds, categories, onClose, onCreated }) {
  const [form, setForm] = useState({ title: '', mode: 'timed', time_limit_minutes: '', question_category_id: '' })
  const [error, setError] = useState('')
  const [loading, setLoading] = useState(false)
  const navigate = useNavigate()

  const submit = async () => {
    if (!form.title.trim()) return setError('Title is required')
    setLoading(true)
    try {
      if (form.question_category_id) {
        const res = await api.post(`/question-categories/${form.question_category_id}/create-quiz`, null, {
          params: {
            title: form.title,
            mode: form.mode,
            time_limit_minutes: form.time_limit_minutes ? parseInt(form.time_limit_minutes) : null,
          }
        })
        navigate(`/quizzes/${res.data.id}`)
      } else {
        const res = await api.post('/questions/from-bank', {
          title: form.title,
          question_ids: [...selectedIds],
          mode: form.mode,
          time_limit_minutes: form.time_limit_minutes ? parseInt(form.time_limit_minutes) : null,
        })
        navigate(`/quizzes/${res.data.id}`)
      }
    } catch (err) { setError(err.response?.data?.detail || 'Failed') }
    finally { setLoading(false) }
  }

  const fromCategory = !!form.question_category_id

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}>
      <div style={{ background: 'var(--card-bg)', borderRadius: 12, padding: 24, maxWidth: 420, width: '100%' }}>
        <h2 style={{ marginBottom: 16 }}>Create Quiz</h2>
        {error && <div className="alert alert-error">{error}</div>}
        <div className="form-group">
          <label>Source</label>
          <select value={form.question_category_id} onChange={e => setForm(f => ({ ...f, question_category_id: e.target.value }))}>
            <option value="">{selectedIds.size} selected question{selectedIds.size !== 1 ? 's' : ''}</option>
            {categories.map(c => <option key={c.id} value={c.id}>All from: {c.name} ({c.question_count} questions)</option>)}
          </select>
        </div>
        <div className="form-group">
          <label>Quiz Title</label>
          <input type="text" value={form.title} onChange={e => setForm(f => ({ ...f, title: e.target.value }))} placeholder="Enter title..." />
        </div>
        <div className="form-group">
          <label>Mode</label>
          <select value={form.mode} onChange={e => setForm(f => ({ ...f, mode: e.target.value }))}>
            <option value="timed">Timed (Exam)</option>
            <option value="learning">Learning (Study)</option>
          </select>
        </div>
        <div className="form-group">
          <label>Time Limit (minutes, optional)</label>
          <input type="number" value={form.time_limit_minutes} onChange={e => setForm(f => ({ ...f, time_limit_minutes: e.target.value }))} placeholder="Leave blank for no limit" min={1} />
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="btn btn-primary" onClick={submit} disabled={loading}>{loading ? 'Creating…' : 'Create Quiz'}</button>
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
        </div>
      </div>
    </div>
  )
}

function TagBrowser({ tags, selectedTagIds, toggleTag }) {
  const [search, setSearch] = useState({ subjects: '', diseases: '', keywords: '' })
  const sections = [
    { key: 'subjects', label: 'Subjects', color: '#8b5cf6', items: tags.subjects || [] },
    { key: 'diseases', label: 'Diseases', color: '#ef4444', items: tags.diseases || [] },
    { key: 'keywords', label: 'Keywords', color: '#0ea5e9', items: tags.keywords || [] },
  ]
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 10, marginTop: 10 }}>
      {sections.map(sec => {
        if (sec.items.length === 0) return null
        const q = search[sec.key].toLowerCase()
        const filtered = q ? sec.items.filter(t => t.name.toLowerCase().includes(q)) : sec.items
        return (
          <div key={sec.key} style={{ background: 'var(--bg)', borderRadius: 8, padding: 10, border: '1px solid var(--border)' }}>
            <div style={{ fontSize: '0.75rem', fontWeight: 700, color: sec.color, textTransform: 'uppercase', marginBottom: 6 }}>
              {sec.label} ({sec.items.length})
            </div>
            <input type="text" placeholder={`Search ${sec.label.toLowerCase()}...`}
              value={search[sec.key]}
              onChange={e => setSearch(s => ({ ...s, [sec.key]: e.target.value }))}
              style={{ width: '100%', padding: '5px 8px', border: '1px solid var(--border)', borderRadius: 6, fontSize: '0.78rem', background: 'var(--input-bg)', color: 'var(--text)', marginBottom: 6, boxSizing: 'border-box' }} />
            <div style={{ maxHeight: 180, overflowY: 'auto' }}>
              {filtered.map(tag => {
                const selected = selectedTagIds.includes(tag.id)
                return (
                  <button key={tag.id} onClick={() => toggleTag(tag.id)}
                    style={{
                      display: 'block', width: '100%', textAlign: 'left',
                      background: selected ? sec.color : 'transparent',
                      color: selected ? '#fff' : 'var(--text)',
                      border: 'none', borderRadius: 4, padding: '3px 8px',
                      fontSize: '0.78rem', cursor: 'pointer', marginBottom: 1,
                    }}>
                    {tag.name} <span style={{ opacity: 0.6 }}>({tag.count})</span>
                  </button>
                )
              })}
              {filtered.length === 0 && <div style={{ fontSize: '0.75rem', color: 'var(--text-muted)', padding: 4 }}>No matches</div>}
            </div>
          </div>
        )
      })}
    </div>
  )
}

const LETTERS = ['A','B','C','D','E','F']

function QuestionEditModal({ question, categories, onSaved, onClose }) {
  const [form, setForm] = useState({
    question_text: question.question_text,
    question_type: question.question_type,
    options: question.options ? [...question.options] : [],
    correct_answer: question.correct_answer,
    explanation: question.explanation || '',
    question_category_id: question.question_category_id || '',
  })
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')

  const setOption = (i, val) => {
    const updated = [...form.options]
    const wasCorrect = form.options[i] === form.correct_answer
    updated[i] = val
    setForm(f => ({ ...f, options: updated, correct_answer: wasCorrect ? val : f.correct_answer }))
  }

  const save = async () => {
    if (!form.question_text.trim()) return setError('Question text is required')
    if (form.options.length > 0 && !form.options.includes(form.correct_answer))
      return setError('Correct answer must match one of the options')
    setSaving(true); setError('')
    try {
      const payload = { ...form, question_category_id: form.question_category_id ? parseInt(form.question_category_id) : null }
      const res = await api.patch(`/questions/${question.id}`, payload)
      onSaved({ ...question, ...res.data,
        question_category_name: categories.find(c => c.id === payload.question_category_id)?.name || null })
      onClose()
    } catch (err) { setError(err.response?.data?.detail || 'Save failed') }
    finally { setSaving(false) }
  }

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.55)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}
      onClick={e => e.target === e.currentTarget && onClose()}>
      <div style={{ background: 'var(--card-bg)', borderRadius: 12, padding: 24, maxWidth: 640, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: '0 20px 60px rgba(0,0,0,0.3)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
          <h2 style={{ fontSize: '1.1rem' }}>Edit Question</h2>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontSize: '1.2rem' }}>✕</button>
        </div>
        <p style={{ fontSize: '0.78rem', color: 'var(--text-muted)', marginBottom: 16 }}>
          This question is shared — changes apply to all quizzes using it.
        </p>
        {error && <div className="alert alert-error">{error}</div>}
        <div className="form-group">
          <label>Question Text</label>
          <textarea rows={4} value={form.question_text} onChange={e => setForm(f => ({ ...f, question_text: e.target.value }))}
            style={{ fontFamily: 'inherit' }} />
        </div>
        {form.options.length > 0 && (
          <div className="form-group">
            <label>Options — select the correct one</label>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {form.options.map((opt, i) => (
                <div key={i} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                  <input type="radio" name="correct" checked={form.correct_answer === opt}
                    onChange={() => setForm(f => ({ ...f, correct_answer: opt }))}
                    style={{ width: 'auto', accentColor: 'var(--primary)' }} />
                  <span style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 24, height: 24, borderRadius: '50%', flexShrink: 0, fontSize: '0.72rem', fontWeight: 700,
                    background: form.correct_answer === opt ? 'var(--correct-fg)' : 'var(--border)',
                    color: form.correct_answer === opt ? 'white' : 'var(--text-muted)' }}>{LETTERS[i]}</span>
                  <input type="text" value={opt} onChange={e => setOption(i, e.target.value)}
                    style={{ flex: 1, padding: '7px 12px', border: `1.5px solid ${form.correct_answer === opt ? 'var(--correct-bd)' : 'var(--border)'}`, borderRadius: 6, fontSize: '0.875rem', background: form.correct_answer === opt ? 'var(--correct-bg)' : 'var(--input-bg)', color: 'var(--text)', fontFamily: 'inherit' }} />
                </div>
              ))}
            </div>
          </div>
        )}
        <div className="form-group">
          <label>Question Category</label>
          <select value={form.question_category_id} onChange={e => setForm(f => ({ ...f, question_category_id: e.target.value }))}>
            <option value="">— Uncategorized —</option>
            {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </div>
        <div className="form-group">
          <label>Explanation</label>
          <textarea rows={6} value={form.explanation} onChange={e => setForm(f => ({ ...f, explanation: e.target.value }))}
            style={{ fontFamily: 'inherit' }} />
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="btn btn-primary" onClick={save} disabled={saving}>{saving ? 'Saving…' : 'Save Changes'}</button>
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
        </div>
      </div>
    </div>
  )
}

function CreateQuestionModal({ categories, onCreated, onClose }) {
  const LETTERS = ['A','B','C','D','E','F','G','H']
  const [form, setForm] = useState({ question_text: '', question_type: 'mcq', options: ['', '', '', ''], correct_answer: '', correctIndex: -1, explanation: '', question_category_id: '', image_path: '' })
  const [saving, setSaving] = useState(false)
  const [error, setError] = useState('')
  const [imageTab, setImageTab] = useState('upload') // 'upload' | 'bank'
  const [imageBank, setImageBank] = useState([])
  const [uploadingImage, setUploadingImage] = useState(false)

  const setOption = (i, val) => {
    const updated = [...form.options]
    updated[i] = val
    setForm(f => ({ ...f, options: updated, correct_answer: f.correctIndex === i ? val : f.correct_answer }))
  }

  const setCorrectIndex = (i) => {
    setForm(f => ({ ...f, correctIndex: i, correct_answer: f.options[i] }))
  }

  const removeOption = (i) => {
    setForm(f => {
      const opts = f.options.filter((_, idx) => idx !== i)
      let ci = f.correctIndex
      if (ci === i) ci = -1
      else if (ci > i) ci--
      return { ...f, options: opts, correctIndex: ci, correct_answer: ci >= 0 ? opts[ci] : '' }
    })
  }

  const loadImageBank = async () => {
    try {
      const res = await api.get('/questions/images')
      setImageBank(res.data)
    } catch {}
  }

  const handleImageUpload = async (e) => {
    const file = e.target.files?.[0]
    if (!file) return
    setUploadingImage(true)
    try {
      const fd = new FormData()
      fd.append('file', file)
      const res = await api.post('/questions/upload-image', fd)
      setForm(f => ({ ...f, image_path: res.data.image_path }))
    } catch (err) {
      setError(err.response?.data?.detail || 'Image upload failed')
    } finally {
      setUploadingImage(false)
    }
  }

  const save = async () => {
    if (!form.question_text.trim()) return setError('Question text is required')
    const validOpts = form.options.filter(o => o.trim())
    if (validOpts.length < 2) return setError('At least 2 options are required')
    if (form.correctIndex < 0 || !form.correct_answer) return setError('Select the correct answer')
    setSaving(true); setError('')
    try {
      const payload = {
        question_text: form.question_text,
        question_type: form.question_type,
        options: validOpts,
        correct_answer: form.correct_answer,
        explanation: form.explanation || null,
        question_category_id: form.question_category_id ? parseInt(form.question_category_id) : null,
        image_path: form.image_path || null,
      }
      const res = await api.post('/questions/create', payload)
      onCreated(res.data)
      onClose()
    } catch (err) { setError(err.response?.data?.detail || 'Failed to create question') }
    finally { setSaving(false) }
  }

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}>
      <div style={{ background: 'var(--card-bg)', borderRadius: 12, padding: 28, maxWidth: 720, width: '100%', maxHeight: '90vh', overflowY: 'auto', boxShadow: '0 20px 60px rgba(0,0,0,0.3)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }}>
          <h2 style={{ fontSize: '1.15rem', margin: 0 }}>Create Question</h2>
          <button onClick={onClose} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontSize: '1.2rem' }}>✕</button>
        </div>
        {error && <div className="alert alert-error" style={{ marginBottom: 14 }}>{error}</div>}

        <div className="form-group">
          <label style={{ fontWeight: 600, fontSize: '0.88rem', marginBottom: 6, display: 'block' }}>Question Text</label>
          <Suspense fallback={<textarea value={form.question_text} onChange={e => setForm(f => ({ ...f, question_text: e.target.value }))} rows={4}
            placeholder="Loading editor..." style={{ width: '100%', padding: 12, border: '1px solid var(--border)', borderRadius: 8, background: 'var(--input-bg)', color: 'var(--text)', fontSize: '0.9rem', resize: 'vertical', boxSizing: 'border-box' }} />}>
            <RichEditor value={form.question_text} onChange={(v) => setForm(f => ({ ...f, question_text: v }))} height={180} placeholder="Write the question..." />
          </Suspense>
        </div>

        <div className="form-group">
          <label style={{ fontWeight: 600, fontSize: '0.88rem', marginBottom: 6, display: 'block' }}>Category</label>
          <select value={form.question_category_id} onChange={e => setForm(f => ({ ...f, question_category_id: e.target.value }))}
            style={{ width: '100%', padding: '10px 14px', border: '1px solid var(--border)', borderRadius: 8, background: 'var(--input-bg)', color: 'var(--text)', fontSize: '0.9rem' }}>
            <option value="">None</option>
            {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
        </div>

        {/* Image */}
        <div className="form-group">
          <label style={{ fontWeight: 600, fontSize: '0.88rem', marginBottom: 6, display: 'block' }}>Image (optional)</label>
          {form.image_path ? (
            <div style={{ position: 'relative', display: 'inline-block', marginBottom: 8 }}>
              <img src={`/uploads/${form.image_path}`} alt="Question"
                style={{ maxWidth: '100%', maxHeight: 180, borderRadius: 8, border: '1px solid var(--border)' }} />
              <button onClick={() => setForm(f => ({ ...f, image_path: '' }))}
                style={{ position: 'absolute', top: 4, right: 4, background: 'rgba(0,0,0,0.6)', color: '#fff', border: 'none', borderRadius: '50%', width: 24, height: 24, cursor: 'pointer', fontSize: '0.8rem', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>✕</button>
            </div>
          ) : (
            <div>
              <div style={{ display: 'flex', gap: 6, marginBottom: 8 }}>
                <button className={`btn btn-sm ${imageTab === 'upload' ? 'btn-primary' : 'btn-secondary'}`}
                  onClick={() => setImageTab('upload')} style={{ fontSize: '0.78rem' }}>Upload New</button>
                <button className={`btn btn-sm ${imageTab === 'bank' ? 'btn-primary' : 'btn-secondary'}`}
                  onClick={() => { setImageTab('bank'); loadImageBank() }} style={{ fontSize: '0.78rem' }}>Image Bank</button>
              </div>
              {imageTab === 'upload' && (
                <div>
                  <input type="file" accept="image/*" onChange={handleImageUpload} disabled={uploadingImage}
                    style={{ fontSize: '0.85rem' }} />
                  {uploadingImage && <span style={{ fontSize: '0.78rem', color: 'var(--text-muted)', marginLeft: 8 }}>Uploading...</span>}
                </div>
              )}
              {imageTab === 'bank' && (
                <div style={{ maxHeight: 200, overflowY: 'auto', display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(100px, 1fr))', gap: 8, padding: 4 }}>
                  {imageBank.length === 0 && <div style={{ fontSize: '0.78rem', color: 'var(--text-muted)', gridColumn: '1/-1' }}>No images in bank yet. Upload one first.</div>}
                  {imageBank.map((img, i) => (
                    <div key={i} onClick={() => setForm(f => ({ ...f, image_path: img.image_path }))}
                      style={{ cursor: 'pointer', border: '2px solid var(--border)', borderRadius: 8, overflow: 'hidden', aspectRatio: '1', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'var(--bg)' }}
                      onMouseEnter={e => e.currentTarget.style.borderColor = 'var(--primary)'} onMouseLeave={e => e.currentTarget.style.borderColor = 'var(--border)'}>
                      <img src={img.url} alt="" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'cover' }}
                        onError={e => e.target.style.display = 'none'} />
                    </div>
                  ))}
                </div>
              )}
            </div>
          )}
        </div>

        <div className="form-group">
          <label style={{ fontWeight: 600, fontSize: '0.88rem', marginBottom: 6, display: 'block' }}>
            Options — click the letter to mark as correct
          </label>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {form.options.map((opt, i) => {
              const isCorrect = form.correctIndex === i
              return (
                <div key={i} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                  <button onClick={() => setCorrectIndex(i)} title={isCorrect ? 'Correct answer' : 'Click to mark as correct'}
                    style={{
                      display: 'flex', alignItems: 'center', justifyContent: 'center', width: 32, height: 32,
                      borderRadius: '50%', flexShrink: 0, fontSize: '0.8rem', fontWeight: 700, cursor: 'pointer',
                      border: isCorrect ? '2px solid var(--correct-fg)' : '2px solid var(--border)',
                      background: isCorrect ? 'var(--correct-fg)' : 'transparent',
                      color: isCorrect ? 'white' : 'var(--text-muted)',
                      transition: 'all 0.15s',
                    }}>
                    {LETTERS[i]}
                  </button>
                  <input value={opt} onChange={e => setOption(i, e.target.value)}
                    placeholder={`Option ${LETTERS[i]}`}
                    style={{
                      flex: 1, padding: '10px 14px',
                      border: `1.5px solid ${isCorrect ? 'var(--correct-bd)' : 'var(--border)'}`,
                      borderRadius: 8, background: isCorrect ? 'var(--correct-bg)' : 'var(--input-bg)',
                      color: 'var(--text)', fontSize: '0.9rem', fontFamily: 'inherit',
                    }} />
                  {form.options.length > 2 && (
                    <button onClick={() => removeOption(i)} title="Remove option"
                      style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontSize: '1.1rem', padding: '4px 6px' }}
                      onMouseEnter={e => e.currentTarget.style.color = '#ef4444'} onMouseLeave={e => e.currentTarget.style.color = 'var(--text-muted)'}>
                      ✕
                    </button>
                  )}
                </div>
              )
            })}
          </div>
          {form.options.length < 8 && (
            <button className="btn btn-sm btn-secondary" style={{ marginTop: 8 }}
              onClick={() => setForm(f => ({ ...f, options: [...f.options, ''] }))}>+ Add option</button>
          )}
        </div>

        <div className="form-group">
          <label style={{ fontWeight: 600, fontSize: '0.88rem', marginBottom: 6, display: 'block' }}>Explanation (optional)</label>
          <Suspense fallback={<textarea value={form.explanation} onChange={e => setForm(f => ({ ...f, explanation: e.target.value }))} rows={3}
            placeholder="Loading editor..." style={{ width: '100%', padding: 12, border: '1px solid var(--border)', borderRadius: 8, background: 'var(--input-bg)', color: 'var(--text)', fontSize: '0.9rem', resize: 'vertical', boxSizing: 'border-box' }} />}>
            <RichEditor value={form.explanation} onChange={(v) => setForm(f => ({ ...f, explanation: v }))} height={150} placeholder="Explain why this is the correct answer..." />
          </Suspense>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 8 }}>
          <button className="btn btn-primary" onClick={save} disabled={saving}>
            {saving ? 'Creating...' : 'Create Question'}
          </button>
          <button className="btn btn-secondary" onClick={onClose}>Cancel</button>
        </div>
      </div>
    </div>
  )
}

export default function QuestionBankPage() {
  const { dialogProps, openAlert } = useDialog()
  const [questions, setQuestions] = useState([])
  const [total, setTotal] = useState(0)
  const [loading, setLoading] = useState(false)
  const [categories, setCategories] = useState([])
  const [searchQuery, setSearchQuery] = useState('')
  const [searchMode, setSearchMode] = useState('hybrid')
  const [filterCatIds, setFilterCatIds] = useState([])
  const [showUncategorized, setShowUncategorized] = useState(false)
  const [showFavorites, setShowFavorites] = useState(false)
  const [showMyQuestions, setShowMyQuestions] = useState(false)
  const [favorites, setFavorites] = useState([])
  const [offset, setOffset] = useState(0)
  const [studyQuestion, setStudyQuestion] = useState(null)
  const [editQuestion, setEditQuestion] = useState(null)
  const [selectedIds, setSelectedIds] = useState(new Set())
  const [showCreateQuiz, setShowCreateQuiz] = useState(false)
  const [newCatName, setNewCatName] = useState('')
  const [showCatForm, setShowCatForm] = useState(false)
  const [assignCatId, setAssignCatId] = useState('')
  const [bulkError, setBulkError] = useState('')
  const [pageSize, setPageSize] = useState(50)
  const [tags, setTags] = useState({ subjects: [], diseases: [], keywords: [] })
  const [selectedTagIds, setSelectedTagIds] = useState([])
  const [showTags, setShowTags] = useState(false)
  const [classifyJobId, setClassifyJobId] = useState(null)
  const [classifyStatus, setClassifyStatus] = useState(null)
  const [classifySteps, setClassifySteps] = useState([])
  const [showCreateQuestion, setShowCreateQuestion] = useState(false)
  const [showImport, setShowImport] = useState(false)
  const [importFile, setImportFile] = useState(null)
  const [importing, setImporting] = useState(false)
  const [importResult, setImportResult] = useState(null)
  const [qtiImporting, setQtiImporting] = useState(false)
  const [qtiExporting, setQtiExporting] = useState(false)
  const debounceRef = useRef(null)
  const classifyPollRef = useRef(null)
  const { user } = useAuth()
  const isModerator = user?.role === 'admin' || user?.role === 'moderator'
  const LIMIT = pageSize

  const loadTags = () => {
    api.get('/tags').then(res => setTags(res.data)).catch(() => {})
  }

  useEffect(() => {
    api.get('/question-categories/').then(res => setCategories(res.data)).catch(() => {})
    api.get('/favorites').then(res => setFavorites(res.data)).catch(() => {})
    loadTags()
  }, [])

  const loadQuestions = async (query = searchQuery, off = 0, catIds = filterCatIds, uncatOnly = showUncategorized, favOnly = showFavorites, mode = searchMode, size = pageSize, tagIds = selectedTagIds) => {
    setLoading(true)
    try {
      const params = { limit: size === 'all' ? 5000 : size, offset: off, search_mode: mode }
      if (query.trim()) params.q = query.trim()
      if (catIds.length > 0) params.category_ids = catIds.join(',')
      if (uncatOnly) params.uncategorized = true
      if (favOnly) params.favorites_only = true
      if (showMyQuestions) params.my_questions = true
      if (tagIds.length > 0) params.tag_ids = tagIds.join(',')
      const res = await api.get('/questions/bank', { params })
      setQuestions(off === 0 ? res.data.questions : prev => [...prev, ...res.data.questions])
      setTotal(res.data.total)
      setOffset(off)
    } catch { } finally { setLoading(false) }
  }

  const tagIdsKey = selectedTagIds.join(',')
  const catIdsKey = filterCatIds.join(',')
  useEffect(() => {
    clearTimeout(debounceRef.current)
    debounceRef.current = setTimeout(() => loadQuestions(searchQuery, 0, filterCatIds, showUncategorized, showFavorites, searchMode, pageSize, selectedTagIds), 300)
    return () => clearTimeout(debounceRef.current)
  }, [searchQuery, catIdsKey, showUncategorized, showFavorites, showMyQuestions, searchMode, pageSize, tagIdsKey])

  const toggleTag = (tagId) => {
    setSelectedTagIds(prev => {
      const n = prev.includes(tagId) ? prev.filter(id => id !== tagId) : [...prev, tagId]
      return n
    })
  }

  const startClassification = async () => {
    try {
      const res = await api.post('/tags/classify')
      setClassifyJobId(res.data.job_id)
      setClassifyStatus('running')
      setClassifySteps([])
      // Start polling
      if (classifyPollRef.current) clearInterval(classifyPollRef.current)
      classifyPollRef.current = setInterval(async () => {
        try {
          const s = await api.get(`/tags/status/${res.data.job_id}`)
          setClassifyStatus(s.data.status)
          setClassifySteps(s.data.steps || [])
          if (s.data.status === 'completed' || s.data.status === 'failed') {
            clearInterval(classifyPollRef.current)
            classifyPollRef.current = null
            if (s.data.status === 'completed') loadTags()
          }
        } catch { }
      }, 2000)
    } catch (err) {
      await openAlert(err.response?.data?.detail || 'Failed to start classification', { title: 'Error' })
    }
  }

  useEffect(() => {
    return () => { if (classifyPollRef.current) clearInterval(classifyPollRef.current) }
  }, [])

  const toggleSelect = (id) => setSelectedIds(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n })

  const selectAll = async () => {
    // Fetch ALL matching IDs from server (not just loaded page)
    try {
      const params = {}
      if (searchQuery.trim()) params.q = searchQuery.trim()
      if (filterCatIds.length > 0) params.category_ids = filterCatIds.join(',')
      if (showUncategorized) params.uncategorized = true
      if (showFavorites) params.favorites_only = true
      if (selectedTagIds.length > 0) params.tag_ids = selectedTagIds.join(',')
      const res = await api.get('/questions/bank/ids', { params })
      setSelectedIds(new Set(res.data))
    } catch {
      // Fallback to loaded questions
      setSelectedIds(new Set(questions.map(q => q.id)))
    }
  }

  const clearSelection = () => setSelectedIds(new Set())

  const bulkAssignCategory = async () => {
    if (!assignCatId) return
    setBulkError('')
    const catIdVal = assignCatId === 'remove' ? null : parseInt(assignCatId)
    try {
      await api.post('/questions/bulk-category', {
        question_ids: [...selectedIds],
        category_id: catIdVal,
      })
      const catName = catIdVal ? categories.find(c => c.id === catIdVal)?.name ?? null : null
      setQuestions(prev => prev.map(q => selectedIds.has(q.id)
        ? { ...q, question_category_id: catIdVal, question_category_name: catName }
        : q))
      clearSelection()
      setAssignCatId('')
      api.get('/question-categories/').then(res => setCategories(res.data))
    } catch (err) {
      setBulkError(err.response?.data?.detail || 'Failed to assign category')
    }
  }

  const addCategory = async () => {
    if (!newCatName.trim()) return
    try {
      const res = await api.post('/question-categories/', { name: newCatName.trim() })
      setCategories(prev => [...prev, res.data])
      setNewCatName(''); setShowCatForm(false)
    } catch (err) { await openAlert(err.response?.data?.detail || 'Failed', { title: 'Error' }) }
  }

  const [deletingCatId, setDeletingCatId] = useState(null)
  const [moveToCatId, setMoveToCatId] = useState('')

  const confirmDeleteCategory = async () => {
    const catId = deletingCatId
    const moveTo = moveToCatId ? parseInt(moveToCatId) : undefined
    setDeletingCatId(null); setMoveToCatId('')
    try {
      await api.delete(`/question-categories/${catId}`, { params: moveTo ? { move_to: moveTo } : {} })
      setCategories(prev => prev.filter(c => c.id !== catId))
      setFilterCatIds(prev => prev.filter(c => c !== catId))
      loadQuestions(searchQuery, 0, filterCatIds.filter(c => c !== catId), showUncategorized, showFavorites)
    } catch { }
  }

  const deleteCategory = (catId) => {
    setDeletingCatId(catId)
    setMoveToCatId('')
  }

  const handleImport = async () => {
    if (!importFile) return
    setImporting(true)
    setImportResult(null)
    try {
      const fd = new FormData()
      fd.append('file', importFile)
      const res = await api.post('/questions/import/upload', fd)
      setImportResult(res.data)
      if (res.data.imported > 0) {
        loadQuestions()
        api.get('/question-categories/').then(r => setCategories(r.data))
      }
    } catch (err) {
      setImportResult({ error: err.response?.data?.detail || 'Import failed' })
    } finally {
      setImporting(false)
    }
  }

  const handleQtiImport = () => {
    if (qtiImporting) return
    const input = document.createElement('input')
    input.type = 'file'
    input.accept = '.xml'
    input.onchange = async (e) => {
      const file = e.target.files?.[0]
      if (!file) return
      setQtiImporting(true)
      try {
        const fd = new FormData()
        fd.append('file', file)
        const res = await api.post('/questions/import/qti', fd)
        const errors = res.data.errors?.length ? ` ${res.data.errors.length} error(s).` : ''
        openAlert(`Imported ${res.data.imported} of ${res.data.total_items} questions.${errors}`, { title: 'QTI Import Complete' })
        loadQuestions()
      } catch (err) {
        openAlert(err.response?.data?.detail || 'QTI import failed', { title: 'Import Failed' })
      } finally {
        setQtiImporting(false)
      }
    }
    input.click()
  }

  const handleQtiExport = async () => {
    setQtiExporting(true)
    try {
      const ids = selectedIds.size > 0 ? [...selectedIds].join(',') : ''
      const res = await api.get(`/questions/export/qti${ids ? `?question_ids=${ids}` : ''}`, { responseType: 'blob' })
      const url = URL.createObjectURL(res.data)
      const a = document.createElement('a')
      a.href = url
      a.download = 'questions_qti.xml'
      a.click()
      URL.revokeObjectURL(url)
    } catch (err) {
      openAlert(err.response?.data?.detail || 'QTI export failed', { title: 'Export Failed' })
    } finally {
      setQtiExporting(false)
    }
  }

  const toggleFavorite = async (questionId) => {
    const isFavorited = favorites.includes(questionId)
    try {
      if (isFavorited) {
        await api.delete(`/favorites/${questionId}`)
        setFavorites(prev => prev.filter(id => id !== questionId))
      } else {
        await api.post('/favorites', { question_id: questionId })
        setFavorites(prev => [...prev, questionId])
      }
    } catch (err) {
      await openAlert(err.response?.data?.detail || 'Failed to update favorite', { title: 'Error' })
    }
  }

  return (
    <div>
      <Dialog {...dialogProps} />
      {/* Delete category dialog */}
      {deletingCatId && (() => {
        const cat = categories.find(c => c.id === deletingCatId)
        const others = categories.filter(c => c.id !== deletingCatId)
        return (
          <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}>
            <div style={{ background: 'var(--card-bg)', borderRadius: 12, padding: 24, maxWidth: 400, width: '100%' }}>
              <h2 style={{ marginBottom: 12, fontSize: '1.1rem' }}>Delete "{cat?.name}"?</h2>
              {cat?.question_count > 0 && (
                <div className="form-group">
                  <label>Move {cat.question_count} questions to:</label>
                  <select value={moveToCatId} onChange={e => setMoveToCatId(e.target.value)}>
                    <option value="">Leave uncategorized</option>
                    {others.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                  </select>
                </div>
              )}
              <div style={{ display: 'flex', gap: 8, marginTop: 16 }}>
                <button className="btn btn-danger" onClick={confirmDeleteCategory}>Delete category</button>
                <button className="btn btn-secondary" onClick={() => { setDeletingCatId(null); setMoveToCatId('') }}>Cancel</button>
              </div>
            </div>
          </div>
        )
      })()}

      {studyQuestion && <QuestionStudyModal question={studyQuestion} onClose={() => setStudyQuestion(null)}
        isFavorited={favorites.includes(studyQuestion.id)} onToggleFavorite={toggleFavorite} />}
      {editQuestion && <QuestionEditModal question={editQuestion} categories={categories}
        onSaved={updated => setQuestions(prev => prev.map(q => q.id === updated.id ? updated : q))}
        onClose={() => setEditQuestion(null)} />}
      {showCreateQuiz && <CreateQuizModal selectedIds={selectedIds} categories={categories} onClose={() => setShowCreateQuiz(false)} onCreated={() => {}} />}
      {showCreateQuestion && <CreateQuestionModal categories={categories} onCreated={(q) => { setQuestions(prev => [q, ...prev]); setTotal(t => t + 1) }} onClose={() => setShowCreateQuestion(false)} />}

      {/* Import CSV/Excel Modal */}
      {showImport && (
        <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', zIndex: 1000, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 16 }}>
          <div style={{ background: 'var(--card-bg)', borderRadius: 12, padding: 28, maxWidth: 520, width: '100%', boxShadow: '0 20px 60px rgba(0,0,0,0.3)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
              <h2 style={{ fontSize: '1.1rem', margin: 0 }}>Import Questions</h2>
              <button onClick={() => setShowImport(false)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text-muted)', fontSize: '1.2rem' }}>✕</button>
            </div>
            <p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: 14, lineHeight: 1.5 }}>
              Upload a CSV or Excel (.xlsx) file with columns: <strong>question_text</strong>, <strong>option_a</strong> through <strong>option_e</strong>, <strong>correct_answer</strong> (A/B/C/D/E), <strong>explanation</strong>, <strong>category</strong>.
            </p>
            <a href="/api/questions/import/sample" download style={{ fontSize: '0.85rem', color: 'var(--primary)', marginBottom: 14, display: 'inline-block' }}>
              Download sample CSV template
            </a>
            <div style={{ marginTop: 12, marginBottom: 14 }}>
              <input type="file" accept=".csv,.xlsx,.xls" onChange={e => { setImportFile(e.target.files[0]); setImportResult(null) }}
                style={{ fontSize: '0.88rem' }} />
            </div>
            {importResult && !importResult.error && (
              <div className="alert" style={{ background: 'var(--correct-bg)', border: '1px solid var(--correct-bd)', marginBottom: 12, fontSize: '0.85rem' }}>
                Imported <strong>{importResult.imported}</strong> of {importResult.total_rows} questions.
                {importResult.errors?.length > 0 && (
                  <div style={{ marginTop: 6, fontSize: '0.78rem', color: 'var(--text-muted)' }}>
                    {importResult.errors.map((e, i) => <div key={i}>{e}</div>)}
                  </div>
                )}
              </div>
            )}
            {importResult?.error && (
              <div className="alert alert-error" style={{ marginBottom: 12, fontSize: '0.85rem' }}>{importResult.error}</div>
            )}
            <div style={{ display: 'flex', gap: 8 }}>
              <button className="btn btn-primary" onClick={handleImport} disabled={!importFile || importing}>
                {importing ? 'Importing...' : 'Upload & Import'}
              </button>
              <button className="btn btn-secondary" onClick={() => setShowImport(false)}>Close</button>
            </div>
          </div>
        </div>
      )}

      {/* Header */}
      <div className="card" style={{ marginBottom: 16 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', flexWrap: 'wrap', gap: 12 }}>
          <div>
            <h2 style={{ marginBottom: 4 }}>Question Bank</h2>
            <p style={{ color: 'var(--text-muted)', fontSize: '0.875rem' }}>{total} questions total</p>
          </div>
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
            {selectedIds.size > 0 && (
              <button className="btn btn-primary btn-sm" onClick={() => setShowCreateQuiz(true)}>
                Create Quiz ({selectedIds.size} selected)
              </button>
            )}
            <button className="btn btn-secondary btn-sm" onClick={() => setShowCreateQuestion(true)}>+ Question</button>
            <button className="btn btn-secondary btn-sm" onClick={() => { setShowImport(true); setImportFile(null); setImportResult(null) }}>Import CSV/Excel</button>
            <button className="btn btn-secondary btn-sm" onClick={handleQtiImport} disabled={qtiImporting}>
              {qtiImporting ? 'Importing QTI...' : 'Import QTI'}
            </button>
            <button className="btn btn-secondary btn-sm" onClick={handleQtiExport} disabled={qtiExporting}>
              {qtiExporting ? 'Exporting QTI...' : `Export QTI${selectedIds.size > 0 ? ` (${selectedIds.size})` : ''}`}
            </button>
            {isModerator && <button className="btn btn-secondary btn-sm" onClick={() => setShowCatForm(v => !v)}>+ Category</button>}
          </div>
        </div>

        {showCatForm && (
          <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>
            <input type="text" value={newCatName} onChange={e => setNewCatName(e.target.value)} placeholder="New category name..."
              onKeyDown={e => e.key === 'Enter' && addCategory()}
              style={{ flex: 1, padding: '7px 12px', border: '1px solid var(--border)', borderRadius: 8, fontSize: '0.875rem', background: 'var(--input-bg)', color: 'var(--text)' }} />
            <button className="btn btn-primary btn-sm" onClick={addCategory}>Add</button>
            <button className="btn btn-secondary btn-sm" onClick={() => { setShowCatForm(false); setNewCatName('') }}>Cancel</button>
          </div>
        )}
      </div>

      {/* Category filter chips */}
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 12, paddingBottom: 12, borderBottom: '1px solid var(--border)' }}>
        <span style={{ fontSize: '0.72rem', fontWeight: 700, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: '0.04em', alignSelf: 'center', marginRight: 4 }}>Filter:</span>
        <button className={`btn btn-sm ${filterCatIds.length === 0 && !showUncategorized && !showFavorites ? 'btn-primary' : 'btn-secondary'}`}
          onClick={() => { setFilterCatIds([]); setShowUncategorized(false); setShowFavorites(false) }}>All ({total})</button>
        <button className={`btn btn-sm ${showFavorites ? 'btn-primary' : 'btn-secondary'}`}
          onClick={() => { setShowFavorites(v => !v); setFilterCatIds([]); setShowUncategorized(false) }}>⭐ Favorites ({favorites.length})</button>
        <button className={`btn btn-sm ${showMyQuestions ? 'btn-primary' : 'btn-secondary'}`}
          onClick={() => { setShowMyQuestions(v => !v); setFilterCatIds([]); setShowUncategorized(false); setShowFavorites(false) }}>My Questions</button>
        <button className={`btn btn-sm ${showUncategorized ? 'btn-primary' : 'btn-secondary'}`}
          onClick={() => { setShowUncategorized(v => !v); setFilterCatIds([]); setShowFavorites(false); setShowMyQuestions(false) }}>Uncategorized</button>
        {categories.map(cat => {
          const isActive = filterCatIds.includes(cat.id)
          return (
            <div key={cat.id} style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
              <button className={`btn btn-sm ${isActive ? 'btn-primary' : 'btn-secondary'}`}
                onClick={() => { setFilterCatIds(prev => prev.includes(cat.id) ? prev.filter(c => c !== cat.id) : [...prev, cat.id]); setShowUncategorized(false); setShowFavorites(false) }}>
                {cat.name} <span style={{ opacity: 0.65 }}>({cat.question_count})</span>
              </button>
              {isModerator && <button onClick={() => deleteCategory(cat.id)}
                style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#cbd5e1', fontSize: '0.72rem', padding: '2px 3px', lineHeight: 1 }}
                onMouseEnter={e => e.currentTarget.style.color = '#ef4444'} onMouseLeave={e => e.currentTarget.style.color = '#cbd5e1'}>✕</button>}
            </div>
          )
        })}
        {/* Active tag chips — shown inline with categories */}
        {selectedTagIds.map(tid => {
          const allTags = [...(tags.subjects || []), ...(tags.diseases || []), ...(tags.keywords || [])]
          const tag = allTags.find(t => t.id === tid)
          if (!tag) return null
          const color = (tags.subjects || []).find(t => t.id === tid) ? '#8b5cf6' : (tags.diseases || []).find(t => t.id === tid) ? '#ef4444' : '#0ea5e9'
          return (
            <button key={`tag-${tid}`} onClick={() => toggleTag(tid)}
              style={{ background: color, color: '#fff', border: 'none', fontSize: '0.72rem', padding: '3px 10px', borderRadius: 12, cursor: 'pointer', fontWeight: 600 }}>
              {tag.name} ✕
            </button>
          )
        })}
        {selectedTagIds.length > 0 && (
          <button onClick={() => setSelectedTagIds([])}
            style={{ background: 'none', border: 'none', fontSize: '0.72rem', color: 'var(--text-muted)', cursor: 'pointer', textDecoration: 'underline' }}>
            Clear tags
          </button>
        )}
      </div>

      {/* Tag browser — collapsible */}
      {(tags.subjects?.length > 0 || tags.diseases?.length > 0 || tags.keywords?.length > 0) && (
        <div style={{ marginBottom: 12 }}>
          <button className="btn btn-sm btn-secondary" onClick={() => setShowTags(v => !v)}
            style={{ fontSize: '0.78rem', marginBottom: showTags ? 6 : 0 }}>
            🏷 Browse Tags {showTags ? '▲' : '▼'}
          </button>
          {showTags && <TagBrowser tags={tags} selectedTagIds={selectedTagIds} toggleTag={toggleTag} />}
        </div>
      )}

      {/* Classify + status */}
      {isModerator && (
        <div style={{ marginBottom: 12 }}>
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' }}>
            <button className="btn btn-sm btn-secondary" onClick={startClassification}
              disabled={classifyStatus === 'running'}>
              {classifyStatus === 'running' ? 'Classifying...' : 'Classify Questions (AI)'}
            </button>
            {classifyStatus && (
              <span style={{ fontSize: '0.78rem', color: classifyStatus === 'completed' ? 'var(--correct-fg)' : classifyStatus === 'failed' ? 'var(--wrong-fg)' : 'var(--text-muted)' }}>
                {classifyStatus === 'completed' ? 'Done' : classifyStatus === 'failed' ? 'Failed' : classifyStatus === 'running' ? 'Running...' : ''}
              </span>
            )}
          </div>
          {classifySteps.length > 0 && classifyStatus === 'running' && (
            <div style={{ marginTop: 6, padding: '8px 12px', background: 'var(--bg)', borderRadius: 8, fontSize: '0.78rem', color: 'var(--text-muted)', maxHeight: 120, overflowY: 'auto' }}>
              {classifySteps.slice(-5).map((s, i) => (
                <div key={i}>{s.message}</div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Search row */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 8, flexWrap: 'wrap', alignItems: 'center' }}>
        <div style={{ flex: 1, minWidth: 200, position: 'relative' }}>
          <span style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)', color: '#94a3b8' }}>🔍</span>
          <input type="text" placeholder="Search questions..." value={searchQuery} onChange={e => setSearchQuery(e.target.value)}
            style={{ width: '100%', padding: '9px 13px 9px 36px', border: '1px solid var(--border)', borderRadius: 8, fontSize: '0.9rem', background: 'var(--input-bg)', color: 'var(--text)' }} />
        </div>
        {/* Search mode — clearly labelled separately from category chips */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: '0.8rem', color: 'var(--text-muted)' }}>
          <span>Search:</span>
          <select value={searchMode} onChange={e => setSearchMode(e.target.value)}
            style={{ padding: '5px 8px', border: '1px solid var(--border)', borderRadius: 6, fontSize: '0.8rem', background: 'var(--input-bg)', color: 'var(--text)' }}>
            <option value="hybrid">Keyword + Semantic</option>
            <option value="keyword">Keyword only</option>
            <option value="semantic">Semantic (AI)</option>
          </select>
        </div>
        {/* Page size */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: '0.8rem', color: 'var(--text-muted)' }}>
          <span>Show:</span>
          <select value={pageSize} onChange={e => setPageSize(e.target.value === 'all' ? 'all' : parseInt(e.target.value))}
            style={{ padding: '5px 8px', border: '1px solid var(--border)', borderRadius: 6, fontSize: '0.8rem', background: 'var(--input-bg)', color: 'var(--text)' }}>
            <option value={50}>50</option>
            <option value={100}>100</option>
            <option value={200}>200</option>
            <option value="all">All</option>
          </select>
        </div>
      </div>

      {/* Bulk actions row — only shown for moderators, clearly separated */}
      {isModerator && (
        <div style={{ display: 'flex', gap: 8, marginBottom: 10, flexWrap: 'wrap', alignItems: 'center', padding: '8px 12px', background: 'var(--bg)', borderRadius: 8 }}>
          <button className="btn btn-sm btn-secondary" onClick={selectAll} disabled={loading}>
            Select all {total > 0 ? `(${total})` : ''}
          </button>
          {selectedIds.size > 0 && (
            <>
              <span style={{ fontSize: '0.82rem', color: 'var(--text-muted)' }}>{selectedIds.size} selected</span>
              <button className="btn btn-sm btn-secondary" onClick={clearSelection}>Clear</button>
              <select value={assignCatId} onChange={e => setAssignCatId(e.target.value)}
                style={{ padding: '5px 10px', border: '1px solid var(--border)', borderRadius: 6, fontSize: '0.82rem', background: 'var(--input-bg)', color: 'var(--text)' }}>
                <option value="">Move to category…</option>
                <option value="remove">— Remove category</option>
                {categories.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
              </select>
              <button className="btn btn-sm btn-primary" onClick={bulkAssignCategory} disabled={!assignCatId}>Apply</button>
              <button className="btn btn-sm btn-primary" onClick={() => setShowCreateQuiz(true)}>Create Quiz</button>
            </>
          )}
          {bulkError && <span style={{ fontSize: '0.8rem', color: 'var(--wrong-fg)' }}>{bulkError}</span>}
        </div>
      )}

      {/* Question list */}
      {loading && questions.length === 0 && <div className="loading"><div className="spinner" /></div>}

      {questions.map(q => (
        <div key={q.id} style={{
          background: 'var(--card-bg)',
          border: `1.5px solid ${selectedIds.has(q.id) ? 'var(--primary)' : 'var(--border)'}`,
          borderRadius: 'var(--card-radius)', padding: '14px 16px', marginBottom: 8,
          display: 'flex', gap: 10, alignItems: 'flex-start',
        }}>
          {isModerator && (
            <input type="checkbox" checked={selectedIds.has(q.id)} onChange={() => toggleSelect(q.id)}
              style={{ marginTop: 4, accentColor: 'var(--primary)', flexShrink: 0 }} />
          )}
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ display: 'flex', gap: 8, marginBottom: 4, flexWrap: 'wrap', alignItems: 'center' }}>
              <span style={{ fontSize: '0.72rem', color: 'var(--text-muted)' }}>From: {q.quiz_title}</span>
              {q.question_category_name && (
                <span style={{ fontSize: '0.72rem', fontWeight: 600, padding: '1px 7px', borderRadius: 10, background: 'var(--option-sel-bg)', color: 'var(--primary)' }}>
                  {q.question_category_name}
                </span>
              )}
            </div>
            <p style={{ fontSize: '0.875rem', color: 'var(--text)', lineHeight: 1.55, marginBottom: q.options ? 6 : 0 }}>
              {stripHtml(q.question_text).slice(0, 200)}{stripHtml(q.question_text).length > 200 ? '...' : ''}
            </p>
            {q.options && (
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                {q.options.map((opt, i) => (
                  <span key={i} style={{
                    fontSize: '0.72rem', padding: '2px 7px', borderRadius: 4,
                    background: 'var(--bg)', color: 'var(--text-muted)',
                    border: '1px solid var(--border)',
                  }}>
                    {String.fromCharCode(65 + i)}. {opt.slice(0, 50)}{opt.length > 50 ? '…' : ''}
                  </span>
                ))}
              </div>
            )}
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 4, flexShrink: 0 }}>
            <button
              onClick={() => toggleFavorite(q.id)}
              title={favorites.includes(q.id) ? 'Remove from favorites' : 'Add to favorites'}
              style={{
                background: 'none',
                border: 'none',
                cursor: 'pointer',
                fontSize: '1.3rem',
                padding: 4,
                lineHeight: 1,
              }}
            >
              {favorites.includes(q.id) ? '⭐' : '☆'}
            </button>
            <button className="btn btn-sm btn-secondary" onClick={() => setStudyQuestion(q)}>Study</button>
            {(q.user_id === user?.id || isModerator) && (
              <button className="btn btn-sm btn-secondary" style={{ fontSize: '0.72rem' }}
                onClick={async () => {
                  const newVal = q.is_shared ? 0 : 1
                  try {
                    await api.patch(`/questions/${q.id}/share?shared=${newVal}`)
                    setQuestions(prev => prev.map(x => x.id === q.id ? { ...x, is_shared: newVal } : x))
                  } catch {}
                }}>{q.is_shared ? 'Unshare' : 'Share'}</button>
            )}
            {isModerator && <button className="btn btn-sm btn-secondary" onClick={() => setEditQuestion(q)}>Edit</button>}
            {isModerator && <button className="btn btn-sm btn-secondary" style={{ color: 'var(--wrong-fg)' }}
              onClick={async () => {
                if (!await openAlert(`Delete "${stripHtml(q.question_text).slice(0, 80)}..."? This removes it from all quizzes.`, { title: 'Delete Question', confirmLabel: 'Delete', cancelLabel: 'Cancel' })) return
                try {
                  await api.delete(`/questions/${q.id}`)
                  setQuestions(prev => prev.filter(x => x.id !== q.id))
                  setTotal(t => t - 1)
                } catch (err) { await openAlert(err.response?.data?.detail || 'Delete failed', { title: 'Error' }) }
              }}>Delete</button>}
          </div>
        </div>
      ))}

      {!loading && questions.length === 0 && (
        <div className="card"><div className="empty-state">No questions found.</div></div>
      )}

      {questions.length < total && (
        <div style={{ textAlign: 'center', marginTop: 12 }}>
          <button className="btn btn-secondary" onClick={() => loadQuestions(searchQuery, questions.length, filterCatIds, showUncategorized, showFavorites, searchMode, pageSize, selectedTagIds)} disabled={loading}>
            {loading ? 'Loading…' : `Load more (${total - questions.length} remaining)`}
          </button>
        </div>
      )}
    </div>
  )
}
