import React, { Fragment, useCallback, useEffect, useState } from 'react'
import { GripVertical, Pencil } from 'lucide-react'
import {
  defaultSection,
  exerciseRow,
  noteRow,
  sectionPlannedMinutes,
} from '../utils/trainingUnitSectionsForm'

const DND_TU_ITEM = 'application/x-shinkan-training-unit-item'
const DND_TU_SECTION = 'application/x-shinkan-training-section-v1'

function dtHasType(e, mime) {
  const t = e?.dataTransfer?.types
  if (!t || !mime) return false
  if (typeof t.contains === 'function' && t.contains(mime)) return true
  return Array.from(t).includes(mime)
}

function truncatePreview(text, max = 160) {
  const t = (text || '').replace(/\s+/g, ' ').trim()
  if (t.length <= max) return t
  return `${t.slice(0, max - 1)}…`
}

function reorderBlocksImmutable(blocks, fromI, toBeforeIdx) {
  const b = [...blocks]
  if (fromI < 0 || fromI >= b.length) return blocks
  const [moved] = b.splice(fromI, 1)
  let insertAt = toBeforeIdx
  if (fromI < toBeforeIdx) insertAt = toBeforeIdx - 1
  insertAt = Math.max(0, Math.min(insertAt, b.length))
  b.splice(insertAt, 0, moved)
  return b
}

/**
 * @param {(updater: (prev: Array) => Array) => void} props.onSectionsChange — wie React setState
 * @param {(p: { fromSlot: number, fromSectionIdx: number, toSlot: number, toSectionIdx: number }) => void} [props.onMoveSectionsAcrossSlots] — Rahmenprogramm: Abschnitt zwischen Slots verschieben
 */
export default function TrainingUnitSectionsEditor({
  sections,
  onSectionsChange,
  onRequestExercisePick,
  onPeekExercise,
  showExecutionExtras = false,
  heading = 'Abschnitte & Übungen',
  hideHeading = false,
  headingAccessory = null,
  wideExerciseGrid = false,
  enableItemDragReorder = true,
  enableSectionDragReorder = true,
  slotIndex = null,
  onMoveSectionsAcrossSlots = null,
}) {
  const ensure = (prev) =>
    prev && prev.length ? prev : [defaultSection()]

  const patch = useCallback(
    (updater) => {
      onSectionsChange((prev) => updater(ensure(prev)))
    },
    [onSectionsChange]
  )

  const sectionToSlot =
    slotIndex !== null && slotIndex !== undefined ? Number(slotIndex) : -1

  const updateSectionField = (sIdx, field, val) => {
    patch((prev) =>
      prev.map((s, i) => (i === sIdx ? { ...s, [field]: val } : s))
    )
  }

  const addSection = () => {
    patch((prev) => [...prev, defaultSection(`Abschnitt ${prev.length + 1}`)])
  }

  const removeSection = (sIdx) => {
    patch((prev) => {
      const next = prev.filter((_, i) => i !== sIdx)
      return next.length ? next : [defaultSection()]
    })
  }

  const moveSection = (sIdx, dir) => {
    patch((prev) => {
      const p = [...prev]
      const ta = sIdx + dir
      if (ta < 0 || ta >= p.length) return p
      ;[p[sIdx], p[ta]] = [p[ta], p[sIdx]]
      return p
    })
  }

  const addItem = (sIdx, kind) => {
    patch((prev) =>
      prev.map((s, i) =>
        i !== sIdx
          ? s
          : {
              ...s,
              items: [...(s.items || []), kind === 'note' ? noteRow() : exerciseRow()],
            }
      )
    )
  }

  const removeItem = (sIdx, iIdx) => {
    patch((prev) =>
      prev.map((s, si) =>
        si !== sIdx ? s : { ...s, items: (s.items || []).filter((_, ii) => ii !== iIdx) }
      )
    )
  }

  const moveItem = (sIdx, iIdx, dir) => {
    patch((prev) =>
      prev.map((s, si) => {
        if (si !== sIdx) return s
        const items = [...(s.items || [])]
        const ta = iIdx + dir
        if (ta < 0 || ta >= items.length) return s
        ;[items[iIdx], items[ta]] = [items[ta], items[iIdx]]
        return { ...s, items }
      })
    )
  }

  const updateItem = (sIdx, iIdx, field, val) => {
    patch((prev) =>
      prev.map((s, si) =>
        si !== sIdx
          ? s
          : {
              ...s,
              items: (s.items || []).map((row, ii) =>
                ii === iIdx ? { ...row, [field]: val } : row
              ),
            }
      )
    )
  }

  const [textEdit, setTextEdit] = useState(null)
  const [draggingPos, setDraggingPos] = useState(null)
  const [dropTargetPos, setDropTargetPos] = useState(null)

  const [dropSectionBand, setDropSectionBand] = useState(null)
  /** { slot: number, beforeIdx: number } */

  useEffect(() => {
    if (!textEdit) return
    const onKey = (e) => {
      if (e.key === 'Escape') setTextEdit(null)
    }
    window.addEventListener('keydown', onKey)
    return () => window.removeEventListener('keydown', onKey)
  }, [textEdit])

  const clearSectionDnD = () => setDropSectionBand(null)

  const onSectionDragStart = (e, sIdx) => {
    if (!enableSectionDragReorder) return
    e.stopPropagation()
    try {
      e.dataTransfer.effectAllowed = 'move'
      e.dataTransfer.setData(
        DND_TU_SECTION,
        JSON.stringify({
          fromSlot: sectionToSlot,
          fromSectionIdx: sIdx,
        })
      )
    } catch {
      /* ignore */
    }
    setDropSectionBand(null)
  }

  const onSectionBandDragOver = (e, beforeIdx) => {
    if (!enableSectionDragReorder) return
    if (!dtHasType(e, DND_TU_SECTION)) return
    e.preventDefault()
    e.stopPropagation()
    try {
      e.dataTransfer.dropEffect = 'move'
    } catch {
      /* ignore */
    }
    setDropSectionBand({ slot: sectionToSlot, beforeIdx })
  }

  const onSectionBandDrop = (e, insertBeforeIdx) => {
    if (!enableSectionDragReorder) return
    e.preventDefault()
    e.stopPropagation()
    clearSectionDnD()
    let raw = ''
    try {
      raw = e.dataTransfer.getData(DND_TU_SECTION)
    } catch {
      return
    }
    if (!raw) return
    let data
    try {
      data = JSON.parse(raw)
    } catch {
      return
    }
    const fromSi = data.fromSectionIdx
    const fromSlot = typeof data.fromSlot === 'number' ? data.fromSlot : -1
    if (typeof fromSi !== 'number') return

    if (
      typeof onMoveSectionsAcrossSlots === 'function' &&
      sectionToSlot >= 0 &&
      fromSlot >= 0
    ) {
      onMoveSectionsAcrossSlots({
        fromSlot,
        fromSectionIdx: fromSi,
        toSlot: sectionToSlot,
        toSectionIdx: insertBeforeIdx,
      })
      return
    }

    patch((prev) => reorderBlocksImmutable(prev, fromSi, insertBeforeIdx))
  }

  const onItemDragStart = (e, sIdx, iIdx) => {
    if (!enableItemDragReorder) return
    e.stopPropagation()
    try {
      e.dataTransfer.effectAllowed = 'move'
      e.dataTransfer.setData(
        DND_TU_ITEM,
        JSON.stringify({ sectionIndex: sIdx, itemIndex: iIdx })
      )
    } catch {
      /* ignore */
    }
    setDraggingPos({ sIdx, iIdx })
  }

  const clearDragChrome = () => {
    setDraggingPos(null)
    setDropTargetPos(null)
  }

  const onItemDragOverRow = (e, sIdx, iIdx) => {
    if (!enableItemDragReorder) return
    if (!dtHasType(e, DND_TU_ITEM)) return
    e.preventDefault()
    e.stopPropagation()
    try {
      e.dataTransfer.dropEffect = 'move'
    } catch {
      /* ignore */
    }
    setDropTargetPos({ sIdx, iIdx })
  }

  const onItemDropRow = (e, toSIdx, toIdx) => {
    if (!enableItemDragReorder) return
    e.preventDefault()
    e.stopPropagation()
    let raw = ''
    try {
      raw = e.dataTransfer.getData(DND_TU_ITEM)
    } catch {
      clearDragChrome()
      return
    }
    if (!raw) {
      clearDragChrome()
      return
    }
    let data
    try {
      data = JSON.parse(raw)
    } catch {
      clearDragChrome()
      return
    }
    const fromS = data.sectionIndex
    const fromI = data.itemIndex
    if (typeof fromS !== 'number' || typeof fromI !== 'number') {
      clearDragChrome()
      return
    }
    if (fromS === toSIdx && fromI === toIdx) {
      clearDragChrome()
      return
    }

    patch((prev) => {
      const list = ensure(prev)
      if (
        fromS < 0 ||
        fromS >= list.length ||
        toSIdx < 0 ||
        toSIdx >= list.length ||
        typeof toIdx !== 'number'
      ) {
        return prev
      }

      const fromItems = [...(list[fromS].items || [])]
      if (fromI < 0 || fromI >= fromItems.length) return prev

      const moved = fromItems[fromI]
      fromItems.splice(fromI, 1)

      if (fromS === toSIdx) {
        let insertAt = toIdx
        if (fromI < toIdx) insertAt = toIdx - 1
        const bounded = Math.max(0, Math.min(insertAt, fromItems.length))
        fromItems.splice(bounded, 0, moved)
        return list.map((sec, i) => (i === fromS ? { ...sec, items: fromItems } : sec))
      }

      const toItems = [...(list[toSIdx].items || [])]
      const insertAt = Math.max(0, Math.min(toIdx, toItems.length))
      toItems.splice(insertAt, 0, moved)
      return list.map((sec, i) => {
        if (i === fromS) return { ...sec, items: fromItems }
        if (i === toSIdx) return { ...sec, items: toItems }
        return sec
      })
    })
    clearDragChrome()
  }

  const applyTextEdit = () => {
    if (!textEdit) return
    const { kind, sIdx, iIdx, draft } = textEdit
    if (kind === 'zwischen-note') {
      updateItem(sIdx, iIdx, 'note_body', draft)
    } else if (kind === 'exercise-notes') {
      updateItem(sIdx, iIdx, 'notes', draft)
    }
    setTextEdit(null)
  }

  const list = ensure(sections)

  return (
    <div
      className={
        'training-unit-sections-editor' +
        (wideExerciseGrid ? ' training-unit-sections-editor--wide' : '')
      }
    >
      {(!hideHeading || headingAccessory) ? (
        <div
          className="tu-editor-heading-toolbar"
          style={{
            display: 'flex',
            flexWrap: 'wrap',
            justifyContent: 'space-between',
            alignItems: 'center',
            gap: '10px',
            marginBottom: '0.75rem',
          }}
        >
          {!hideHeading ? (
            <h3 style={{ margin: 0, fontSize: '1rem', flex: '1 1 200px', minWidth: 0 }}>
              {heading}
            </h3>
          ) : headingAccessory ? (
            <span style={{ flex: '1 1 auto', minWidth: 0 }} />
          ) : null}
          {headingAccessory ? (
            <div
              style={{
                display: 'flex',
                flexWrap: 'wrap',
                gap: '8px',
                justifyContent: 'flex-end',
                alignItems: 'center',
              }}
            >
              {headingAccessory}
            </div>
          ) : null}
        </div>
      ) : null}
      {list.map((sec, sIdx) => {
        const planMin = sectionPlannedMinutes(sec)
        const itemCount = sec.items?.length ?? 0
        const bandActiveBefore = (bx) =>
          enableSectionDragReorder &&
          dropSectionBand &&
          dropSectionBand.slot === sectionToSlot &&
          dropSectionBand.beforeIdx === bx

        return (
          <Fragment key={`secFrag-${sIdx}`}>
            {enableSectionDragReorder ? (
              <div
                className={'tu-section-dropband' + (bandActiveBefore(sIdx) ? ' tu-section-dropband--active' : '')}
                title="Abschnitt hier einfügen"
                onDragOver={(e) => {
                  if (!enableSectionDragReorder) return
                  if (!dtHasType(e, DND_TU_SECTION)) return
                  onSectionBandDragOver(e, sIdx)
                }}
                onDragLeave={(e) => {
                  if (e.currentTarget.contains(e.relatedTarget)) return
                  clearSectionDnD()
                }}
                onDrop={(e) => onSectionBandDrop(e, sIdx)}
              />
            ) : null}
            <div
              className="tu-section-shell"
              style={{
                marginBottom: '1rem',
                padding: '0.75rem',
                background: 'var(--surface2)',
                borderRadius: '10px',
                border: '1px solid var(--border, rgba(0,0,0,0.08))',
              }}
            >
              <div
                style={{
                  display: 'flex',
                  flexWrap: 'wrap',
                  gap: '0.5rem',
                  marginBottom: '0.5rem',
                  alignItems: 'flex-start',
                }}
              >
                {enableSectionDragReorder ? (
                  <span
                    className="tu-sec-drag-grip"
                    draggable
                    onDragStart={(e) => onSectionDragStart(e, sIdx)}
                    role="button"
                    tabIndex={0}
                    aria-label="Abschnitt ziehen"
                    title="Abschnitt ziehen"
                  >
                    <GripVertical size={16} strokeWidth={2} aria-hidden />
                  </span>
                ) : null}
                <input
                  className="form-input"
                  style={{ flex: '2 1 180px', marginBottom: 0 }}
                  value={sec.title}
                  onChange={(e) => updateSectionField(sIdx, 'title', e.target.value)}
                  placeholder="Abschnittstitel (z. B. Aufwärmen)"
                />
                <div style={{ display: 'flex', gap: '4px', alignSelf: 'center' }}>
                  <button
                    type="button"
                    aria-label="Abschnitt hoch"
                    onClick={() => moveSection(sIdx, -1)}
                    disabled={sIdx === 0}
                    style={{ padding: '4px 10px', opacity: sIdx === 0 ? 0.35 : 1 }}
                  >
                    ▲
                  </button>
                  <button
                    type="button"
                    aria-label="Abschnitt runter"
                    onClick={() => moveSection(sIdx, 1)}
                    disabled={sIdx === list.length - 1}
                    style={{
                      padding: '4px 10px',
                      opacity: sIdx === list.length - 1 ? 0.35 : 1,
                    }}
                  >
                    ▼
                  </button>
                </div>
                <button
                  type="button"
                  className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                  onClick={() => removeSection(sIdx)}
                >
                  Abschnitt entfernen
                </button>
              </div>
              <textarea
                className="form-input"
                rows={2}
                value={sec.guidance_notes}
                onChange={(e) =>
                  updateSectionField(sIdx, 'guidance_notes', e.target.value)
                }
                placeholder="Hinweise zum Abschnitt (Material, Zeit, Zielrichtung …)"
              />
              {planMin > 0 && (
                <p style={{ fontSize: '0.78rem', color: 'var(--text2)', marginTop: '0.35rem' }}>
                  Geplant in diesem Abschnitt: ca. {planMin} Min. (Übungen)
                </p>
              )}

              {(sec.items || []).map((it, iIdx) => {
                const dropHere =
                  enableItemDragReorder &&
                  dropTargetPos?.sIdx === sIdx &&
                  dropTargetPos?.iIdx === iIdx
                const dragHere =
                  enableItemDragReorder &&
                  draggingPos?.sIdx === sIdx &&
                  draggingPos?.iIdx === iIdx
                const rowCommon =
                  'tu-item-row' +
                  (dropHere ? ' tu-item-row--drop-target' : '') +
                  (dragHere ? ' tu-item-row--dragging' : '')

                const dndRowProps = enableItemDragReorder
                  ? {
                      onDragOverCapture: (ev) => onItemDragOverRow(ev, sIdx, iIdx),
                      onDrop: (ev) => onItemDropRow(ev, sIdx, iIdx),
                    }
                  : {}

                if (it.item_type === 'note') {
                  const notePv = truncatePreview(it.note_body || '', 260)
                  const noteHasText = Boolean((it.note_body || '').trim())
                  return (
                    <div
                      key={`note-${sIdx}-${iIdx}`}
                      className={`${rowCommon} tu-item-row--note`}
                      {...dndRowProps}
                    >
                      {enableItemDragReorder ? (
                        <span
                          className="tu-row-grip"
                          draggable
                          onDragStart={(e) => onItemDragStart(e, sIdx, iIdx)}
                          onDragEnd={clearDragChrome}
                          role="button"
                          tabIndex={0}
                          aria-label="Eintrag ziehen"
                        >
                          <GripVertical size={15} strokeWidth={2} aria-hidden />
                        </span>
                      ) : null}
                      <div className="tu-item-row__nudge">
                        <button
                          type="button"
                          aria-label="Eintrag nach oben"
                          onClick={() => moveItem(sIdx, iIdx, -1)}
                          disabled={iIdx === 0}
                        >
                          ▲
                        </button>
                        <button
                          type="button"
                          aria-label="Eintrag nach unten"
                          onClick={() => moveItem(sIdx, iIdx, 1)}
                          disabled={iIdx === sec.items.length - 1}
                        >
                          ▼
                        </button>
                      </div>
                      <div className="tu-item-row__body tu-item-row__body--note">
                        <span className="tu-item-row__meta-label">Zwischen-Anmerkung</span>
                        <p
                          className={`tu-item-row__preview tu-item-row__preview--clamp${noteHasText ? '' : ' tu-item-row__preview--empty'}`}
                          title={noteHasText ? (it.note_body || '').trim() : undefined}
                        >
                          {noteHasText ? notePv : '—'}
                        </p>
                      </div>
                      <button
                        type="button"
                        className="tu-icon-btn"
                        title="Zwischen-Anmerkung bearbeiten"
                        aria-label="Zwischen-Anmerkung bearbeiten"
                        onClick={() =>
                          setTextEdit({
                            kind: 'zwischen-note',
                            sIdx,
                            iIdx,
                            draft: it.note_body || '',
                          })
                        }
                      >
                        <Pencil size={15} strokeWidth={2} aria-hidden />
                      </button>
                      <button
                        type="button"
                        className="tu-item-row__remove"
                        title="Entfernen"
                        aria-label="Zwischen-Anmerkung entfernen"
                        onClick={() => removeItem(sIdx, iIdx)}
                      >
                        ✗
                      </button>
                    </div>
                  )
                }

                const variantOpts = Array.isArray(it.variants) ? it.variants : []
                const exTitle =
                  it.exercise_title || (it.exercise_id ? `Übung #${it.exercise_id}` : '')
                const annotPrev = truncatePreview(it.notes || '', 220)
                const annotHasText = Boolean((it.notes || '').trim())
                const hasVariants = variantOpts.length > 0 && it.exercise_id
                const variantIdPeek =
                  it.exercise_variant_id === '' || it.exercise_variant_id == null
                    ? undefined
                    : Number(it.exercise_variant_id)

                return (
                  <div
                    key={`ex-${sIdx}-${iIdx}`}
                    className={`${rowCommon} tu-item-row--exercise`}
                    {...dndRowProps}
                  >
                    <div className="tu-item-row__mainline">
                      {enableItemDragReorder ? (
                        <span
                          className="tu-row-grip"
                          draggable
                          onDragStart={(e) => onItemDragStart(e, sIdx, iIdx)}
                          onDragEnd={clearDragChrome}
                          role="button"
                          tabIndex={0}
                          aria-label="Eintrag ziehen"
                        >
                          <GripVertical size={15} strokeWidth={2} aria-hidden />
                        </span>
                      ) : null}
                      <div className="tu-item-row__nudge">
                        <button
                          type="button"
                          aria-label="Eintrag nach oben"
                          onClick={() => moveItem(sIdx, iIdx, -1)}
                          disabled={iIdx === 0}
                        >
                          ▲
                        </button>
                        <button
                          type="button"
                          aria-label="Eintrag nach unten"
                          onClick={() => moveItem(sIdx, iIdx, 1)}
                          disabled={iIdx === sec.items.length - 1}
                        >
                          ▼
                        </button>
                      </div>
                      <div className="tu-item-row__body tu-item-row__body--exercise">
                        <div className="tu-ex-title-line">
                          {exTitle ? (
                            <strong className="tu-ex-title">{exTitle}</strong>
                          ) : (
                            <span className="tu-ex-title-placeholder">Keine Übung gewählt</span>
                          )}
                          <span className="tu-ex-inline-actions">
                            <button
                              type="button"
                              className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                              onClick={() =>
                                onRequestExercisePick?.({
                                  sectionIndex: sIdx,
                                  itemIndex: iIdx,
                                })
                              }
                            >
                              {exTitle ? 'Wechseln' : 'Übung suchen…'}
                            </button>
                            {it.exercise_id && onPeekExercise ? (
                              <button
                                type="button"
                                className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                                onClick={() =>
                                  onPeekExercise(Number(it.exercise_id), variantIdPeek)
                                }
                              >
                                Vorschau
                              </button>
                            ) : null}
                          </span>
                        </div>
                        <div className="tu-ex-meta-line">
                          {hasVariants ? (
                            <select
                              className={`form-input tu-ex-variant-select${
                                wideExerciseGrid ? ' tu-ex-variant-select--wide' : ''
                              }`}
                              value={
                                it.exercise_variant_id === '' ||
                                it.exercise_variant_id == null
                                  ? ''
                                  : String(it.exercise_variant_id)
                              }
                              onChange={(e) => {
                                const raw = e.target.value
                                updateItem(
                                  sIdx,
                                  iIdx,
                                  'exercise_variant_id',
                                  raw === '' ? '' : parseInt(raw, 10)
                                )
                              }}
                              title="Übungsvariante"
                            >
                              <option value="">Stammübung</option>
                              {variantOpts.map((v) => (
                                <option key={v.id} value={v.id}>
                                  {v.variant_name || `Variante #${v.id}`}
                                </option>
                              ))}
                            </select>
                          ) : null}
                          <div className="tu-ex-annot">
                            <span
                              className={`tu-item-row__preview tu-ex-annot__text${annotHasText ? '' : ' tu-item-row__preview--empty'}`}
                              title={annotHasText ? (it.notes || '').trim() : undefined}
                            >
                              {annotHasText ? annotPrev : '—'}
                            </span>
                            <button
                              type="button"
                              className="tu-icon-btn"
                              title="Anmerkung zur Übung"
                              aria-label="Anmerkung zur Übung bearbeiten"
                              onClick={() =>
                                setTextEdit({
                                  kind: 'exercise-notes',
                                  sIdx,
                                  iIdx,
                                  draft: it.notes || '',
                                })
                              }
                            >
                              <Pencil size={15} strokeWidth={2} aria-hidden />
                            </button>
                          </div>
                        </div>
                      </div>
                      <div className="tu-item-row__side">
                        <input
                          type="number"
                          className="form-input tu-ex-duration"
                          min={1}
                          value={it.planned_duration_min}
                          onChange={(e) =>
                            updateItem(sIdx, iIdx, 'planned_duration_min', e.target.value)
                          }
                          placeholder="Min"
                          title="Geplante Dauer (Minuten)"
                        />
                        <button
                          type="button"
                          className="tu-item-row__remove"
                          title="Übung entfernen"
                          aria-label="Übung entfernen"
                          onClick={() => removeItem(sIdx, iIdx)}
                        >
                          ✗
                        </button>
                      </div>
                    </div>

                    {showExecutionExtras ? (
                      <label className="tu-ex-run-block form-label">
                        Ist-Dauer / Anpassungen
                        <span className="tu-ex-run-block__controls">
                          <input
                            type="number"
                            className="form-input"
                            min={1}
                            value={it.actual_duration_min}
                            onChange={(e) =>
                              updateItem(sIdx, iIdx, 'actual_duration_min', e.target.value)
                            }
                            placeholder="IST min"
                          />
                          <textarea
                            className="form-input"
                            rows={2}
                            value={it.modifications || ''}
                            onChange={(e) =>
                              updateItem(sIdx, iIdx, 'modifications', e.target.value)
                            }
                            placeholder="Abweichungen beim Durchführen"
                          />
                        </span>
                      </label>
                    ) : null}
                  </div>
                )
              })}

              {enableItemDragReorder ? (
                <div
                  className={`tu-item-append-drop${
                    dropTargetPos?.sIdx === sIdx && dropTargetPos?.iIdx === itemCount
                      ? ' tu-item-append-drop--active'
                      : ''
                  }`}
                  title="Hierhin ziehen, um nach unten einzufügen"
                  onDragOverCapture={(e) => onItemDragOverRow(e, sIdx, itemCount)}
                  onDrop={(e) => onItemDropRow(e, sIdx, itemCount)}
                />
              ) : null}

              <div style={{ marginTop: '0.65rem', display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
                <button
                  type="button"
                  className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                  onClick={() => onRequestExercisePick?.({ sectionIndex: sIdx })}
                >
                  + Übung
                </button>
                <button
                  type="button"
                  className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                  onClick={() => addItem(sIdx, 'note')}
                >
                  + Anmerkung
                </button>
              </div>
            </div>
          </Fragment>
        )
      })}

      {enableSectionDragReorder ? (
        <div
          className={
            'tu-section-dropband tu-section-dropband--end' +
            (dropSectionBand &&
            dropSectionBand.slot === sectionToSlot &&
            dropSectionBand.beforeIdx === list.length
              ? ' tu-section-dropband--active'
              : '')
          }
          title="Abschnitt am Ende einfügen"
          onDragOver={(e) => {
            if (!dtHasType(e, DND_TU_SECTION)) return
            onSectionBandDragOver(e, list.length)
          }}
          onDragLeave={(e) => {
            if (e.currentTarget.contains(e.relatedTarget)) return
            clearSectionDnD()
          }}
          onDrop={(e) => onSectionBandDrop(e, list.length)}
        />
      ) : null}

      <button
        type="button"
        className="btn btn-secondary framework-ctrl framework-ctrl--xs"
        onClick={addSection}
      >
        + Abschnitt hinzufügen
      </button>

      {textEdit ? (
        <div
          className="tu-textedit-backdrop"
          role="presentation"
          onMouseDown={(e) => {
            if (e.target === e.currentTarget) setTextEdit(null)
          }}
        >
          <div
            className="tu-textedit-panel"
            role="dialog"
            aria-modal="true"
            aria-labelledby="tu-textedit-title"
            onMouseDown={(e) => e.stopPropagation()}
          >
            <h4 id="tu-textedit-title" className="tu-textedit-title">
              {textEdit.kind === 'zwischen-note'
                ? 'Zwischen-Anmerkung'
                : 'Anmerkung zur Übung'}
            </h4>
            <textarea
              className="form-input tu-textedit-textarea"
              rows={5}
              value={textEdit.draft}
              onChange={(e) =>
                setTextEdit((prev) => (prev ? { ...prev, draft: e.target.value } : prev))
              }
              placeholder={
                textEdit.kind === 'zwischen-note'
                  ? 'Hinweise zwischen Übungen …'
                  : 'Kurze Anmerkung zur Übung'
              }
            />
            <div className="tu-textedit-actions">
              <button type="button" className="btn btn-primary" onClick={applyTextEdit}>
                Übernehmen
              </button>
              <button
                type="button"
                className="btn btn-secondary"
                onClick={() => setTextEdit(null)}
              >
                Abbrechen
              </button>
            </div>
          </div>
        </div>
      ) : null}
    </div>
  )
}
