import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { Link, useNavigate, useSearchParams } from 'react-router-dom'
import api from '../../utils/api'
import { useAuth } from '../../context/AuthContext'
import { useToast } from '../../context/ToastContext'
import { activeClubMemberships, getTenantClubDependencyKey } from '../../utils/activeClub'
import PageSectionNav from '../PageSectionNav'
import TrainingPlanningFrameworkImportModal from './TrainingPlanningFrameworkImportModal'
import TrainingPlanningTrainerAssignModal from './TrainingPlanningTrainerAssignModal'
import TrainingPublishToFrameworkModal from './TrainingPublishToFrameworkModal'
import SaveExercisesAsModuleModal from './SaveExercisesAsModuleModal'
import {
  addDaysIsoDate,
  pad2,
  toIsoLocal,
  mondayIndex,
  getCalendarGridRange,
  shiftCalendarMonth,
  enumerateIsoDays,
  WEEKDAYS_DE,
  toNumList,
  sessionAssignDefaults,
  normalizeGroupCoTrainerIds,
  filterDirectoryExcludingLead,
  frameworkLineageText,
} from '../../utils/trainingPlanningPageHelpers'
import {
  buildPlanUnitEditPath,
  buildPlanUnitNewPath,
  buildPlanningHubReturnState,
  legacyPlanningUnitDeepLinkTarget,
  parsePlanningHubQuery,
} from '../../utils/planningUnitRoutes'

function TrainingPlanningPageRoot() {
  const { user } = useAuth()
  const toast = useToast()
  const navigate = useNavigate()
  const tenantClubDepKey = useMemo(() => getTenantClubDependencyKey(user), [user])
  const [searchParams] = useSearchParams()
  const unitDeepLinkHandledRef = useRef(null)
  const hubQuerySyncedRef = useRef(false)
  const [groups, setGroups] = useState([])
  const [selectedGroupId, setSelectedGroupId] = useState('')
  const [units, setUnits] = useState([])
  const [loading, setLoading] = useState(true)
  const [publishFrameworkOpen, setPublishFrameworkOpen] = useState(false)
  /** Einheit für „Rahmen-Session“-Dialog (Liste oder geöffnetes Bearbeiten) */
  const [publishFrameworkUnitId, setPublishFrameworkUnitId] = useState(null)
  const [saveModuleOpen, setSaveModuleOpen] = useState(false)
  const [saveModuleUnitId, setSaveModuleUnitId] = useState(null)

  const today = new Date().toISOString().split('T')[0]
  const thirtyDaysLater = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]

  const [frameworkImportOpen, setFrameworkImportOpen] = useState(false)
  const [frameworkProgramsList, setFrameworkProgramsList] = useState([])
  const [fwImportProgramId, setFwImportProgramId] = useState('')
  const [fwImportDetail, setFwImportDetail] = useState(null)
  const [fwImportLoading, setFwImportLoading] = useState(false)
  const [fwImportSelectedSlots, setFwImportSelectedSlots] = useState(() => new Set())
  const [fwImportSlotDates, setFwImportSlotDates] = useState({})
  const [fwImportStartDate, setFwImportStartDate] = useState(today)
  const [fwImportIntervalDays, setFwImportIntervalDays] = useState(7)
  const [fwImportSubmitting, setFwImportSubmitting] = useState(false)

  const [startDate, setStartDate] = useState(today)
  const [endDate, setEndDate] = useState(thirtyDaysLater)
  const [planView, setPlanView] = useState('list')
  const [calendarMonthStr, setCalendarMonthStr] = useState(() => today.slice(0, 7))
  const [planScope, setPlanScope] = useState('group')
  const [assignedToMeOnly, setAssignedToMeOnly] = useState(false)
  const [clubDirectory, setClubDirectory] = useState([])
  const [assignModalOpen, setAssignModalOpen] = useState(false)
  const [assignDraft, setAssignDraft] = useState({
    unit: null,
    lead_trainer_profile_id: '',
    session_assistants_inherit: true,
    session_assistant_profile_ids: [],
  })
  const [assignSaving, setAssignSaving] = useState(false)

  const planningReturnState = useMemo(
    () =>
      buildPlanningHubReturnState({
        selectedGroupId,
        planView,
        calendarMonthStr,
        startDate,
        endDate,
        planScope,
        assignedToMeOnly,
      }),
    [selectedGroupId, planView, calendarMonthStr, startDate, endDate, planScope, assignedToMeOnly]
  )

  const navigateToEditUnit = useCallback(
    (unit, opts = {}) => {
      const id = typeof unit === 'object' ? unit?.id : unit
      if (id == null) return
      let path = buildPlanUnitEditPath(id)
      const debrief =
        opts.debrief === true ||
        opts.mode === 'debrief' ||
        searchParams.get('debrief') === '1' ||
        searchParams.get('debrief') === 'true'
      if (debrief) path += '?mode=debrief'
      navigate(path, { state: { planningReturn: planningReturnState } })
    },
    [navigate, planningReturnState, searchParams]
  )

  const loadData = useCallback(async () => {
    try {
      const groupsData = await api.listTrainingGroups({ status: 'active' })
      setGroups(groupsData)

      if (groupsData.length > 0) {
        setSelectedGroupId((prev) => {
          const prevStr = prev != null && prev !== '' ? String(prev) : ''
          const stillThere = prevStr && groupsData.some((g) => String(g.id) === prevStr)
          if (stillThere) return prevStr
          const ownGroup = groupsData.find((g) => g.trainer_id === user?.id)
          if (ownGroup) return String(ownGroup.id)
          if (groupsData.length === 1) return String(groupsData[0].id)
          return ''
        })
      } else {
        setSelectedGroupId('')
      }
    } catch (err) {
      console.error('Failed to load data:', err)
      toast.error('Fehler beim Laden: ' + err.message)
    } finally {
      setLoading(false)
    }
  }, [user?.id, toast])

  const loadUnits = useCallback(async () => {
    if (!selectedGroupId) return
    let start = startDate
    let end = endDate
    if (planView === 'calendar') {
      const r = getCalendarGridRange(calendarMonthStr)
      start = r.gridStart
      end = r.gridEnd
    }
    const gid = parseInt(selectedGroupId, 10)
    const groupRow = groups.find((g) => g.id === gid)
    const clubId = groupRow?.club_id
    try {
      const filters = {
        start_date: start,
        end_date: end
      }
      if (assignedToMeOnly) {
        filters.assigned_to_me = true
      }
      if (planScope === 'club' && clubId) {
        filters.club_id = clubId
      } else {
        filters.group_id = gid
      }
      const unitsData = await api.listTrainingUnits(filters)
      setUnits(unitsData)
    } catch (err) {
      console.error('Failed to load units:', err)
    }
  }, [
    selectedGroupId,
    groups,
    startDate,
    endDate,
    planView,
    calendarMonthStr,
    planScope,
    assignedToMeOnly
  ])

  useEffect(() => {
    loadData()
  }, [loadData, tenantClubDepKey])

  useEffect(() => {
    if (selectedGroupId) {
      loadUnits()
    }
  }, [selectedGroupId, loadUnits])

  const selectedGroupClubIdMemo = useMemo(() => {
    const g = groups.find((gr) => gr.id === parseInt(selectedGroupId, 10))
    return g?.club_id != null ? Number(g.club_id) : null
  }, [groups, selectedGroupId])

  const canClubOrgTraining = useMemo(() => {
    const r = (user?.role || '').toLowerCase()
    if (r === 'admin' || r === 'superadmin') return true
    if (selectedGroupClubIdMemo == null || !Number.isFinite(selectedGroupClubIdMemo)) return false
    const row = activeClubMemberships(user?.clubs).find((c) => Number(c.id) === selectedGroupClubIdMemo)
    return Array.isArray(row?.roles) && row.roles.includes('club_admin')
  }, [user?.role, user?.clubs, selectedGroupClubIdMemo])

  const clubAdminClubIdSet = useMemo(() => {
    const ids = []
    for (const c of activeClubMemberships(user?.clubs)) {
      if (Array.isArray(c.roles) && c.roles.includes('club_admin')) {
        const id = Number(c.id)
        if (Number.isFinite(id)) ids.push(id)
      }
    }
    return new Set(ids)
  }, [user?.clubs])

  useEffect(() => {
    let assignModalClubId = null
    if (assignModalOpen && assignDraft.unit?.group_id != null) {
      const ug = Number(assignDraft.unit.group_id)
      const gAssign = Number.isFinite(ug) ? groups.find((x) => x.id === ug) : null
      if (gAssign?.club_id != null) assignModalClubId = Number(gAssign.club_id)
    }

    const loadClubId =
      assignModalOpen && assignModalClubId != null && Number.isFinite(assignModalClubId)
        ? assignModalClubId
        : canClubOrgTraining && selectedGroupClubIdMemo != null && Number.isFinite(selectedGroupClubIdMemo)
          ? selectedGroupClubIdMemo
          : null

    if (loadClubId == null || !Number.isFinite(loadClubId)) {
      setClubDirectory([])
      return undefined
    }
    let cancelled = false
    ;(async () => {
      try {
        const d = await api.clubMembersDirectory(loadClubId)
        if (!cancelled) setClubDirectory(Array.isArray(d) ? d : [])
      } catch (err) {
        if (!cancelled) {
          console.error('Mitgliederverzeichnis:', err)
          setClubDirectory([])
        }
      }
    })()
    return () => {
      cancelled = true
    }
  }, [assignModalOpen, assignDraft.unit, groups, canClubOrgTraining, selectedGroupClubIdMemo])

  const listActionClubId = useMemo(() => {
    const uid = publishFrameworkUnitId ?? saveModuleUnitId
    if (uid == null) return selectedGroupClubIdMemo
    const u = units.find((x) => Number(x.id) === Number(uid))
    if (u?.group_club_id != null) {
      const c = Number(u.group_club_id)
      if (Number.isFinite(c)) return c
    }
    const gid = u?.group_id != null ? Number(u.group_id) : NaN
    if (Number.isFinite(gid)) {
      const g = groups.find((gr) => Number(gr.id) === gid)
      if (g?.club_id != null) {
        const c = Number(g.club_id)
        if (Number.isFinite(c)) return c
      }
    }
    return selectedGroupClubIdMemo
  }, [publishFrameworkUnitId, saveModuleUnitId, units, groups, selectedGroupClubIdMemo])

  useEffect(() => {
    if (!frameworkImportOpen) return
    let cancelled = false
    ;(async () => {
      try {
        const list = await api.listTrainingFrameworkPrograms()
        if (!cancelled) setFrameworkProgramsList(Array.isArray(list) ? list : [])
      } catch (e) {
        if (!cancelled) {
          console.error('Rahmenprogramme laden:', e)
          setFrameworkProgramsList([])
        }
      }
    })()
    return () => {
      cancelled = true
    }
  }, [frameworkImportOpen])

  const openFrameworkImportModal = useCallback(() => {
    setFwImportProgramId('')
    setFwImportDetail(null)
    setFwImportSelectedSlots(new Set())
    setFwImportSlotDates({})
    setFwImportStartDate(new Date().toISOString().split('T')[0])
    setFwImportIntervalDays(7)
    setFrameworkImportOpen(true)
  }, [])

  const onFwImportProgramChange = async (idStr) => {
    setFwImportProgramId(idStr)
    if (!idStr) {
      setFwImportDetail(null)
      return
    }
    setFwImportLoading(true)
    try {
      const d = await api.getTrainingFrameworkProgram(parseInt(idStr, 10))
      setFwImportDetail(d)
      setFwImportSelectedSlots(new Set())
      setFwImportSlotDates({})
    } catch (e) {
      toast.error(e.message || 'Rahmenprogramm laden fehlgeschlagen')
      setFwImportDetail(null)
    } finally {
      setFwImportLoading(false)
    }
  }

  const toggleFwImportSlot = (slot) => {
    if (!slot?.blueprint_training_unit_id) return
    const sid = slot.id
    setFwImportSelectedSlots((prev) => {
      const n = new Set(prev)
      if (n.has(sid)) n.delete(sid)
      else n.add(sid)
      return n
    })
  }

  const applyFwImportDateSuggestions = () => {
    if (!fwImportDetail?.slots?.length) return
    const sorted = [...fwImportDetail.slots].sort(
      (a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)
    )
    let offset = 0
    const iv = Math.max(0, Number(fwImportIntervalDays) || 0)
    const next = {}
    for (const s of sorted) {
      if (!fwImportSelectedSlots.has(s.id)) continue
      if (!s.blueprint_training_unit_id) continue
      next[String(s.id)] = addDaysIsoDate(fwImportStartDate, offset)
      offset += iv
    }
    setFwImportSlotDates((prev) => ({ ...prev, ...next }))
  }

  const submitFrameworkImport = async () => {
    if (!selectedGroupId) {
      toast.error('Bitte zuerst eine Trainingsgruppe wählen.')
      return
    }
    const gid = parseInt(selectedGroupId, 10)
    if (!fwImportDetail?.slots?.length) return
    const sorted = [...fwImportDetail.slots].sort(
      (a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)
    )
    const picks = sorted.filter(
      (s) => fwImportSelectedSlots.has(s.id) && s.blueprint_training_unit_id
    )
    if (!picks.length) {
      toast.error('Bitte mindestens eine Session mit Ablauf (Blueprint) auswählen.')
      return
    }
    for (const s of picks) {
      const key = String(s.id)
      const date = fwImportSlotDates[key] || fwImportStartDate
      if (!date) {
        toast.error('Bitte für jede ausgewählte Session ein Datum setzen (oder Datumsvorschläge nutzen).')
        return
      }
    }
    setFwImportSubmitting(true)
    try {
      for (const s of picks) {
        const key = String(s.id)
        const date = fwImportSlotDates[key] || fwImportStartDate
        await api.createTrainingUnitFromFrameworkSlot({
          group_id: gid,
          planned_date: date,
          framework_slot_id: s.id,
        })
      }
      setFrameworkImportOpen(false)
      await loadUnits()
    } catch (e) {
      toast.error(e.message || 'Übernahme fehlgeschlagen')
    } finally {
      setFwImportSubmitting(false)
    }
  }

  const handleCreate = () => {
    if (!selectedGroupId) {
      toast.error('Bitte wähle zuerst eine Trainingsgruppe')
      return
    }
    navigate(buildPlanUnitNewPath({ groupId: selectedGroupId, plannedDate: today }), {
      state: { planningReturn: planningReturnState },
    })
  }

  const handleCreateForDate = (isoDay) => {
    if (!selectedGroupId) {
      toast.error('Bitte wähle zuerst eine Trainingsgruppe')
      return
    }
    navigate(buildPlanUnitNewPath({ groupId: selectedGroupId, plannedDate: isoDay }), {
      state: { planningReturn: planningReturnState },
    })
  }

  const handleEdit = useCallback(
    (unit) => {
      navigateToEditUnit(unit)
    },
    [navigateToEditUnit]
  )

  useEffect(() => {
    if (!user?.id || loading) return
    const target = legacyPlanningUnitDeepLinkTarget(searchParams)
    if (!target) {
      unitDeepLinkHandledRef.current = null
      return
    }
    const uid = searchParams.get('unit')
    if (unitDeepLinkHandledRef.current === uid) return
    unitDeepLinkHandledRef.current = uid
    const returnState = buildPlanningHubReturnState(parsePlanningHubQuery(searchParams))
    navigate(target, { replace: true, state: { planningReturn: returnState } })
  }, [user?.id, loading, searchParams, navigate])

  useEffect(() => {
    if (loading) return
    if (searchParams.get('unit')) return
    const hasHubQuery = ['group', 'view', 'month', 'start', 'end', 'scope', 'mine'].some((k) =>
      searchParams.has(k)
    )
    if (!hasHubQuery) {
      hubQuerySyncedRef.current = false
      return
    }
    if (hubQuerySyncedRef.current) return
    hubQuerySyncedRef.current = true
    const q = parsePlanningHubQuery(searchParams)
    if (q.selectedGroupId) setSelectedGroupId(q.selectedGroupId)
    setPlanView(q.planView)
    if (q.calendarMonthStr) setCalendarMonthStr(q.calendarMonthStr)
    if (q.startDate) setStartDate(q.startDate)
    if (q.endDate) setEndDate(q.endDate)
    if (q.planScope) setPlanScope(q.planScope)
    setAssignedToMeOnly(q.assignedToMeOnly)
  }, [loading, searchParams])

  const handleTakeLead = async (unit) => {
    if (!user?.id) return
    try {
      await api.updateTrainingUnit(unit.id, { lead_trainer_profile_id: user.id })
      await loadUnits()
    } catch (err) {
      toast.error(err.message || 'Leitung konnte nicht übernommen werden')
    }
  }

  const openTrainerAssignModal = (unit) => {
    const effLead =
      unit.effective_lead_trainer_profile_id != null
        ? Number(unit.effective_lead_trainer_profile_id)
        : null
    let coIds = toNumList(unit.assistant_trainer_profile_ids)
    if (effLead != null && Number.isFinite(effLead)) {
      coIds = coIds.filter((id) => id !== effLead)
    }
    setAssignDraft({
      unit,
      lead_trainer_profile_id:
        unit.lead_trainer_profile_id != null && unit.lead_trainer_profile_id !== ''
          ? String(unit.lead_trainer_profile_id)
          : '',
      session_assistants_inherit:
        unit.assistant_trainer_profile_ids == null || unit.assistant_trainer_profile_ids === undefined,
      session_assistant_profile_ids: coIds,
    })
    setAssignModalOpen(true)
  }

  const saveTrainerAssignModal = async () => {
    if (!assignDraft.unit) return
    setAssignSaving(true)
    try {
      const payload = {}
      const leadStr = String(assignDraft.lead_trainer_profile_id || '').trim()
      if (leadStr) payload.lead_trainer_profile_id = parseInt(leadStr, 10)
      else payload.lead_trainer_profile_id = null
      if (assignDraft.session_assistants_inherit) {
        payload.assistant_trainer_profile_ids = null
      } else {
        payload.assistant_trainer_profile_ids = [...assignDraft.session_assistant_profile_ids].sort((a, b) => a - b)
      }
      await api.updateTrainingUnit(assignDraft.unit.id, payload)
      setAssignModalOpen(false)
      setAssignDraft({
        unit: null,
        ...sessionAssignDefaults(),
      })
      await loadUnits()
    } catch (err) {
      toast.error(err.message || 'Zuweisung konnte nicht gespeichert werden')
    } finally {
      setAssignSaving(false)
    }
  }

  const handleAssignLeadSelectChange = useCallback((v) => {
    setAssignDraft((prev) => {
      const exclude = []
      const tr = String(v || '').trim()
      if (tr !== '') {
        const n = parseInt(tr, 10)
        if (Number.isFinite(n)) exclude.push(n)
      } else if (prev.unit?.effective_lead_trainer_profile_id != null) {
        const ef = Number(prev.unit.effective_lead_trainer_profile_id)
        if (Number.isFinite(ef)) exclude.push(ef)
      }
      const exSet = new Set(exclude)
      const co = exclude.length
        ? prev.session_assistant_profile_ids.filter((x) => !exSet.has(x))
        : prev.session_assistant_profile_ids
      return { ...prev, lead_trainer_profile_id: v, session_assistant_profile_ids: co }
    })
  }, [])

  const handleAssignAssistantsInheritChange = useCallback((checked) => {
    setAssignDraft((prev) => ({
      ...prev,
      session_assistants_inherit: checked,
    }))
  }, [])

  const handleAssignCoTrainerToggle = useCallback((mid) => {
    setAssignDraft((prev) => {
      const was = prev.session_assistant_profile_ids.includes(mid)
      const nextIds = was
        ? prev.session_assistant_profile_ids.filter((x) => x !== mid)
        : [...prev.session_assistant_profile_ids, mid].sort((a, b) => a - b)
      return { ...prev, session_assistant_profile_ids: nextIds }
    })
  }, [])

  const handleDelete = async (unit) => {
    if (!confirm(`Trainingseinheit vom ${unit.planned_date} wirklich löschen?`)) return
    try {
      await api.deleteTrainingUnit(unit.id)
      await loadUnits()
    } catch (err) {
      toast.error('Fehler beim Löschen: ' + err.message)
    }
  }

  const calendarGridDays = useMemo(() => {
    const r = getCalendarGridRange(calendarMonthStr)
    return enumerateIsoDays(r.gridStart, r.gridEnd)
  }, [calendarMonthStr])

  const unitsByPlannedDate = useMemo(() => {
    const m = new Map()
    for (const u of units) {
      const raw = u.planned_date
      if (!raw) continue
      const key = String(raw).slice(0, 10)
      if (!m.has(key)) m.set(key, [])
      m.get(key).push(u)
    }
    return m
  }, [units])

  const calendarMonthTitle = useMemo(() => {
    const p = calendarMonthStr.split('-').map(Number)
    const y = p[0]
    const mo = p[1]
    if (!y || !mo) return ''
    return new Date(y, mo - 1, 1).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })
  }, [calendarMonthStr])

  const mayConfigureSessionAssignments = useCallback(
    (unit) => {
      if (!unit) return false
      const pid = Number(user?.id)
      if (!Number.isFinite(pid)) return false
      const r = (user?.role || '').toLowerCase()
      if (r === 'admin' || r === 'superadmin') return true

      const gClub = unit.group_club_id != null ? Number(unit.group_club_id) : null
      if (Number.isFinite(gClub) && clubAdminClubIdSet.has(gClub)) return true

      const gid = Number(unit.group_id)
      const g = groups.find((gr) => gr.id === gid)
      if (!g) return false

      const cb = unit.created_by != null ? Number(unit.created_by) : NaN
      if (Number.isFinite(cb) && cb === pid) return true

      const ht = g.trainer_id != null ? Number(g.trainer_id) : NaN
      if (Number.isFinite(ht) && ht === pid) return true

      return normalizeGroupCoTrainerIds(g.co_trainer_ids).includes(pid)
    },
    [user?.id, user?.role, groups, clubAdminClubIdSet]
  )

  if (loading) {
    return (
      <div className="app-page" style={{ padding: '2rem 0', textAlign: 'center' }}>
        <div className="spinner"></div>
        <p>Laden...</p>
      </div>
    )
  }

  const selectedGroup = groups.find((g) => g.id === parseInt(selectedGroupId, 10))

  let assignExcludeLeadPid = null
  if (assignModalOpen && assignDraft.unit) {
    const dl = String(assignDraft.lead_trainer_profile_id || '').trim()
    if (dl !== '') {
      const n = parseInt(dl, 10)
      assignExcludeLeadPid = Number.isFinite(n) ? n : null
    } else if (assignDraft.unit.effective_lead_trainer_profile_id != null) {
      const n = Number(assignDraft.unit.effective_lead_trainer_profile_id)
      assignExcludeLeadPid = Number.isFinite(n) ? n : null
    }
  }
  const clubDirectoryForAssignCo = filterDirectoryExcludingLead(clubDirectory, assignExcludeLeadPid)

  return (
    <>
        <h1 style={{ marginBottom: '0.35rem' }}>Trainingsplanung</h1>

        <div
          style={{
            display: 'flex',
            flexWrap: 'wrap',
            alignItems: 'center',
            gap: '12px',
            marginBottom: '1rem',
          }}
        >
          <span
            className="form-label"
            style={{
              marginBottom: 0,
              fontSize: '0.9rem',
              color: 'var(--text2)',
            }}
          >
            Ansicht
          </span>
          <PageSectionNav
            semantics="toggle"
            ariaLabel="Darstellung Liste oder Kalender"
            value={planView}
            onChange={(id) => {
              if (id === 'calendar') {
                setPlanView('calendar')
                setCalendarMonthStr((prev) => {
                  const fromList = (startDate || '').slice(0, 7)
                  if (/^\d{4}-\d{2}$/.test(fromList)) return fromList
                  return prev || new Date().toISOString().slice(0, 7)
                })
              } else {
                setPlanView('list')
              }
            }}
            items={[
              { id: 'list', label: 'Liste' },
              { id: 'calendar', label: 'Kalender' },
            ]}
            className="page-section-nav--inline planning-ansicht-nav"
          />
          <span style={{ fontSize: '0.8rem', color: 'var(--text3)', lineHeight: 1.35, maxWidth: '22rem' }}>
            {planView === 'list'
              ? 'Zeitraum unten mit Von/Bis filtern.'
              : 'Monat unten wechseln; Termine erscheinen im Raster.'}
          </span>
        </div>

        <p style={{ color: 'var(--text2)', fontSize: '0.95rem', marginBottom: '1.25rem' }}>
          Wähle eine Trainingsgruppe und lege <strong>Trainingseinheiten</strong> für den Zeitraum an (Inhalt: Abschnitte
          und Übungen). Rahmenprogramme, Module und Vorlagen erreichst du über die Registerkarten oben.
        </p>

        {!loading && groups.length === 0 && (
          <div
            className="card"
            style={{
              marginBottom: '1.25rem',
              borderLeft: '4px solid var(--accent)',
              padding: '1rem 1.25rem'
            }}
          >
            <h2 style={{ fontSize: '1.1rem', marginBottom: '0.5rem' }}>Erst Verein & Gruppe anlegen</h2>
            <p style={{ color: 'var(--text2)', marginBottom: '0.85rem', lineHeight: 1.5 }}>
              Ohne Trainingsgruppe kann hier nichts gebucht werden. Unter <strong>Vereine</strong> legst du einen Verein an
              (kurzer Name genügt), optional eine Sparte, dann eine <strong>Trainingsgruppe</strong>. Wochentage, feste Zeiten oder
              Eigenschaften sind optional und kannst du später ergänzen.
            </p>
            <Link to="/clubs" className="btn btn-primary" style={{ textDecoration: 'none' }}>
              Zu Vereinen & Trainingsgruppen
            </Link>
          </div>
        )}

        <div className="card" style={{ marginBottom: '1.5rem' }}>
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
              gap: '1rem'
            }}
          >
            <div>
              <label className="form-label">Trainingsgruppe</label>
              <select
                className="form-input"
                value={selectedGroupId}
                onChange={(e) => setSelectedGroupId(e.target.value)}
              >
                <option value="">Bitte wählen</option>
                {groups.map((g) => (
                  <option key={g.id} value={g.id}>
                    {g.name} ({g.club_name})
                  </option>
                ))}
              </select>
            </div>

            {planView === 'list' ? (
              <>
                <div>
                  <label className="form-label">Von</label>
                  <input
                    type="date"
                    className="form-input"
                    value={startDate}
                    onChange={(e) => setStartDate(e.target.value)}
                  />
                </div>

                <div>
                  <label className="form-label">Bis</label>
                  <input
                    type="date"
                    className="form-input"
                    value={endDate}
                    onChange={(e) => setEndDate(e.target.value)}
                  />
                </div>
              </>
            ) : (
              <div
                style={{
                  gridColumn: '1 / -1',
                  display: 'flex',
                  flexWrap: 'wrap',
                  alignItems: 'center',
                  gap: '0.65rem',
                }}
              >
                <button
                  type="button"
                  className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                  aria-label="Voriger Monat"
                  onClick={() => setCalendarMonthStr((prev) => shiftCalendarMonth(prev, -1))}
                >
                  ←
                </button>
                <span
                  style={{
                    fontWeight: 600,
                    fontSize: '1rem',
                    flex: '1 1 auto',
                    textAlign: 'center',
                    minWidth: '12rem',
                  }}
                >
                  {calendarMonthTitle}
                </span>
                <button
                  type="button"
                  className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                  aria-label="Nächster Monat"
                  onClick={() => setCalendarMonthStr((prev) => shiftCalendarMonth(prev, 1))}
                >
                  →
                </button>
                <button
                  type="button"
                  className="btn btn-secondary"
                  style={{ whiteSpace: 'nowrap', padding: '0.35rem 0.65rem', fontSize: '0.85rem' }}
                  onClick={() => setCalendarMonthStr(new Date().toISOString().slice(0, 7))}
                >
                  Aktueller Monat
                </button>
              </div>
            )}

            <div
              style={{
                gridColumn: '1 / -1',
                display: 'flex',
                flexWrap: 'wrap',
                alignItems: 'center',
                gap: '12px',
              }}
            >
              <span className="form-label" style={{ marginBottom: 0, alignSelf: 'center' }}>
                Einblenden
              </span>
              <PageSectionNav
                semantics="toggle"
                ariaLabel="Gruppe oder ganzer Verein"
                value={planScope}
                onChange={setPlanScope}
                items={[
                  { id: 'group', label: 'Nur diese Gruppe', disabled: !selectedGroupId },
                  { id: 'club', label: 'Ganzer Verein', disabled: !selectedGroupId },
                ]}
                className="page-section-nav--inline"
              />
              <label
                style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  gap: '8px',
                  fontSize: '0.88rem',
                  color: 'var(--text2)',
                  cursor: selectedGroupId ? 'pointer' : 'default',
                  opacity: selectedGroupId ? 1 : 0.65,
                }}
              >
                <input
                  type="checkbox"
                  checked={assignedToMeOnly}
                  disabled={!selectedGroupId}
                  onChange={(e) => setAssignedToMeOnly(e.target.checked)}
                />
                Nur meine Zuordnung (Leitung / Co)
              </label>
              <p
                style={{
                  fontSize: '0.78rem',
                  color: 'var(--text3)',
                  lineHeight: 1.45,
                  flex: '1 1 220px',
                  margin: 0,
                }}
              >
                Neue Termine gelten immer für die gewählte Gruppe. „Ganzer Verein“ zeigt zusätzlich Termine
                anderer Gruppen desselben Vereins.
              </p>
              <details className="planning-filter-help">
                <summary className="planning-filter-help__summary">Mehr zu Ansicht &amp; Trainerzuordnung</summary>
                <div className="planning-filter-help__body">
                  <p style={{ margin: '0 0 0.65rem' }}>
                    „Ganzer Verein“ bezieht sich auf denselben Verein wie die gewählte Gruppe. Neu angelegte Termine
                    beziehen sich weiterhin auf die Gruppe, die du oben gewählt hast.
                  </p>
                  {selectedGroupId ? (
                    <p style={{ margin: 0 }}>
                      Über <strong>Trainer</strong> oder <strong>Trainer zuweisen</strong> bearbeitest du Leitung und
                      Co je Einheit (berechtigt: Vereinsorganisation, Haupt-/Co‑Trainer der Gruppe sowie Erstellung
                      der Einheit). Das Mitgliederverzeichnis listet nur eigene Vereinsmitglieder; die Leitung erscheint
                      nicht unter Co‑Trainer.
                    </p>
                  ) : (
                    <p style={{ margin: 0, color: 'var(--text3)' }}>
                      Wähle zuerst eine Gruppe — dann erweitert sich die Hilfe zu Trainer und Berechtigungen.
                    </p>
                  )}
                </div>
              </details>
            </div>
          </div>

          {selectedGroup && (
            <div
              style={{
                marginTop: '1rem',
                padding: '1rem',
                background: 'var(--surface2)',
                borderRadius: '8px'
              }}
            >
              <p style={{ fontSize: '0.875rem', color: 'var(--text2)' }}>
                {selectedGroup.location || 'Kein Ort angegeben'}
                {selectedGroup.weekday && ` · ${selectedGroup.weekday}`}
                {selectedGroup.time_start &&
                  ` · ${selectedGroup.time_start.slice(0, 5)} - ${selectedGroup.time_end?.slice(0, 5)}`}
              </p>
            </div>
          )}

          <div className="training-planning-create training-planning-create--in-card">
            <div className="training-planning-create__intro">
              <h3 className="training-planning-create__title">Neue Trainingseinheit</h3>
              <p className="training-planning-create__lede">
                Datum, Zeiten und Ablauf (Abschnitte &amp; Übungen) — optional{' '}
                <strong>Trainingsvorlage</strong> oder Inhalte aus einem <strong>Rahmenprogramm</strong> im Dialog.
              </p>
              {!selectedGroupId && (
                <p className="training-planning-create__hint training-planning-create__hint--warn">
                  Wähle oben eine Trainingsgruppe, um fortzufahren.
                </p>
              )}
              {groups.length === 0 && (
                <p className="training-planning-create__hint training-planning-create__hint--warn">
                  Es gibt noch keine aktive Trainingsgruppe — unter{' '}
                  <Link to="/clubs">Vereine</Link> anlegen oder aktivieren.
                </p>
              )}
            </div>
            <div className="training-planning-create__actions">
              <button
                type="button"
                className="btn btn-primary training-planning-create__cta"
                disabled={!selectedGroupId}
                title={!selectedGroupId ? 'Zuerst eine Trainingsgruppe wählen' : undefined}
                onClick={handleCreate}
              >
                Trainingseinheit planen…
              </button>
              <button
                type="button"
                className="btn btn-secondary training-planning-create__secondary"
                disabled={!selectedGroupId}
                title={!selectedGroupId ? 'Zuerst eine Trainingsgruppe wählen' : undefined}
                onClick={openFrameworkImportModal}
              >
                Aus Rahmen übernehmen…
              </button>
            </div>
          </div>
        </div>

        {!selectedGroupId ? (
          <div className="card">
            <p style={{ color: 'var(--text2)', textAlign: 'center' }}>
              Wähle oben eine Trainingsgruppe — danach kannst du unter{' '}
              <strong>„Trainingseinheit planen…“</strong> einen Termin anlegen.
            </p>
          </div>
        ) : planView === 'calendar' ? (
          <div className="card" style={{ padding: 'clamp(8px, 2vw, 14px)', overflowX: 'auto' }}>
            {units.length === 0 ? (
              <p style={{ color: 'var(--text2)', fontSize: '0.88rem', margin: '0 0 12px', lineHeight: 1.45 }}>
                Im sichtbaren Monatsbereich liegt noch keine Einheit. Über <strong>+</strong> in einem Tag legst du einen
                neuen Termin mit Datum an.
              </p>
            ) : null}
            <div
              style={{
                display: 'grid',
                gridTemplateColumns: 'repeat(7, minmax(0, 1fr))',
                gap: '4px',
                minWidth: 'min(960px, 100%)',
              }}
              role="grid"
              aria-label={`Kalender ${calendarMonthTitle}`}
            >
              {WEEKDAYS_DE.map((w) => (
                <div
                  key={w}
                  style={{
                    fontWeight: 600,
                    fontSize: '0.72rem',
                    textAlign: 'center',
                    padding: '6px 2px',
                    color: 'var(--text3)',
                  }}
                  role="columnheader"
                >
                  {w}
                </div>
              ))}
              {calendarGridDays.map((dayIso) => {
                const inMonth = dayIso.slice(0, 7) === calendarMonthStr
                const dayNum = parseInt(dayIso.slice(8, 10), 10)
                const isTodayMarker = dayIso === today
                const dayUnits = unitsByPlannedDate.get(dayIso) || []
                return (
                  <div
                    key={dayIso}
                    role="gridcell"
                    style={{
                      minHeight: '96px',
                      border: '1px solid var(--border, rgba(0, 0, 0, 0.1))',
                      borderRadius: '6px',
                      padding: '5px',
                      background: inMonth ? 'var(--surface)' : 'var(--surface2)',
                      opacity: inMonth ? 1 : 0.58,
                      boxShadow: isTodayMarker ? 'inset 0 0 0 2px var(--accent-dark, #256)' : undefined,
                    }}
                  >
                    <div
                      style={{
                        display: 'flex',
                        justifyContent: 'space-between',
                        alignItems: 'flex-start',
                        gap: '4px',
                        marginBottom: '6px',
                      }}
                    >
                      <span style={{ fontWeight: 700, fontSize: '0.82rem', lineHeight: 1 }}>{dayNum}</span>
                      <button
                        type="button"
                        className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                        title={`Neue Trainingseinheit am ${dayIso}`}
                        aria-label={`Neue Trainingseinheit am ${dayIso}`}
                        onClick={() => handleCreateForDate(dayIso)}
                        disabled={!selectedGroupId}
                        style={{ padding: '2px 6px', flexShrink: 0 }}
                      >
                        +
                      </button>
                    </div>
                    <div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
                      {dayUnits.slice(0, 3).map((unit) => (
                        <div
                          key={unit.id}
                          style={{ display: 'flex', flexDirection: 'column', gap: '4px', width: '100%' }}
                        >
                          <button
                            type="button"
                            onClick={() => handleEdit(unit)}
                            title={[
                              planScope === 'club' && unit.group_name ? unit.group_name : '',
                              unit.planned_time_start?.slice(0, 5) || '',
                              unit.lead_trainer_name?.trim(),
                              unit.planned_focus?.trim(),
                              unit.status === 'completed'
                                ? 'Durchgeführt'
                                : unit.status === 'cancelled'
                                  ? 'Abgesagt'
                                  : 'Geplant',
                            ]
                              .filter(Boolean)
                              .join(' · ')}
                            style={{
                              border: 'none',
                              cursor: 'pointer',
                              textAlign: 'left',
                              padding: '4px 5px',
                              borderRadius: '4px',
                              fontSize: '0.7rem',
                              lineHeight: 1.25,
                              width: '100%',
                              borderLeftWidth: '3px',
                              borderLeftStyle: 'solid',
                              borderLeftColor:
                                unit.status === 'completed'
                                  ? '#2ea44f'
                                  : unit.status === 'cancelled'
                                    ? 'var(--danger)'
                                    : 'var(--accent-dark)',
                              background: 'var(--surface2)',
                              color: 'var(--text1)',
                            }}
                          >
                            <span style={{ fontWeight: 600 }}>
                              {unit.planned_time_start
                                ? `${unit.planned_time_start.slice(0, 5)}`
                                : 'Ganztags'}
                            </span>
                            {planScope === 'club' && (unit.group_name || '').trim() ? (
                              <span style={{ display: 'block', fontWeight: 500, color: 'var(--text1)' }}>
                                {(unit.group_name || '').trim().length > 22
                                  ? `${(unit.group_name || '').trim().slice(0, 22)}…`
                                  : unit.group_name}
                              </span>
                            ) : null}
                            {unit.lead_trainer_name?.trim() ? (
                              <span
                                style={{
                                  display: 'block',
                                  color: 'var(--text3)',
                                  fontWeight: 400,
                                  fontSize: '0.62rem',
                                }}
                              >
                                {unit.lead_trainer_name.trim().split(/\s+/).slice(-1)[0] ||
                                  unit.lead_trainer_name.trim()}
                              </span>
                            ) : null}
                            {unit.planned_focus?.trim() ? (
                              <span style={{ display: 'block', color: 'var(--text2)', fontWeight: 400 }}>
                                {(unit.planned_focus || '').trim().length > 24
                                  ? `${(unit.planned_focus || '').trim().slice(0, 24)}…`
                                  : unit.planned_focus}
                              </span>
                            ) : null}
                          </button>
                          {mayConfigureSessionAssignments(unit) ? (
                            <button
                              type="button"
                              className="btn btn-secondary framework-ctrl framework-ctrl--xs"
                              style={{ fontSize: '0.62rem', padding: '2px 4px', alignSelf: 'stretch' }}
                              onClick={(ev) => {
                                ev.stopPropagation()
                                openTrainerAssignModal(unit)
                              }}
                            >
                              Trainer
                            </button>
                          ) : null}
                        </div>
                      ))}
                    </div>
                    {dayUnits.length > 3 ? (
                      <p style={{ fontSize: '0.65rem', color: 'var(--text3)', margin: '4px 0 0', lineHeight: 1.3 }}>
                        +{dayUnits.length - 3} weitere
                      </p>
                    ) : null}
                  </div>
                )
              })}
            </div>
          </div>
        ) : units.length === 0 ? (
          <div className="card">
            <p style={{ color: 'var(--text2)', textAlign: 'center' }}>
              Keine Trainingseinheiten in diesem Zeitraum. Unten unter <strong>„Neue Trainingseinheit“</strong> einen
              Termin anlegen — optional mit Vorlage im Dialog.
            </p>
          </div>
        ) : (
          <div style={{ display: 'grid', gap: '1rem' }}>
            {units.map((unit) => {
              const lineage = unit.origin_framework_slot_id ? frameworkLineageText(unit) : null
              const uid = user?.id != null ? Number(user.id) : null
              const effLead =
                unit.effective_lead_trainer_profile_id != null
                  ? Number(unit.effective_lead_trainer_profile_id)
                  : null
              const showTakeLead =
                unit.status === 'planned' && uid != null && effLead != null && effLead !== uid
              return (
              <div key={unit.id} className="card">
                <div
                  style={{
                    display: 'flex',
                    flexWrap: 'wrap',
                    justifyContent: 'space-between',
                    alignItems: 'flex-start',
                    gap: '12px',
                    marginBottom: '1rem'
                  }}
                >
                  <div style={{ minWidth: 0, flex: '1 1 200px' }}>
                    <h3 style={{ marginBottom: '0.25rem' }}>
                      {unit.planned_date}
                      {unit.planned_time_start &&
                        ` · ${unit.planned_time_start.slice(0, 5)} - ${unit.planned_time_end?.slice(0, 5)}`}
                    </h3>
                    {planScope === 'club' && (unit.group_name || '').trim() ? (
                      <p
                        style={{
                          fontSize: '0.85rem',
                          color: 'var(--text3)',
                          margin: '0 0 0.35rem',
                        }}
                      >
                        {unit.group_name}
                      </p>
                    ) : null}
                    <p style={{ fontSize: '0.82rem', color: 'var(--text2)', margin: '0 0 0.5rem' }}>
                      Leitung: {(unit.lead_trainer_name || '').trim() || '—'}
                    </p>
                    {(() => {
                      const coRaw = unit.effective_assistant_trainer_profile_ids
                      const co = Array.isArray(coRaw)
                        ? coRaw.map(Number).filter((x) => Number.isFinite(x) && x >= 1)
                        : []
                      if (!co.length) return null
                      const src =
                        unit.assistant_trainer_profile_ids != null
                          ? 'Session-Zuweisung'
                          : 'über Trainingsgruppe'
                      return (
                        <p
                          style={{
                            fontSize: '0.78rem',
                            color: 'var(--text3)',
                            margin: '0 0 0.5rem',
                          }}
                        >
                          Co-Trainer ({src}): {co.length}
                        </p>
                      )
                    })()}
                    {unit.planned_focus && (
                      <p
                        style={{
                          color: 'var(--text2)',
                          fontSize: '0.875rem',
                          marginBottom: '0.5rem'
                        }}
                      >
                        Fokus: {unit.planned_focus}
                      </p>
                    )}
                    {lineage ? (
                      <p
                        style={{
                          color: 'var(--text2)',
                          fontSize: '0.82rem',
                          marginBottom: '0.5rem',
                          lineHeight: 1.45,
                        }}
                      >
                        <span style={{ fontWeight: 600, color: 'var(--text3)' }}>Aus Rahmen: </span>
                        {unit.origin_framework_program_id ? (
                          <Link
                            to={`/planning/framework-programs/${unit.origin_framework_program_id}`}
                            style={{ color: 'var(--accent-dark)' }}
                          >
                            {lineage.fpTitle}
                          </Link>
                        ) : (
                          <span>{lineage.fpTitle}</span>
                        )}
                        <span style={{ color: 'var(--text2)' }}> · {lineage.slotBit}</span>
                      </p>
                    ) : null}
                    <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap' }}>
                      <span
                        style={{
                          fontSize: '0.75rem',
                          padding: '0.25rem 0.5rem',
                          borderRadius: '4px',
                          background:
                            unit.status === 'completed'
                              ? '#2ea44f'
                              : unit.status === 'cancelled'
                                ? 'var(--danger)'
                                : 'var(--surface2)',
                          color:
                            unit.status === 'completed' || unit.status === 'cancelled'
                              ? 'white'
                              : 'var(--text2)'
                        }}
                      >
                        {unit.status === 'planned' && 'Geplant'}
                        {unit.status === 'completed' && 'Durchgeführt'}
                        {unit.status === 'cancelled' && 'Abgesagt'}
                      </span>
                      {unit.attendance_count !== null && unit.attendance_count !== undefined && (
                        <span
                          style={{
                            fontSize: '0.75rem',
                            padding: '0.25rem 0.5rem',
                            borderRadius: '4px',
                            background: 'var(--surface2)',
                            color: 'var(--text2)'
                          }}
                        >
                          {unit.attendance_count} Teilnehmer
                        </span>
                      )}
                    </div>
                  </div>

                  <div
                    style={{
                      display: 'flex',
                      gap: '0.5rem',
                      flexWrap: 'wrap',
                      justifyContent: 'flex-end',
                      flex: '1 1 180px',
                      minWidth: 0
                    }}
                  >
                    <Link
                      to={`/planning/run/${unit.id}`}
                      className="btn btn-secondary"
                      style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}
                    >
                      Plan &amp; Ablauf
                    </Link>
                    <Link
                      to={`/planning/run/${unit.id}/coach`}
                      className="btn btn-primary"
                      style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}
                    >
                      Im Training (Coach)
                    </Link>
                    <button className="btn btn-secondary" onClick={() => handleEdit(unit)}>
                      Bearbeiten
                    </button>
                    <button
                      type="button"
                      className="btn btn-secondary"
                      title="Gespeicherten Ablauf als Session eines Rahmenprogramms übernehmen"
                      onClick={() => {
                        setPublishFrameworkUnitId(unit.id)
                        setPublishFrameworkOpen(true)
                      }}
                    >
                      Rahmen-Session…
                    </button>
                    <button
                      type="button"
                      className="btn btn-secondary"
                      title="Gespeicherte Übungen aus dieser Einheit als Trainingsmodul speichern"
                      onClick={() => {
                        setSaveModuleUnitId(unit.id)
                        setSaveModuleOpen(true)
                      }}
                    >
                      Übungen → Modul…
                    </button>
                    {mayConfigureSessionAssignments(unit) ? (
                      <button
                        type="button"
                        className="btn btn-secondary"
                        onClick={() => openTrainerAssignModal(unit)}
                        title="Nur organisatorisch: Leitung und Co für diese Einheit"
                      >
                        Trainer zuweisen
                      </button>
                    ) : null}
                    {showTakeLead ? (
                      <button type="button" className="btn btn-secondary" onClick={() => handleTakeLead(unit)}>
                        Ich übernehme
                      </button>
                    ) : null}
                    <button
                      className="btn"
                      style={{ background: 'var(--danger)', color: 'white', border: 'none' }}
                      onClick={() => handleDelete(unit)}
                    >
                      Löschen
                    </button>
                  </div>
                </div>

                {unit.notes && (
                  <p style={{ color: 'var(--text2)', fontSize: '0.875rem', marginTop: '0.5rem' }}>
                    {unit.notes}
                  </p>
                )}
              </div>
              )
            })}
          </div>
        )}

        <TrainingPlanningTrainerAssignModal
          open={assignModalOpen && !!assignDraft.unit}
          unit={assignDraft.unit}
          leadTrainerProfileId={assignDraft.lead_trainer_profile_id}
          onLeadChange={handleAssignLeadSelectChange}
          sessionAssistantsInherit={assignDraft.session_assistants_inherit}
          onSessionAssistantsInheritChange={handleAssignAssistantsInheritChange}
          sessionAssistantProfileIds={assignDraft.session_assistant_profile_ids}
          onCoTrainerToggle={handleAssignCoTrainerToggle}
          clubDirectory={clubDirectory}
          coTrainerOptions={clubDirectoryForAssignCo}
          saving={assignSaving}
          onBackdropRequestClose={() => {
            if (!assignSaving) setAssignModalOpen(false)
          }}
          onCancel={() => setAssignModalOpen(false)}
          onSave={saveTrainerAssignModal}
        />

        <TrainingPlanningFrameworkImportModal
          open={frameworkImportOpen}
          frameworkProgramsList={frameworkProgramsList}
          fwImportProgramId={fwImportProgramId}
          onProgramChange={onFwImportProgramChange}
          fwImportLoading={fwImportLoading}
          fwImportDetail={fwImportDetail}
          fwImportSelectedSlots={fwImportSelectedSlots}
          onToggleSlot={toggleFwImportSlot}
          fwImportSlotDates={fwImportSlotDates}
          onSlotDateChange={(slotId, value) =>
            setFwImportSlotDates((prev) => ({ ...prev, [slotId]: value }))
          }
          fwImportStartDate={fwImportStartDate}
          onFwImportStartDateChange={setFwImportStartDate}
          fwImportIntervalDays={fwImportIntervalDays}
          onFwImportIntervalDaysChange={setFwImportIntervalDays}
          fwImportSubmitting={fwImportSubmitting}
          onApplyDateSuggestions={applyFwImportDateSuggestions}
          onSubmit={submitFrameworkImport}
          onClose={() => setFrameworkImportOpen(false)}
        />

        <TrainingPublishToFrameworkModal
          open={publishFrameworkOpen}
          onClose={() => {
            setPublishFrameworkOpen(false)
            setPublishFrameworkUnitId(null)
          }}
          onSuccess={() => {
            setPublishFrameworkOpen(false)
            setPublishFrameworkUnitId(null)
          }}
          unitId={publishFrameworkUnitId}
          planningModalClubId={listActionClubId}
        />

        <SaveExercisesAsModuleModal
          open={saveModuleOpen}
          onClose={() => {
            setSaveModuleOpen(false)
            setSaveModuleUnitId(null)
          }}
          onSuccess={() => {
            setSaveModuleOpen(false)
            setSaveModuleUnitId(null)
          }}
          unitId={saveModuleUnitId}
          planningModalClubId={listActionClubId}
        />
    </>
  )
}

export default TrainingPlanningPageRoot
