import React, { useState, useEffect, useMemo, useCallback, useRef, lazy, Suspense } from 'react'
import { Link } from 'react-router-dom'
import api from '../../utils/api'
import { useAuth } from '../../context/AuthContext'
import { activeClubMemberships, getTenantClubDependencyKey } from '../../utils/activeClub'
import PageSectionNav from '../PageSectionNav'
import ExerciseListCard from './ExerciseListCard'
import ExerciseListFilterModal from './ExerciseListFilterModal'
import ExerciseListBulkModal from './ExerciseListBulkModal'
import ExerciseListSearchBar from './ExerciseListSearchBar'
import ExerciseListBulkToolbar from './ExerciseListBulkToolbar'
import SaveSelectedExercisesAsModuleModal from './SaveSelectedExercisesAsModuleModal'
import ExercisePeekModal from '../ExercisePeekModal'
import { buildExercisesListReturnContext } from '../../utils/navReturnContext'
import { buildExerciseListFilterChips } from '../../utils/exerciseListFilterChips'
import { applyDashboardExerciseListUrl, buildExerciseListQueryBase } from '../../utils/exerciseListQuery'
import { readExerciseListSessionState, writeExerciseListSessionState } from '../../utils/exerciseListSessionState'
import {
  mergeSelectedWithListEntries,
  normalizeSelectedEntries,
  snapshotExerciseForSelection,
} from '../../utils/exerciseListSelection'
import { useExerciseListCatalogsAndQuery } from '../../hooks/useExerciseListCatalogsAndQuery'
import {
  INITIAL_EXERCISE_LIST_FILTERS,
  mergeExerciseListPrefsFromApi,
  compactExerciseListPrefsPayload,
} from '../../constants/exerciseListFilters'

const ExerciseProgressionGraphPanel = lazy(() => import('../ExerciseProgressionGraphPanel'))

const BULK_MAX_IDS = 500
const EXERCISES_PAGE_TABS = [
  { id: 'list', label: 'Liste' },
  { id: 'progression', label: 'Progressionsgraphen' },
]

function ExercisesListPageRoot() {
  const { user, checkAuth } = useAuth()
  const isPlatformAdmin = user?.role === 'admin' || user?.role === 'superadmin'
  const isSuperadmin = user?.role === 'superadmin'
  const tenantClubDepKey = useMemo(() => getTenantClubDependencyKey(user), [user])

  const [mineOnly, setMineOnly] = useState(() => {
    try {
      const sp = new URLSearchParams(window.location.search)
      return sp.get('mine') === '1' || sp.get('created_by_me') === '1'
    } catch {
      return false
    }
  })

  const [searchInput, setSearchInput] = useState('')
  const [aiSearchInput, setAiSearchInput] = useState('')
  const [debouncedSearch, setDebouncedSearch] = useState('')
  const [debouncedAiSearch, setDebouncedAiSearch] = useState('')
  const [filters, setFilters] = useState(() => ({ ...INITIAL_EXERCISE_LIST_FILTERS }))
  const [filterModalOpen, setFilterModalOpen] = useState(false)
  const [savingExercisePrefs, setSavingExercisePrefs] = useState(false)
  const [pageTab, setPageTab] = useState('list')
  const prefsAppliedRef = useRef(false)

  const [selectedEntries, setSelectedEntries] = useState(() => [])
  const [bulkModalOpen, setBulkModalOpen] = useState(false)
  const [bulkVisibility, setBulkVisibility] = useState('')
  const [bulkStatus, setBulkStatus] = useState('')
  const [bulkClubSelect, setBulkClubSelect] = useState('')
  const [bulkClubManual, setBulkClubManual] = useState('')
  const [bulkSubmitting, setBulkSubmitting] = useState(false)
  const [bulkPatchFocusAreas, setBulkPatchFocusAreas] = useState(false)
  const [bulkFocusAreaIds, setBulkFocusAreaIds] = useState([])
  const [bulkPatchStyleDirections, setBulkPatchStyleDirections] = useState(false)
  const [bulkStyleDirectionIds, setBulkStyleDirectionIds] = useState([])
  const [bulkPatchTrainingTypes, setBulkPatchTrainingTypes] = useState(false)
  const [bulkTrainingTypeIds, setBulkTrainingTypeIds] = useState([])
  const [bulkPatchTargetGroups, setBulkPatchTargetGroups] = useState(false)
  const [bulkTargetGroupIds, setBulkTargetGroupIds] = useState([])
  const [peekExercise, setPeekExercise] = useState(null)
  const [saveModuleModalOpen, setSaveModuleModalOpen] = useState(false)

  useEffect(() => {
    if (!user?.id) return
    if (prefsAppliedRef.current) return
    const session = readExerciseListSessionState()
    const merged = mergeExerciseListPrefsFromApi(user.exercise_list_prefs)
    const filtersFromSession = session?.filters
    setFilters(applyDashboardExerciseListUrl(filtersFromSession ?? merged))
    if (session) {
      setSearchInput(session.searchInput || '')
      setAiSearchInput(session.aiSearchInput || '')
      setMineOnly(session.mineOnly)
      setSelectedEntries(normalizeSelectedEntries(session.selectedEntries))
    }
    try {
      const sp = new URLSearchParams(window.location.search)
      if (sp.get('mine') === '1' || sp.get('created_by_me') === '1') setMineOnly(true)
    } catch {
      /* ignore */
    }
    prefsAppliedRef.current = true
  }, [user?.id, user?.exercise_list_prefs])

  useEffect(() => {
    if (!prefsAppliedRef.current) return
    writeExerciseListSessionState({
      filters,
      searchInput,
      aiSearchInput,
      mineOnly,
      selectedEntries,
    })
  }, [filters, searchInput, aiSearchInput, mineOnly, selectedEntries])

  useEffect(() => {
    if (!user?.id) prefsAppliedRef.current = false
  }, [user?.id])

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

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

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

  const queryBase = useMemo(
    () => buildExerciseListQueryBase(filters, debouncedSearch, debouncedAiSearch, mineOnly),
    [filters, debouncedSearch, debouncedAiSearch, mineOnly]
  )

  const {
    catalogs,
    catalogsReady,
    exercises,
    setExercises,
    listFetching,
    loadingMore,
    hasMore,
    loadMore,
  } = useExerciseListCatalogsAndQuery({ queryBase, pageTab, tenantClubDepKey })

  const selectedIds = useMemo(
    () => new Set(selectedEntries.map((e) => Number(e.id)).filter((id) => Number.isFinite(id) && id > 0)),
    [selectedEntries]
  )

  const selectedExercisesDisplay = useMemo(
    () => mergeSelectedWithListEntries(selectedEntries, exercises),
    [selectedEntries, exercises]
  )

  const filterResultExercises = useMemo(
    () => exercises.filter((e) => !selectedIds.has(Number(e.id))),
    [exercises, selectedIds]
  )

  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 skillOptions = useMemo(
    () => catalogs.skills.map((s) => ({ id: s.id, label: s.name || String(s.id) })),
    [catalogs.skills]
  )
  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 filterChips = useMemo(
    () =>
      buildExerciseListFilterChips({
        mineOnly,
        setMineOnly,
        filters,
        setFilters,
        focusOptions,
        styleOptions,
        trainingTypeOptions,
        targetGroupOptions,
        skillOptions,
        visibilityOptions,
        statusOptions,
      }),
    [
      mineOnly,
      filters,
      focusOptions,
      styleOptions,
      trainingTypeOptions,
      targetGroupOptions,
      skillOptions,
      visibilityOptions,
      statusOptions,
    ]
  )

  /** Für Browser-/datalist-Vorschläge (aktuelle Treffer-Titel, begrenzt) */
  const searchTitleSuggestions = useMemo(() => {
    const titles = exercises.map((e) => (e.title || '').trim()).filter(Boolean)
    return [...new Set(titles)].slice(0, 80)
  }, [exercises])

  const clubNameById = useMemo(() => {
    const m = {}
    for (const c of activeClubMemberships(user?.clubs)) {
      if (c?.id != null) m[Number(c.id)] = c.name || `#${c.id}`
    }
    return m
  }, [user?.clubs])

  const effectiveClubId =
    user?.effective_club_id != null && user.effective_club_id !== ''
      ? Number(user.effective_club_id)
      : user?.active_club_id != null && user.active_club_id !== ''
        ? Number(user.active_club_id)
        : null

  const toggleSelect = useCallback((exercise) => {
    const snap = snapshotExerciseForSelection(exercise)
    if (!snap) return
    setSelectedEntries((prev) => {
      const idx = prev.findIndex((e) => Number(e.id) === snap.id)
      if (idx >= 0) return prev.filter((_, i) => i !== idx)
      return [...prev, snap]
    })
  }, [])

  const clearSelection = useCallback(() => setSelectedEntries([]), [])

  const toggleSelectAllPage = useCallback(() => {
    setSelectedEntries((prev) => {
      const ids = new Set(prev.map((e) => Number(e.id)))
      const pageIds = filterResultExercises.map((e) => Number(e.id))
      const allSel = pageIds.length > 0 && pageIds.every((id) => ids.has(id))
      if (allSel) {
        const remove = new Set(pageIds)
        return prev.filter((e) => !remove.has(Number(e.id)))
      }
      const next = [...prev]
      for (const ex of filterResultExercises) {
        const snap = snapshotExerciseForSelection(ex)
        if (!snap || ids.has(snap.id)) continue
        ids.add(snap.id)
        next.push(snap)
      }
      return next
    })
  }, [filterResultExercises])

  const allOnPageSelected = useMemo(
    () =>
      filterResultExercises.length > 0 &&
      filterResultExercises.every((e) => selectedIds.has(Number(e.id))),
    [filterResultExercises, selectedIds]
  )

  const selectedExercisesInListOrder = selectedExercisesDisplay

  const exercisesModuleReturnContext = useMemo(() => buildExercisesListReturnContext(), [])

  const bulkVisibilityOptions = useMemo(() => {
    const base = [
      { id: '', label: '— nicht ändern —' },
      { id: 'private', label: 'Privat' },
      { id: 'club', label: 'Verein' },
    ]
    if (isSuperadmin) base.push({ id: 'official', label: 'Offiziell (global)' })
    return base
  }, [isSuperadmin])

  const handleDelete = async (exercise) => {
    if (!confirm(`Übung "${exercise.title}" wirklich löschen?`)) return
    try {
      await api.deleteExercise(exercise.id)
      setExercises((prev) => prev.filter((e) => e.id !== exercise.id))
      setSelectedEntries((prev) => prev.filter((e) => Number(e.id) !== Number(exercise.id)))
    } catch (err) {
      alert('Fehler beim Löschen: ' + err.message)
    }
  }

  const resetAllFilters = useCallback(() => {
    setMineOnly(false)
    setFilters({ ...INITIAL_EXERCISE_LIST_FILTERS })
  }, [])

  const handleSaveExerciseFilterPrefs = useCallback(async () => {
    const uid = user?.id
    if (!uid) {
      alert('Nicht angemeldet.')
      return
    }
    setSavingExercisePrefs(true)
    try {
      const payload = compactExerciseListPrefsPayload(filters)
      await api.updateProfile(uid, { exercise_list_prefs: payload })
      await checkAuth()
      alert('Standardfilter für die Übungsliste gespeichert.')
    } catch (e) {
      alert('Speichern fehlgeschlagen: ' + (e.message || String(e)))
    } finally {
      setSavingExercisePrefs(false)
    }
  }, [user?.id, filters, checkAuth])

  const openBulkModal = () => {
    setBulkVisibility('')
    setBulkStatus('')
    setBulkClubSelect('')
    setBulkClubManual('')
    setBulkPatchFocusAreas(false)
    setBulkFocusAreaIds([])
    setBulkPatchStyleDirections(false)
    setBulkStyleDirectionIds([])
    setBulkPatchTrainingTypes(false)
    setBulkTrainingTypeIds([])
    setBulkPatchTargetGroups(false)
    setBulkTargetGroupIds([])
    setBulkModalOpen(true)
  }

  const handleBulkSubmit = async () => {
    const anyRelationPatch =
      bulkPatchFocusAreas ||
      bulkPatchStyleDirections ||
      bulkPatchTrainingTypes ||
      bulkPatchTargetGroups
    if (!bulkVisibility && !bulkStatus && !anyRelationPatch) {
      alert(
        'Bitte mindestens eine Änderung wählen (Sichtbarkeit, Status oder eine der Zuordnungen mit gesetztem Häkchen „ersetzen“).'
      )
      return
    }
    const ids = Array.from(selectedIds).filter((x) => Number.isFinite(x) && x > 0)
    if (ids.length === 0) {
      alert('Keine Übungen ausgewählt.')
      return
    }
    if (ids.length > BULK_MAX_IDS) {
      alert(`Maximal ${BULK_MAX_IDS} Übungen pro Vorgang. Bitte Auswahl oder mehrere Durchläufe verwenden.`)
      return
    }
    const payload = { exercise_ids: ids }
    if (bulkVisibility) payload.visibility = bulkVisibility
    if (bulkStatus) payload.status = bulkStatus
    if (bulkPatchFocusAreas) {
      payload.focus_area_ids = bulkFocusAreaIds.map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0)
    }
    if (bulkPatchStyleDirections) {
      payload.style_direction_ids = bulkStyleDirectionIds.map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0)
    }
    if (bulkPatchTrainingTypes) {
      payload.training_type_ids = bulkTrainingTypeIds.map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0)
    }
    if (bulkPatchTargetGroups) {
      payload.target_group_ids = bulkTargetGroupIds.map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0)
    }
    if (bulkVisibility === 'club') {
      const manual = String(bulkClubManual || '').trim()
      if (manual && /^\d+$/.test(manual)) payload.club_id = Number(manual)
      else if (bulkClubSelect && /^\d+$/.test(String(bulkClubSelect))) {
        payload.club_id = Number(bulkClubSelect)
      }
    }
    setBulkSubmitting(true)
    try {
      const res = await api.bulkPatchExercisesMetadata(payload)
      const updatedSet = new Set((res.updated || []).map((x) => Number(x)))
      let resolvedClubId = null
      if (bulkVisibility === 'club') {
        if (payload.club_id != null) resolvedClubId = payload.club_id
        else if (effectiveClubId != null && !Number.isNaN(effectiveClubId)) resolvedClubId = effectiveClubId
      }
      const clubLabel =
        resolvedClubId != null ? clubNameById[resolvedClubId] || `Verein #${resolvedClubId}` : null

      let nextPrimaryFocusName = null
      if (bulkPatchFocusAreas) {
        const faNums = bulkFocusAreaIds.map((x) => Number(x)).filter((n) => Number.isFinite(n) && n > 0)
        if (faNums.length > 0) {
          const opt = focusOptions.find((o) => Number(o.id) === Number(faNums[0]))
          nextPrimaryFocusName = String(opt?.label ?? '').trim() || String(faNums[0])
        }
      }

      setExercises((prev) =>
        prev.map((e) => {
          if (!updatedSet.has(Number(e.id))) return e
          const next = { ...e }
          if (bulkVisibility) {
            next.visibility = bulkVisibility
            next.club_id = bulkVisibility === 'club' ? resolvedClubId : null
            next.club_name = bulkVisibility === 'club' ? clubLabel : null
          }
          if (bulkStatus) next.status = bulkStatus
          if (bulkPatchFocusAreas) {
            if (nextPrimaryFocusName == null) delete next.focus_area
            else next.focus_area = nextPrimaryFocusName
          }
          return next
        })
      )

      let msg = `${res.updated_count ?? updatedSet.size} Übung(en) aktualisiert.`
      if (res.failed_count) msg += `\n${res.failed_count} nicht geändert (siehe Details).`
      if (Array.isArray(res.failed) && res.failed.length) {
        msg +=
          '\n\n' +
          res.failed
            .slice(0, 12)
            .map((f) => `#${f.id}: ${f.detail}`)
            .join('\n')
        if (res.failed.length > 12) msg += '\n…'
      }
      alert(msg)
      setBulkModalOpen(false)
      clearSelection()
    } catch (err) {
      alert('Massenänderung fehlgeschlagen: ' + (err.message || String(err)))
    } finally {
      setBulkSubmitting(false)
    }
  }

  if (!catalogsReady && pageTab === 'list') {
    return (
      <div className="app-page">
        <div className="empty-state" style={{ padding: '2.5rem 1rem' }}>
          <div className="spinner" />
          <p className="muted" style={{ marginTop: '12px' }}>
            Lade Kataloge…
          </p>
        </div>
      </div>
    )
  }

  return (
    <div className="app-page">
      <div className="exercises-page__header">
        <h1 className="page-title exercises-page__title">Übungen</h1>
        {pageTab === 'list' ? (
          <Link to="/exercises/new" className="btn btn-primary">
            + Neu
          </Link>
        ) : (
          <span aria-hidden="true" />
        )}
      </div>

      <PageSectionNav
        ariaLabel="Übungen Bereiche"
        value={pageTab}
        onChange={setPageTab}
        items={EXERCISES_PAGE_TABS}
        className="exercises-page-toolbar-tabs"
      />

      {pageTab === 'progression' ? (
        <Suspense
          fallback={
            <div className="card empty-state" style={{ padding: '2rem 1rem' }}>
              <div className="spinner" />
              <p className="muted" style={{ marginTop: '12px' }}>
                Lade Progressionsgraphen…
              </p>
            </div>
          }
        >
          <ExerciseProgressionGraphPanel />
        </Suspense>
      ) : (
        <>
      <ExerciseListSearchBar
        searchTitleSuggestions={searchTitleSuggestions}
        searchInput={searchInput}
        onSearchInputChange={setSearchInput}
        aiSearchInput={aiSearchInput}
        onAiSearchInputChange={setAiSearchInput}
        mineOnly={mineOnly}
        onToggleMineOnly={() => setMineOnly((v) => !v)}
        onOpenFilter={() => setFilterModalOpen(true)}
        filterChips={filterChips}
        onResetAllFilters={resetAllFilters}
        exerciseCount={exercises.length}
        allOnPageSelected={allOnPageSelected}
        onToggleSelectAllPage={toggleSelectAllPage}
      />

      <ExerciseListBulkToolbar
        selectedCount={selectedIds.size}
        bulkMaxIds={BULK_MAX_IDS}
        onClearSelection={clearSelection}
        onOpenBulkModal={openBulkModal}
        onOpenSaveModuleModal={() => setSaveModuleModalOpen(true)}
      />

      <ExerciseListFilterModal
        open={filterModalOpen}
        onClose={() => setFilterModalOpen(false)}
        filters={filters}
        setFilters={setFilters}
        focusOptions={focusOptions}
        styleOptions={styleOptions}
        trainingTypeOptions={trainingTypeOptions}
        targetGroupOptions={targetGroupOptions}
        skillOptions={skillOptions}
        visibilityOptions={visibilityOptions}
        statusOptions={statusOptions}
        savingExercisePrefs={savingExercisePrefs}
        onSaveStandard={handleSaveExerciseFilterPrefs}
        onResetAll={resetAllFilters}
      />

      <ExerciseListBulkModal
        open={bulkModalOpen}
        onClose={() => setBulkModalOpen(false)}
        onSubmit={handleBulkSubmit}
        bulkSubmitting={bulkSubmitting}
        selectedCount={selectedIds.size}
        bulkMaxIds={BULK_MAX_IDS}
        user={user}
        isPlatformAdmin={isPlatformAdmin}
        statusOptions={statusOptions}
        bulkVisibilityOptions={bulkVisibilityOptions}
        focusOptions={focusOptions}
        styleOptions={styleOptions}
        trainingTypeOptions={trainingTypeOptions}
        targetGroupOptions={targetGroupOptions}
        bulkVisibility={bulkVisibility}
        setBulkVisibility={setBulkVisibility}
        bulkStatus={bulkStatus}
        setBulkStatus={setBulkStatus}
        bulkClubSelect={bulkClubSelect}
        setBulkClubSelect={setBulkClubSelect}
        bulkClubManual={bulkClubManual}
        setBulkClubManual={setBulkClubManual}
        bulkPatchFocusAreas={bulkPatchFocusAreas}
        setBulkPatchFocusAreas={setBulkPatchFocusAreas}
        bulkFocusAreaIds={bulkFocusAreaIds}
        setBulkFocusAreaIds={setBulkFocusAreaIds}
        bulkPatchStyleDirections={bulkPatchStyleDirections}
        setBulkPatchStyleDirections={setBulkPatchStyleDirections}
        bulkStyleDirectionIds={bulkStyleDirectionIds}
        setBulkStyleDirectionIds={setBulkStyleDirectionIds}
        bulkPatchTrainingTypes={bulkPatchTrainingTypes}
        setBulkPatchTrainingTypes={setBulkPatchTrainingTypes}
        bulkTrainingTypeIds={bulkTrainingTypeIds}
        setBulkTrainingTypeIds={setBulkTrainingTypeIds}
        bulkPatchTargetGroups={bulkPatchTargetGroups}
        setBulkPatchTargetGroups={setBulkPatchTargetGroups}
        bulkTargetGroupIds={bulkTargetGroupIds}
        setBulkTargetGroupIds={setBulkTargetGroupIds}
      />

      <SaveSelectedExercisesAsModuleModal
        open={saveModuleModalOpen}
        onClose={() => setSaveModuleModalOpen(false)}
        selectedExercises={selectedExercisesInListOrder}
        returnContext={exercisesModuleReturnContext}
        onSuccess={clearSelection}
      />

      <ExercisePeekModal
        open={peekExercise != null}
        exerciseId={peekExercise?.id}
        titleFallback={peekExercise?.title}
        onClose={() => setPeekExercise(null)}
      />

      {listFetching && exercises.length === 0 && selectedEntries.length === 0 ? (
        <div className="card empty-state" style={{ padding: '2rem 1rem' }}>
          <div className="spinner" />
          <p className="muted" style={{ marginTop: '12px' }}>
            Lade Übungen…
          </p>
        </div>
      ) : exercises.length === 0 && selectedEntries.length === 0 ? (
        <div className="card">
          <p className="exercises-empty-text">Keine Übungen gefunden.</p>
        </div>
      ) : (
        <>
          {selectedEntries.length > 0 ? (
            <section className="exercises-selection-section" data-testid="exercises-selection-section">
              <div className="exercises-selection-section__head">
                <h2 className="exercises-selection-section__title">Auswahl ({selectedEntries.length})</h2>
                <p className="exercises-selection-section__hint">
                  Bleibt sichtbar, auch wenn du den Filter wechselst — ideal für die Modul-Zusammenstellung.
                </p>
              </div>
              <div className="exercises-list-grid exercises-list-grid--selection">
                {selectedExercisesDisplay.map((exercise) => (
                  <ExerciseListCard
                    key={`sel-${exercise.id}`}
                    exercise={exercise}
                    user={user}
                    selectedIds={selectedIds}
                    toggleSelect={toggleSelect}
                    onDelete={handleDelete}
                    onPeek={(ex) => setPeekExercise({ id: ex.id, title: ex.title })}
                    selectionPinned
                  />
                ))}
              </div>
            </section>
          ) : null}

          {filterResultExercises.length === 0 ? (
            selectedEntries.length > 0 ? (
              <p className="exercises-meta-line exercises-meta-line--muted">
                Keine weiteren Treffer für den aktuellen Filter.
              </p>
            ) : null
          ) : (
            <>
              {listFetching ? (
                <p className="exercises-meta-line exercises-meta-line--muted">Aktualisiere Treffer…</p>
              ) : null}
              <p className="exercises-meta-line">
                {filterResultExercises.length} Treffer
                {selectedEntries.length > 0 ? ' (ohne bereits Ausgewählte)' : ''}
                {hasMore ? ' · es gibt weitere Einträge' : ''}
              </p>
              <div className="exercises-list-grid" data-testid="exercises-list-grid">
                {filterResultExercises.map((exercise) => (
                  <ExerciseListCard
                    key={exercise.id}
                    exercise={exercise}
                    user={user}
                    selectedIds={selectedIds}
                    toggleSelect={toggleSelect}
                    onDelete={handleDelete}
                    onPeek={(ex) => setPeekExercise({ id: ex.id, title: ex.title })}
                  />
                ))}
              </div>
              {hasMore && (
                <div className="exercises-load-more">
                  <button type="button" className="btn btn-secondary" disabled={loadingMore} onClick={loadMore}>
                    {loadingMore ? 'Laden…' : 'Mehr laden'}
                  </button>
                </div>
              )}
            </>
          )}
        </>
      )}
    </>
      )}
    </div>
  )
}

export default ExercisesListPageRoot
