/**
 * Übungssuche mit Volltext-, KI-/Semantikfeld (aktuell gleiche Engine wie Suche) und erweiterten Filtern.
 * Paginierung bis max. 100 Treffer pro Request (API-Limit).
 */
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react'
import { useVirtualizer } from '@tanstack/react-virtual'
import api from '../utils/api'
import { useAuth } from '../context/AuthContext'
import { SKILL_LEVEL_OPTIONS } from '../constants/skillLevels'
import {
  INITIAL_EXERCISE_LIST_FILTERS,
  mergeExerciseListPrefsFromApi,
  splitMnCatalogRules,
  splitScalarCatalogRules,
} from '../constants/exerciseListFilters'
import SkillTreeMultiSelect from './SkillTreeMultiSelect'
import ExerciseFocusRulePicker from './ExerciseFocusRulePicker'
import CatalogRulePicker from './CatalogRulePicker'

const PAGE_SIZE = 100
const LEVEL_FILTER_OPTS = SKILL_LEVEL_OPTIONS.filter((o) => o.level != null)

const INITIAL_FILTERS = { ...INITIAL_EXERCISE_LIST_FILTERS }

/** Stub-Ziel für API-Validator (mind. Ziel oder Durchführung); Nutzer ergänzt Details in der Übungsbearbeitung. */
const QUICK_CREATE_GOAL_PLACEHOLDER =
  'Aus der Trainingsplanung angelegt — bitte Ziel und Durchführung in der Übungsbearbeitung ergänzen.'

export default function ExercisePickerModal({
  open,
  onClose,
  onSelectExercise,
  multiSelect = false,
  onSelectExercises = null,
  enableQuickCreateDraft = false,
  /** Wenn gesetzt: z. B. ['simple'] oder ['combination'] — sonst alle Übungsarten */
  exerciseKindAny = undefined,
}) {
  const { user } = useAuth()
  const [catalogs, setCatalogs] = useState({
    focusAreas: [],
    styleDirections: [],
    trainingTypes: [],
    targetGroups: [],
    skills: [],
  })
  const [catalogsReady, setCatalogsReady] = useState(false)
  const [searchInput, setSearchInput] = useState('')
  const [aiSearchInput, setAiSearchInput] = useState('')
  const [debouncedSearch, setDebouncedSearch] = useState('')
  const [debouncedAi, setDebouncedAi] = useState('')
  const [filters, setFilters] = useState(() => ({ ...INITIAL_FILTERS }))
  const [filterOpen, setFilterOpen] = useState(false)
  const [list, setList] = useState([])
  const [loading, setLoading] = useState(false)
  const [loadingMore, setLoadingMore] = useState(false)
  const [hasMore, setHasMore] = useState(false)
  const [multiPicked, setMultiPicked] = useState([])
  const [quickOpen, setQuickOpen] = useState(false)
  const [quickTitle, setQuickTitle] = useState('')
  const [quickSummary, setQuickSummary] = useState('')
  const [quickSaving, setQuickSaving] = useState(false)
  const pickerScrollRef = useRef(null)

  const toggleMultiPick = (ex) => {
    setMultiPicked((prev) =>
      prev.some((p) => p.id === ex.id) ? prev.filter((p) => p.id !== ex.id) : [...prev, ex]
    )
  }

  useEffect(() => {
    const t = setTimeout(() => setDebouncedSearch(searchInput.trim()), 350)
    return () => clearTimeout(t)
  }, [searchInput])

  useEffect(() => {
    const t = setTimeout(() => setDebouncedAi(aiSearchInput.trim()), 350)
    return () => clearTimeout(t)
  }, [aiSearchInput])

  useEffect(() => {
    if (!open) return
    let cancelled = false
    ;(async () => {
      try {
        const [fa, sd, tt, tg, sk] = await Promise.all([
          api.listFocusAreas(),
          api.listStyleDirections(),
          api.listTrainingTypes(),
          api.listTargetGroups(),
          api.listSkillsCatalog(),
        ])
        if (!cancelled) {
          setCatalogs({
            focusAreas: fa,
            styleDirections: sd,
            trainingTypes: tt,
            targetGroups: tg,
            skills: sk,
          })
          setCatalogsReady(true)
        }
      } catch (e) {
        console.error(e)
        if (!cancelled) setCatalogsReady(true)
      }
    })()
    return () => {
      cancelled = true
    }
  }, [open])

  useEffect(() => {
    if (!open) {
      setSearchInput('')
      setAiSearchInput('')
      setDebouncedSearch('')
      setDebouncedAi('')
      setFilters({ ...INITIAL_FILTERS })
      setFilterOpen(false)
      setList([])
      setHasMore(false)
      setMultiPicked([])
      setQuickOpen(false)
      setQuickTitle('')
      setQuickSummary('')
      setQuickSaving(false)
      return
    }
    setFilters(mergeExerciseListPrefsFromApi(user?.exercise_list_prefs))
  }, [open, user?.exercise_list_prefs])

  const focusOptions = useMemo(
    () => catalogs.focusAreas.map((fa) => ({ id: fa.id, label: `${fa.icon || ''} ${fa.name || ''}`.trim() })),
    [catalogs.focusAreas]
  )
  const styleOptions = useMemo(
    () => catalogs.styleDirections.map((s) => ({ id: s.id, label: s.name || String(s.id) })),
    [catalogs.styleDirections]
  )
  const trainingTypeOptions = useMemo(
    () => catalogs.trainingTypes.map((t) => ({ id: t.id, label: t.name || String(t.id) })),
    [catalogs.trainingTypes]
  )
  const targetGroupOptions = useMemo(
    () => catalogs.targetGroups.map((g) => ({ id: g.id, label: g.name || String(g.id) })),
    [catalogs.targetGroups]
  )
  const visibilityOptions = useMemo(
    () => [
      { id: 'private', label: 'Privat' },
      { id: 'club', label: 'Verein' },
      { id: 'official', label: 'Offiziell' },
    ],
    []
  )
  const statusOptions = useMemo(
    () => [
      { id: 'draft', label: 'Entwurf' },
      { id: 'in_review', label: 'In Prüfung' },
      { id: 'approved', label: 'Freigegeben' },
      { id: 'archived', label: 'Archiviert' },
    ],
    []
  )

  const queryBase = useMemo(() => {
    const q = {}
    const n = (v) => (v === '' || v == null ? undefined : Number(v))
    const ids = (arr) =>
      Array.isArray(arr) && arr.length ? arr.map((x) => Number(x)).filter((x) => !Number.isNaN(x)) : undefined
    const fMn = splitMnCatalogRules(filters.focus_rules)
    if (fMn.includeIds.length) q.focus_area_must_include_ids = fMn.includeIds
    if (fMn.excludeIds.length) q.focus_area_must_exclude_ids = fMn.excludeIds
    if (filters.focus_only_without) q.focus_only_without_focus_areas = true

    const fa = ids(filters.focus_area_ids)
    if (fa?.length) q.focus_area_ids = fa

    const sdMn = splitMnCatalogRules(filters.style_direction_rules)
    if (sdMn.includeIds.length) q.style_direction_must_include_ids = sdMn.includeIds
    if (sdMn.excludeIds.length) q.style_direction_must_exclude_ids = sdMn.excludeIds
    const sdLegacy = ids(filters.style_direction_ids)
    if (sdLegacy?.length) q.style_direction_ids = sdLegacy

    const ttMn = splitMnCatalogRules(filters.training_type_rules)
    if (ttMn.includeIds.length) q.training_type_must_include_ids = ttMn.includeIds
    if (ttMn.excludeIds.length) q.training_type_must_exclude_ids = ttMn.excludeIds
    const ttLegacy = ids(filters.training_type_ids)
    if (ttLegacy?.length) q.training_type_ids = ttLegacy

    const tgMn = splitMnCatalogRules(filters.target_group_rules)
    if (tgMn.includeIds.length) q.target_group_must_include_ids = tgMn.includeIds
    if (tgMn.excludeIds.length) q.target_group_must_exclude_ids = tgMn.excludeIds
    const tgLegacy = ids(filters.target_group_ids)
    if (tgLegacy?.length) q.target_group_ids = tgLegacy

    const visMn = splitScalarCatalogRules(filters.visibility_rules)
    if (visMn.includeVals.length) q.visibility_any = visMn.includeVals
    if (visMn.excludeVals.length) q.visibility_exclude_any = visMn.excludeVals

    const stMn = splitScalarCatalogRules(filters.status_rules)
    if (stMn.includeVals.length) q.status_any = stMn.includeVals
    if (stMn.excludeVals.length) q.status_exclude_any = stMn.excludeVals

    const sk = ids(filters.skill_ids)
    if (sk?.length) q.skill_ids = sk
    if (filters.skill_min_level) q.skill_min_level = n(filters.skill_min_level)
    if (filters.skill_max_level) q.skill_max_level = n(filters.skill_max_level)
    if (filters.exclude_without_focus) q.exclude_without_focus = true
    if (filters.include_archived) q.include_archived = true
    if (debouncedSearch) q.search = debouncedSearch
    if (debouncedAi) q.ai_search = debouncedAi
    if (
      Array.isArray(exerciseKindAny) &&
      exerciseKindAny.length > 0
    ) {
      q.exercise_kind_any = exerciseKindAny
    }
    return q
  }, [filters, debouncedSearch, debouncedAi, exerciseKindAny])

  const reload = useCallback(async () => {
    if (!open || !catalogsReady) return
    setLoading(true)
    try {
      const batch = await api.listExercises({
        ...queryBase,
        include_archived: true,
        include_variants: true,
        limit: PAGE_SIZE,
        offset: 0,
      })
      setList(Array.isArray(batch) ? batch : [])
      setHasMore(batch?.length === PAGE_SIZE)
    } catch (e) {
      console.error(e)
      alert(e.message || 'Laden fehlgeschlagen')
      setList([])
      setHasMore(false)
    } finally {
      setLoading(false)
    }
  }, [open, catalogsReady, queryBase])

  useEffect(() => {
    reload()
  }, [reload])

  const loadMore = async () => {
    if (!hasMore || loadingMore || loading) return
    const last = list[list.length - 1]
    if (!last?.id || last.updated_at == null) return
    setLoadingMore(true)
    try {
      const batch = await api.listExercises({
        ...queryBase,
        include_archived: true,
        include_variants: true,
        limit: PAGE_SIZE,
        cursor_updated_at:
          typeof last.updated_at === 'string'
            ? last.updated_at
            : new Date(last.updated_at).toISOString(),
        cursor_id: last.id,
      })
      setList((prev) => [...prev, ...(Array.isArray(batch) ? batch : [])])
      setHasMore(batch?.length === PAGE_SIZE)
    } catch (e) {
      console.error(e)
      alert(e.message || 'Mehr laden fehlgeschlagen')
    } finally {
      setLoadingMore(false)
    }
  }

  const rowVirtualizer = useVirtualizer({
    count: list.length,
    getScrollElement: () => pickerScrollRef.current,
    estimateSize: () => 88,
    overscan: 8,
    getItemKey: (index) => String(list[index]?.id ?? index),
  })

  const resetFilters = () => setFilters({ ...INITIAL_FILTERS })

  const submitQuickCreate = async () => {
    const title = (quickTitle || '').trim()
    if (title.length < 3) {
      alert('Titel: mindestens 3 Zeichen.')
      return
    }
    const summaryRaw = (quickSummary || '').trim()
    setQuickSaving(true)
    try {
      const created = await api.createExercise({
        title,
        summary: summaryRaw || null,
        goal: QUICK_CREATE_GOAL_PLACEHOLDER,
        execution: null,
        visibility: 'private',
        status: 'draft',
        equipment: [],
        focus_areas_multi: [],
        training_styles_multi: [],
        training_types_multi: [],
        target_groups_multi: [],
        age_groups: [],
        skills: [],
        club_id: null,
      })
      if (!created?.id) {
        throw new Error('Anlegen fehlgeschlagen')
      }
      if (multiSelect && typeof onSelectExercises === 'function') {
        await Promise.resolve(onSelectExercises([created]))
      } else if (typeof onSelectExercise === 'function') {
        await Promise.resolve(onSelectExercise(created))
      }
      onClose()
    } catch (e) {
      console.error(e)
      alert(e.message || 'Übung konnte nicht angelegt werden')
    } finally {
      setQuickSaving(false)
    }
  }

  if (!open) return null

  return (
    <div
      className="admin-modal-backdrop"
      role="presentation"
      onClick={(e) => {
        if (e.target === e.currentTarget) onClose()
      }}
    >
      <div
        className="admin-modal-sheet"
        role="dialog"
        aria-modal="true"
        style={{ maxWidth: '920px', width: '100%', maxHeight: '92vh', display: 'flex', flexDirection: 'column' }}
        onClick={(e) => e.stopPropagation()}
      >
        <div className="admin-modal-sheet__header">
          <h3 className="admin-modal-sheet__title">
            {multiSelect ? 'Übungen auswählen' : 'Übung auswählen'}
          </h3>
          <button type="button" className="btn btn-secondary admin-modal-sheet__close" onClick={onClose}>
            Schließen
          </button>
        </div>

        {enableQuickCreateDraft ? (
          <div
            style={{
              padding: '10px 1rem 12px',
              borderBottom: '1px solid var(--border)',
              flexShrink: 0,
              background: 'var(--surface2)',
            }}
          >
            <button
              type="button"
              className="btn btn-secondary"
              style={{ width: '100%' }}
              onClick={() => setQuickOpen((v) => !v)}
              aria-expanded={quickOpen}
            >
              {quickOpen ? 'Neue Übung ausblenden' : 'Neue Übung anlegen (Entwurf, privat)'}
            </button>
            {quickOpen ? (
              <div style={{ marginTop: '12px', display: 'grid', gap: '10px' }}>
                <p style={{ margin: 0, fontSize: '13px', color: 'var(--text2)', lineHeight: 1.45 }}>
                  Wird mit Sichtbarkeit <strong>privat</strong> und Status <strong>Entwurf</strong> gespeichert und
                  erscheint auf dem Dashboard zum Weiterbearbeiten. Nach dem Speichern wird die Übung direkt in den
                  Ablauf übernommen.
                </p>
                <div>
                  <label className="form-label" htmlFor="ex-picker-quick-title">
                    Titel
                  </label>
                  <input
                    id="ex-picker-quick-title"
                    type="text"
                    className="form-input"
                    value={quickTitle}
                    onChange={(e) => setQuickTitle(e.target.value)}
                    autoComplete="off"
                    minLength={3}
                    maxLength={300}
                    placeholder="z. B. Partnerübung Abwehr"
                  />
                </div>
                <div>
                  <label className="form-label" htmlFor="ex-picker-quick-summary">
                    Kurzbeschreibung
                  </label>
                  <textarea
                    id="ex-picker-quick-summary"
                    className="form-input"
                    rows={3}
                    value={quickSummary}
                    onChange={(e) => setQuickSummary(e.target.value)}
                    placeholder="Optional: grobe Idee, Kontext aus der Planung …"
                  />
                </div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', justifyContent: 'flex-end' }}>
                  <button
                    type="button"
                    className="btn btn-primary"
                    disabled={quickSaving || (quickTitle || '').trim().length < 3}
                    onClick={submitQuickCreate}
                  >
                    {quickSaving ? 'Wird angelegt…' : 'Entwurf anlegen und übernehmen'}
                  </button>
                </div>
              </div>
            ) : null}
          </div>
        ) : null}

        <div style={{ padding: '0 1rem 0.75rem', borderBottom: '1px solid var(--border)', flexShrink: 0 }}>
          <div style={{ display: 'grid', gap: '0.65rem' }}>
            <div>
              <label className="form-label">Volltextsuche</label>
              <input
                type="search"
                className="form-input"
                placeholder="Stichwort, Titelfragment…"
                value={searchInput}
                onChange={(e) => setSearchInput(e.target.value)}
                autoComplete="off"
              />
            </div>
            <div>
              <label className="form-label">
                Semantisch /{' '}
                <span title="aktuell gleiche Datenbanksuche wie Volltext; später KI-Verfeinerung möglich">KI-Feld</span>
              </label>
              <input
                type="search"
                className="form-input"
                placeholder="zweites Suchkonzept oder Umschreibung…"
                value={aiSearchInput}
                onChange={(e) => setAiSearchInput(e.target.value)}
                autoComplete="off"
              />
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem', alignItems: 'center' }}>
              <button type="button" className="btn btn-secondary" onClick={() => setFilterOpen(!filterOpen)}>
                {filterOpen ? 'Filter ausblenden' : 'Erweiterte Filter'}
              </button>
              <button type="button" className="btn" onClick={resetFilters}>
                Filter zurücksetzen
              </button>
              {loading && <span style={{ fontSize: '13px', color: 'var(--text2)' }}>Suche läuft…</span>}
            </div>

            {filterOpen && (
              <div style={{ marginTop: '0.35rem', fontSize: '13px', color: 'var(--text2)' }}>
                  <p style={{ margin: '0 0 12px 0' }}>
                  Felder gelten mit <strong>UND</strong>. Kataloge: mehrere „+“ = alle zutreffend; „−“ schließt aus.
                  Sichtbarkeit/Status: mehrere „+“ = eine davon (ODER); „−“ blendet aus.
                </p>
                <ExerciseFocusRulePicker
                  focusOptions={focusOptions}
                  focusRules={filters.focus_rules}
                  focusOnlyWithout={filters.focus_only_without}
                  legacyFocusAreaIds={filters.focus_area_ids}
                  onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                />
                <div className="exercise-filters-modal-grid exercise-filters-modal-grid--catalog" style={{ marginTop: 12 }}>
                  <CatalogRulePicker
                    label="Stilrichtung"
                    hint="+ alle nötig (UND). − verbietet Zuordnung."
                    options={styleOptions}
                    rules={filters.style_direction_rules}
                    rulesFieldName="style_direction_rules"
                    placeholder="Stil …"
                    onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                  />
                  <CatalogRulePicker
                    label="Trainingsstil"
                    hint="+ alle nötig (UND). − verbietet Zuordnung."
                    options={trainingTypeOptions}
                    rules={filters.training_type_rules}
                    rulesFieldName="training_type_rules"
                    placeholder="Trainingsstil …"
                    onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                  />
                  <CatalogRulePicker
                    label="Zielgruppe"
                    hint="+ alle nötig (UND). − verbietet Zuordnung."
                    options={targetGroupOptions}
                    rules={filters.target_group_rules}
                    rulesFieldName="target_group_rules"
                    placeholder="Gruppe …"
                    onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                  />
                </div>
                <div style={{ marginTop: 12 }}>
                  <label className="form-label">Fähigkeit</label>
                  <SkillTreeMultiSelect
                    value={filters.skill_ids}
                    onChange={(v) => setFilters((f) => ({ ...f, skill_ids: v }))}
                    skills={catalogs.skills}
                    placeholder="Fähigkeit …"
                  />
                  <div className="exercise-filter-skill-levels-row" style={{ marginTop: 8 }}>
                    <select
                      className="form-input exercise-filter-level-select"
                      title="von"
                      value={filters.skill_min_level}
                      onChange={(e) => setFilters((f) => ({ ...f, skill_min_level: e.target.value }))}
                    >
                      <option value="">Stufe von</option>
                      {LEVEL_FILTER_OPTS.map((o) => (
                        <option key={o.value} value={String(o.level)}>
                          {o.level}
                        </option>
                      ))}
                    </select>
                    <select
                      className="form-input exercise-filter-level-select"
                      title="bis"
                      value={filters.skill_max_level}
                      onChange={(e) => setFilters((f) => ({ ...f, skill_max_level: e.target.value }))}
                    >
                      <option value="">Stufe bis</option>
                      {LEVEL_FILTER_OPTS.map((o) => (
                        <option key={`m-${o.value}`} value={String(o.level)}>
                          {o.level}
                        </option>
                      ))}
                    </select>
                  </div>
                </div>
                <div className="exercise-filters-modal-grid exercise-filters-modal-grid--two exercise-filters-modal-grid--catalog" style={{ marginTop: 12 }}>
                  <CatalogRulePicker
                    label="Sichtbarkeit"
                    options={visibilityOptions}
                    rules={filters.visibility_rules}
                    rulesFieldName="visibility_rules"
                    idKind="string"
                    placeholder="Sichtbarkeit …"
                    onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                  />
                  <CatalogRulePicker
                    label="Status"
                    options={statusOptions}
                    rules={filters.status_rules}
                    rulesFieldName="status_rules"
                    idKind="string"
                    placeholder="Status …"
                    onPatch={(patch) => setFilters((f) => ({ ...f, ...patch }))}
                  />
                </div>
                <div style={{ marginTop: 12, display: 'flex', flexDirection: 'column', gap: 10 }}>
                  <label
                    style={{
                      display: 'flex',
                      alignItems: 'center',
                      gap: 8,
                      cursor: filters.focus_only_without ? 'not-allowed' : 'pointer',
                      opacity: filters.focus_only_without ? 0.55 : 1,
                    }}
                  >
                    <input
                      type="checkbox"
                      disabled={!!filters.focus_only_without}
                      checked={!!filters.exclude_without_focus}
                      onChange={(e) =>
                        setFilters((f) => ({
                          ...f,
                          exclude_without_focus: e.target.checked,
                          ...(e.target.checked ? { focus_only_without: false } : {}),
                        }))
                      }
                    />
                    <span>Ohne Fokus ausblenden</span>
                  </label>
                  <p style={{ margin: 0, fontSize: '12px', color: 'var(--text2)' }}>
                    Hinweis: Für die Planung werden archivierte Übungen bei der Suche immer mit eingeschlossen (bestehende
                    Zuordnungen).
                  </p>
                </div>
              </div>
            )}
          </div>
        </div>

        <div
          ref={pickerScrollRef}
          data-testid="exercise-picker-scroll"
          style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '12px 1rem' }}
        >
          {!catalogsReady || (loading && list.length === 0) ? (
            <div style={{ textAlign: 'center', padding: '2rem' }}>
              <div className="spinner" />
            </div>
          ) : list.length === 0 ? (
            <p style={{ color: 'var(--text2)', textAlign: 'center' }}>Keine Treffer.</p>
          ) : (
            <>
              <p style={{ fontSize: '13px', color: 'var(--text2)', marginBottom: 10 }}>
                {list.length} angezeigt{hasMore ? ' · weiter unten „Mehr laden“' : ''}
              </p>
              <div
                role="list"
                aria-label="Übungstreffer"
                style={{
                  position: 'relative',
                  width: '100%',
                  height: rowVirtualizer.getTotalSize(),
                }}
              >
                {rowVirtualizer.getVirtualItems().map((vi) => {
                  const ex = list[vi.index]
                  if (!ex) return null
                  const picked = multiPicked.some((p) => p.id === ex.id)
                  const rowInner = (
                    <>
                      <strong style={{ display: 'block' }}>{ex.title}</strong>
                      {(ex.summary || '').trim().length > 0 && (
                        <span style={{ fontSize: '12px', color: 'var(--text2)' }}>
                          {(ex.summary || '').length > 120
                            ? `${(ex.summary || '').slice(0, 120)}…`
                            : ex.summary}
                        </span>
                      )}
                      {ex.focus_area && (
                        <span className="exercise-tag exercise-tag--accent" style={{ marginTop: 6 }}>
                          {ex.focus_area}
                        </span>
                      )}
                      {(ex.exercise_kind || '').toLowerCase().trim() === 'combination' ? (
                        <span
                          className="exercise-tag"
                          style={{
                            marginTop: 6,
                            marginLeft: 6,
                            background: 'var(--accent-soft)',
                            color: 'var(--accent-dark)',
                          }}
                        >
                          Kombination
                        </span>
                      ) : null}
                    </>
                  )
                  return (
                    <div
                      key={vi.key}
                      role="listitem"
                      data-index={vi.index}
                      ref={rowVirtualizer.measureElement}
                      style={{
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        width: '100%',
                        transform: `translateY(${vi.start}px)`,
                        paddingBottom: 8,
                      }}
                    >
                      {multiSelect ? (
                        <label
                          className="tu-ex-picker-multi-row"
                          style={{
                            display: 'flex',
                            gap: '10px',
                            alignItems: 'flex-start',
                            width: '100%',
                            textAlign: 'left',
                            padding: '10px 12px',
                            borderRadius: '8px',
                            border: picked ? '2px solid var(--accent)' : '1px solid var(--border)',
                            background: 'var(--surface2)',
                            cursor: 'pointer',
                            boxSizing: 'border-box',
                          }}
                        >
                          <input
                            type="checkbox"
                            checked={picked}
                            onChange={() => toggleMultiPick(ex)}
                            style={{ marginTop: '0.35rem', flexShrink: 0 }}
                            aria-label={ex.title ? `Auswahl: ${ex.title}` : 'Auswahl'}
                          />
                          <div style={{ flex: 1, minWidth: 0 }}>{rowInner}</div>
                        </label>
                      ) : (
                        <button
                          type="button"
                          onClick={() => {
                            onSelectExercise(ex)
                            onClose()
                          }}
                          style={{
                            width: '100%',
                            textAlign: 'left',
                            padding: '10px 12px',
                            borderRadius: '8px',
                            border: '1px solid var(--border)',
                            background: 'var(--surface2)',
                            cursor: 'pointer',
                          }}
                        >
                          {rowInner}
                        </button>
                      )}
                    </div>
                  )
                })}
              </div>
              {hasMore && (
                <div style={{ textAlign: 'center', marginTop: 12 }}>
                  <button type="button" className="btn btn-secondary" disabled={loadingMore} onClick={loadMore}>
                    {loadingMore ? 'Laden…' : 'Mehr laden'}
                  </button>
                </div>
              )}
              {multiSelect && typeof onSelectExercises === 'function' ? (
                <div
                  className="exercise-picker-multi-footer"
                  style={{
                    position: 'sticky',
                    bottom: 0,
                    marginTop: 16,
                    paddingTop: 12,
                    borderTop: '1px solid var(--border)',
                    background: 'var(--surface)',
                    display: 'flex',
                    flexWrap: 'wrap',
                    gap: '10px',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                  }}
                >
                  <span style={{ fontSize: '0.92rem', color: 'var(--text2)' }}>
                    {multiPicked.length} ausgewählt
                  </span>
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
                    <button
                      type="button"
                      className="btn btn-secondary"
                      onClick={() => setMultiPicked([])}
                      disabled={!multiPicked.length}
                    >
                      Auswahl leeren
                    </button>
                    <button
                      type="button"
                      className="btn btn-primary"
                      disabled={!multiPicked.length}
                      onClick={() => {
                        onSelectExercises([...multiPicked])
                        onClose()
                      }}
                    >
                      Übernehmen
                    </button>
                  </div>
                </div>
              ) : null}
            </>
          )}
        </div>
      </div>
    </div>
  )
}
