<template>
    <div class="diary">
        <h2>{{ $t('diary.title') }}</h2>
        <div class="diary-header-row">
            <label>{{ $t('diary.date') }}:
                <select v-model="date" @change="handleDateChange">
                    <option :value="null" v-if="dates.length === 0">{{ $t('diary.noEntries') }}</option>
                    <option v-for="entry in dates" :key="entry.id" :value="entry">{{ getFormattedDate(entry.date) }}
                    </option>
                </select>
                <button v-if="date && canDeleteCurrentDate" class="btn-secondary"
                    @click="deleteCurrentDate">{{ $t('diary.deleteDate') }}</button>
                <button @click="openNewDateDialog" class="btn-primary">{{ $t('diary.createNew') }}</button>
                <button type="button" @click="quickCreateNextTraining" class="btn-secondary" :disabled="quickCreateBusy">
                    {{ $t('diary.quickCreate') }}
                </button>
            </label>
        </div>
        <!-- Training Group Selection Dialog -->
        <div v-if="showTrainingGroupDialog" class="dialog-overlay" @click.self="closeTrainingGroupDialog">
            <div class="dialog-content">
                <h3>{{ $t('diary.selectTrainingGroup') }}</h3>
                <div class="dialog-body">
                    <label>
                        <span>{{ $t('diary.selectTrainingGroup') }}:</span>
                        <select v-model="selectedTrainingGroupId" class="input-field" @change="onTrainingGroupSelected">
                            <option value="">{{ $t('diary.selectTrainingGroupPlaceholder') }}</option>
                            <option v-for="group in trainingGroups" :key="group.id" :value="group.id">
                                {{ group.name }}
                            </option>
                        </select>
                    </label>
                    <div v-if="suggestedDate" class="suggestion-info">
                        <p><strong>{{ $t('diary.suggestion') }}:</strong></p>
                        <p>{{ $t('diary.nextAppointment') }}: <strong>{{ getFormattedDate(suggestedDate) }}</strong></p>
                        <p v-if="suggestedStartTime && suggestedEndTime">
                            {{ $t('common.time') }}: <strong>{{ suggestedStartTime }} - {{ suggestedEndTime }}</strong>
                        </p>
                    </div>
                </div>
                <div class="dialog-actions">
                    <button @click="applySuggestion" class="btn-primary" :disabled="!suggestedDate">
                        {{ $t('diary.applySuggestion') }}
                    </button>
                    <button @click="closeTrainingGroupDialog" class="btn-secondary">
                        {{ $t('messages.cancel') }}
                    </button>
                    <button @click="skipSuggestion" class="btn-secondary">
                        {{ $t('diary.skipSuggestion') }}
                    </button>
                </div>
            </div>
        </div>

        <div v-if="showForm">
            <h3>{{ $t('diary.createNewDate') }}</h3>
            <form @submit.prevent="createDate">
                <div>
                    <label for="newDate">{{ $t('diary.date') }}:</label>
                    <input type="date" id="newDate" v-model="newDate" required />
                    <button type="button" @click="setCurrentDate">{{ $t('diary.today') }}</button>
                </div>
                <div>
                    <label for="trainingStart">{{ $t('diary.trainingStart') }}:</label>
                    <input type="time" step="300" id="trainingStart" v-model="trainingStart" />
                </div>
                <div>
                    <label for="trainingEnd">{{ $t('diary.trainingEnd') }}:</label>
                    <input type="time" step="300" id="trainingEnd" v-model="trainingEnd" />
                </div>
                <div>
                    <label for="excludeFromBilling" style="display: inline-flex; align-items: center; gap: 0.4rem;">
                        <input type="checkbox" id="excludeFromBilling" v-model="excludeFromBilling" />
                        <span>{{ $t('diary.excludeFromBilling') }}</span>
                    </label>
                </div>
                <button type="submit">{{ $t('diary.createDate') }}</button>
            </form>
        </div>

        <div v-if="date !== null && !showForm" class="diary-content">
            <DiaryOverviewPanels
                :active-overview-panel="activeOverviewPanel"
                :formatted-date="date?.date ? getFormattedDate(date.date) : ''"
                :diary-status-text="diaryStatusText"
                :diary-time-range-label="diaryTimeRangeLabel"
                :participant-count="participants.length"
                :excused-count="excusedActiveMemberCount"
                :active-member-count="activeMemberCount"
                :available-participant-count="availableParticipantCount"
                :training-plan-count="trainingPlan.length"
                :activities-count="activities.length"
                :training-start="trainingStart"
                :training-end="trainingEnd"
                :exclude-from-billing="excludeFromBilling"
                :groups="groups"
                :editing-group-id="editingGroupId"
                :new-group-count="newGroupCount"
                @toggle-panel="toggleOverviewPanel"
                @update-training-times="updateTrainingTimes"
                @update:training-start="trainingStart = $event"
                @update:training-end="trainingEnd = $event"
                @update:exclude-from-billing="updateExcludeFromBillingImmediate"
                @edit-group="editGroup"
                @update-group-field="updateGroupField"
                @save-group="saveGroup"
                @cancel-edit-group="cancelEditGroup"
                @delete-group="deleteGroup"
                @update:new-group-count="newGroupCount = $event"
                @create-groups="createGroups"
            />

            <!-- Tab-Navigation für Mobile -->
            <div class="mobile-tabs">
                <button 
                    class="tab-button" 
                    :class="{ active: activeTab === 'plan' }"
                    @click="activeTab = 'plan'"
                >
                    {{ $t('diary.trainingPlan') }} <span class="mobile-tab-count">{{ trainingPlan.length }}</span>
                </button>
                <button 
                    class="tab-button" 
                    :class="{ active: activeTab === 'members' }"
                    @click="activeTab = 'members'"
                >
                    {{ $t('diary.participants') }} <span class="mobile-tab-count">{{ participants.length }}</span>
                </button>
                <button 
                    class="tab-button" 
                    :class="{ active: activeTab === 'activities' }"
                    @click="activeTab = 'activities'"
                >
                    {{ $t('diary.activities') }} <span class="mobile-tab-count">{{ activities.length }}</span>
                </button>
            </div>
            <div class="columns">
                <div class="column" :class="{ 'mobile-tab-content': true, 'active': activeTab === 'plan' }">
                    <h3>{{ $t('diary.trainingPlan') }}</h3>
                    <div class="plan-toolbar">
                        <div class="plan-toolbar-stats">
                            <div class="plan-toolbar-stat">
                                <span class="plan-toolbar-label">{{ $t('diary.startTime') }}</span>
                                <strong>{{ normalizedNextStartTime }}</strong>
                            </div>
                            <div class="plan-toolbar-stat">
                                <span class="plan-toolbar-label">{{ $t('diary.timeblocksCount') }}</span>
                                <strong>{{ timeblockCount }}</strong>
                            </div>
                            <div class="plan-toolbar-stat">
                                <span class="plan-toolbar-label">{{ $t('diary.planActivitiesCount') }}</span>
                                <strong>{{ standalonePlanItemCount }}</strong>
                            </div>
                        </div>
                        <div class="plan-toolbar-actions">
                            <label class="plan-view-group-filter">
                                <span>{{ $t('diary.group') }}</span>
                                <select v-model="planGroupFilter">
                                    <option value="__all__">{{ $t('common.all') }}</option>
                                    <option v-for="group in groups" :key="group.id" :value="String(group.id)">
                                        {{ group.name }}
                                    </option>
                                </select>
                            </label>
                            <button type="button" @click="openNewPlanItem()">{{ $t('diary.overallActivity') }}</button>
                            <button type="button" @click="addTimeblock()">{{ $t('diary.addTimeblock') }}</button>
                            <button v-if="groups && groups.length > 0" type="button" @click="addGroupActivity()">{{ $t('diary.addGroupActivity') }}</button>
                            <button
                                v-if="trainingPlan && trainingPlan.length > 0"
                                type="button"
                                @click="generatePDF"
                            >
                                {{ $t('diary.trainingPlanPdfShort') }}
                            </button>
                            <button
                                v-if="date && participants && participants.length > 0"
                                type="button"
                                @click="generateTrainingDayPDF"
                            >
                                {{ $t('diary.trainingDaySummaryPdfShort') }}
                            </button>
                        </div>
                    </div>
                    <div style="overflow: visible; position: relative;">
                        <div v-if="!trainingPlan || trainingPlan.length === 0" class="plan-empty-state">
                            {{ $t('diary.planEmptyState') }}
                        </div>
                        <div v-else class="diary-readiness-panel">
                            <div class="diary-readiness-header">
                                <strong>{{ $t('diary.trainingDayChecklist') }}</strong>
                            </div>
                            <div class="diary-readiness-grid">
                                <div class="diary-readiness-item" :class="{ 'ready': Boolean(trainingStart || trainingEnd) }">
                                    <span>{{ $t('diary.trainingWindow') }}</span>
                                    <strong>{{ Boolean(trainingStart || trainingEnd) ? $t('diary.statusReadyShort') : $t('diary.statusOpenShort') }}</strong>
                                </div>
                                <div class="diary-readiness-item" :class="{ 'ready': trainingPlan.length > 0 }">
                                    <span>{{ $t('diary.trainingPlan') }}</span>
                                    <strong>{{ trainingPlan.length > 0 ? $t('diary.statusReadyShort') : $t('diary.statusOpenShort') }}</strong>
                                </div>
                                <div class="diary-readiness-item" :class="{ 'ready': openPlanItems.length === 0 }">
                                    <span>{{ $t('diary.openPlanItemsLabel') }}</span>
                                    <strong>
                                        {{ openPlanItems.length === 0
                                            ? $t('diary.statusReadyShort')
                                            : $t('diary.openPlanItems', { count: openPlanItems.length }) }}
                                    </strong>
                                </div>
                            </div>
                        </div>
                        <div v-if="addNewItem || addNewTimeblock || addNewGroupActivity" class="plan-composer">
                            <div class="plan-composer-header">
                                <strong>
                                    {{ addNewGroupActivity ? $t('diary.addGroupActivity') : (addNewTimeblock ? $t('diary.addTimeblock') : $t('diary.overallActivity')) }}
                                </strong>
                                <button type="button" class="btn-secondary" @click="cancelAddItem">{{ $t('common.cancel') }}</button>
                            </div>
                            <div v-if="addNewItem && standardDiaryActivities.length" class="plan-quick-actions">
                                <span class="plan-quick-actions-label">{{ $t('diary.standardActivities') }}</span>
                                <div class="plan-quick-actions-list">
                                    <button
                                        v-for="activity in standardDiaryActivities"
                                        :key="activity.name"
                                        type="button"
                                        class="plan-quick-action"
                                        @click="addStandardPlanActivity(activity)"
                                    >
                                        {{ activity.name }}
                                        <span v-if="activity.duration" class="plan-quick-action-meta">
                                            · {{ activity.duration }} {{ $t('diary.standardDurationShort') }}
                                        </span>
                                    </button>
                                </div>
                            </div>
                            <div class="plan-composer-grid">
                                <div v-if="addNewItem || addNewGroupActivity" class="plan-composer-field">
                                    <label>{{ $t('diary.activityOrTimeblock') }}</label>
                                    <div class="plan-composer-activity-input">
                                        <button
                                            v-if="addNewItem || addNewGroupActivity"
                                            type="button"
                                            class="btn-palette"
                                            @click="showDrawingDialog = true"
                                            :title="$t('diary.createDrawing')"
                                        >
                                            🎨
                                        </button>
                                        <div class="plan-composer-input-wrap">
                                            <input
                                                type="text"
                                                v-model="newPlanItem.activity"
                                                :placeholder="$t('diary.activityPlaceholder')"
                                                @input="onNewItemInputChange"
                                            />
                                            <div v-if="newItemShowDropdown && newItemSearchResults.length" class="dropdown" style="max-height: 9.5em;">
                                                <div v-for="s in newItemSearchResults" :key="s.id" @click="chooseNewItemSuggestion(s)">
                                                    <span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code }}]</strong> </span>{{ s.name }}
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div v-if="addNewGroupActivity" class="plan-composer-field">
                                    <label>{{ $t('diary.group') }}</label>
                                    <select v-model="newPlanItem.groupId">
                                        <option value="">{{ $t('diary.selectGroup') }}</option>
                                        <option v-for="group in groups" :key="group.id" :value="String(group.id)">
                                            {{ group.name }}
                                        </option>
                                    </select>
                                </div>
                                <div v-if="addNewItem || addNewTimeblock || addNewGroupActivity" class="plan-composer-field">
                                    <label>{{ $t('diary.durationMinutes') }}</label>
                                    <div class="plan-composer-duration">
                                        <input type="text" v-model="newPlanItem.durationText" @input="calculateDuration" :placeholder="$t('diary.durationExampleLong')" />
                                        <input type="number" v-model="newPlanItem.duration" :placeholder="$t('diary.minutes')" />
                                    </div>
                                </div>
                            </div>
                            <div class="plan-composer-actions">
                                <button type="button" class="btn-primary" @click="addPlanItem">{{ $t('common.add') }}</button>
                            </div>
                        </div>
                        <div v-if="activePlanEditorItem" class="plan-editor">
                            <div class="plan-editor-header">
                                <strong>{{ activePlanEditorType === 'groupActivity' ? $t('diary.editGroupActivity') : $t('diary.editActivity') }}</strong>
                                <button type="button" class="btn-secondary" @click="cancelCurrentPlanEdit">{{ $t('common.cancel') }}</button>
                            </div>
                            <div v-if="activePlanEditorType === 'activity'" class="plan-editor-grid">
                                <div class="plan-editor-field">
                                    <label>{{ $t('diary.activityOrTimeblock') }}</label>
                                    <div class="plan-composer-activity-input">
                                        <button
                                            v-if="activePlanEditorItem.predefinedActivity || hasItemDrawingData(activePlanEditorItem)"
                                            type="button"
                                            class="btn-palette"
                                            @click="editActivity(activePlanEditorItem)"
                                            :title="$t('diary.createDrawing')"
                                        >
                                            🎨
                                        </button>
                                        <div class="plan-composer-input-wrap">
                                            <input
                                                ref="activityInput"
                                                type="text"
                                                v-model="editingActivityText"
                                                @input="onEditInputChangeText(activePlanEditorItem)"
                                                @keyup.enter="saveActivityEdit(activePlanEditorItem)"
                                                @keyup.esc="cancelCurrentPlanEdit"
                                            />
                                            <div v-if="editShowDropdown && editSearchForId === activePlanEditorItem.id && editSearchResults.length" class="dropdown" style="max-height: 9.5em;">
                                                <div v-for="s in editSearchResults" :key="s.id" @click="chooseEditSuggestion(s, activePlanEditorItem)">
                                                    <span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code }}]</strong> </span>{{ s.name }}
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="plan-editor-field">
                                    <label>{{ $t('diary.durationMinutes') }}</label>
                                    <div class="plan-composer-duration">
                                        <input type="text" v-model="editingDurationText" @input="calculateDurationForEdit" :placeholder="$t('diary.durationExampleShort')" />
                                        <input type="number" v-model="editingDuration" :placeholder="$t('diary.min')" @keyup.enter="saveActivityEdit(activePlanEditorItem)" />
                                    </div>
                                </div>
                            </div>
                            <div v-else class="plan-editor-grid">
                                <div class="plan-editor-field">
                                    <label>{{ $t('diary.activityOrTimeblock') }}</label>
                                    <div class="plan-composer-activity-input">
                                        <button
                                            type="button"
                                            class="btn-palette"
                                            @click="editGroupActivity(activePlanEditorItem)"
                                            :title="$t('diary.createDrawing')"
                                        >
                                            🎨
                                        </button>
                                        <div class="plan-composer-input-wrap">
                                            <input
                                                type="text"
                                                v-model="editingGroupActivityText"
                                                @input="onEditGroupActivityInputChange(activePlanEditorItem)"
                                                @keyup.enter="saveGroupActivityEdit(activePlanEditorItem)"
                                                @keyup.esc="cancelCurrentPlanEdit"
                                            />
                                            <div v-if="editShowDropdown && Number(editSearchForId) === Number(activePlanEditorItem.id) && editSearchResults.length" class="dropdown" style="max-height: 9.5em;">
                                                <div v-for="s in editSearchResults" :key="s.id" @click="chooseEditGroupActivitySuggestion(s, activePlanEditorItem)">
                                                    <span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code }}]</strong> </span>{{ s.name }}
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div class="plan-editor-field">
                                    <label>{{ $t('diary.group') }}</label>
                                    <select v-model="editingGroupActivityGroupId">
                                        <option value="">{{ $t('diary.selectGroup') }}</option>
                                        <option v-for="group in groups" :key="group.id" :value="String(group.id)">
                                            {{ group.name }}
                                        </option>
                                    </select>
                                </div>
                                <div class="plan-editor-field">
                                    <label>{{ $t('diary.durationMinutes') }}</label>
                                    <div class="plan-composer-duration">
                                        <input type="text" v-model="editingGroupActivityDurationText" @input="calculateDurationForEditGroupActivity" :placeholder="$t('diary.durationExampleShort')" />
                                        <input type="number" v-model="editingGroupActivityDuration" :placeholder="$t('diary.min')" @keyup.enter="saveGroupActivityEdit(activePlanEditorItem)" />
                                    </div>
                                </div>
                            </div>
                            <div class="plan-editor-actions">
                                <button
                                    v-if="activePlanEditorType === 'activity'"
                                    type="button"
                                    class="btn-primary"
                                    @click="saveActivityEdit(activePlanEditorItem)"
                                >
                                    {{ $t('common.save') }}
                                </button>
                                <button
                                    v-else
                                    type="button"
                                    class="btn-primary"
                                    @click="saveGroupActivityEdit(activePlanEditorItem)"
                                >
                                    {{ $t('common.save') }}
                                </button>
                            </div>
                        </div>
                        <div v-if="activeAssignmentItem" class="plan-assignment-panel">
                            <div class="plan-editor-header">
                                <strong>{{ activeAssignmentType === 'groupActivity' ? $t('diary.assignParticipantsForGroupActivity') : $t('diary.assignParticipants') }}</strong>
                                <button type="button" class="btn-secondary" @click="closeCurrentAssignmentPanel">{{ $t('common.close') }}</button>
                            </div>
                            <div class="plan-assignment-toolbar">
                                <button
                                    type="button"
                                    class="plan-row-action-button plan-row-action-button-primary"
                                    @click="activeAssignmentType === 'groupActivity' ? assignAllMembersToGroupActivity(activeAssignmentItem.id) : assignAllMembersToActivity(activeAssignmentItem.id)"
                                >
                                    {{ $t('diary.all') }}
                                </button>
                                <select
                                    v-if="groups.length > 0"
                                    @change="activeAssignmentType === 'groupActivity' ? assignGroupToGroupActivity(activeAssignmentItem.id, $event.target.value) : assignGroupToActivity(activeAssignmentItem.id, $event.target.value)"
                                >
                                    <option value="">{{ $t('diary.group') }}</option>
                                    <option v-for="group in groups" :key="group.id" :value="String(group.id)">
                                        {{ group.name }}
                                    </option>
                                </select>
                            </div>
                            <div class="plan-assignment-list">
                                <label v-for="m in presentMembers" :key="m.id" class="plan-assignment-row">
                                    <input
                                        type="checkbox"
                                        :checked="activeAssignmentType === 'groupActivity' ? isAssignedToGroupActivity(activeAssignmentItem.id, m.id) : isAssignedToActivity(activeAssignmentItem.id, m.id)"
                                        @change="activeAssignmentType === 'groupActivity'
                                            ? toggleMemberForGroupActivity(activeAssignmentItem.id, m.id, $event.target.checked)
                                            : toggleMemberForActivity(activeAssignmentItem.id, m.id, $event.target.checked)"
                                    >
                                    <span>{{ m.firstName }} {{ m.lastName }}</span>
                                </label>
                            </div>
                        </div>
                        <table>
                            <thead>
                                <tr v-if="showGroupedPlanTable">
                                    <th>{{ $t('diary.startTime') }}</th>
                                    <th v-for="group in groups" :key="`group-col-${group.id}`">{{ group.name }}</th>
                                </tr>
                                <tr v-else>
                                    <th></th> <!-- Neue Spalte für Drag-Handle -->
                                    <th>{{ $t('diary.startTime') }}</th>
                                    <th>{{ $t('diary.activityOrTimeblock') }}</th>
                                    <th>{{ $t('diary.group') }}</th>
                                    <th>{{ $t('diary.durationMinutes') }}</th>
                                    <th></th>
                                </tr>
                            </thead>
                            <tbody v-if="showGroupedPlanTable">
                                <tr v-for="row in groupedPlanRows" :key="row.key">
                                    <td>{{ formatDisplayTime(row.startTime) }}</td>
                                    <td v-if="row.sharedItems.length" :colspan="groups.length">
                                        <div class="plan-cell-stack">
                                            <div v-for="item in row.sharedItems" :key="`shared-${item.id}`" class="plan-cell-item">
                                                <div class="plan-activity-main">
                                                    <span @click="startActivityEdit(item)" class="clickable activity-label">
                                                        <span v-if="hasItemDrawingData(item)"
                                                            @click.stop="openPlanItemVisual(item)"
                                                            class="image-icon" :title="$t('diary.showImage')">🖼️</span>
                                                        {{ getPlanItemDisplayLabel(item) }}
                                                    </span>
                                                    <span v-if="!isStructuralPlanItem(item) && getPlanItemStatus(item).label" class="plan-status-badge" :class="`plan-status-badge-${getPlanItemStatus(item).tone}`">
                                                        {{ getPlanItemStatus(item).label }}
                                                    </span>
                                                    <span v-if="getPlanDurationMinutesDisplay(item)" class="plan-duration-badge">
                                                        {{ getPlanDurationMinutesDisplay(item) }}
                                                    </span>
                                                </div>
                                                <div class="plan-row-actions">
                                                    <button @click="startActivityEdit(item)" class="plan-row-action-button">{{ $t('common.edit') }}</button>
                                                    <button
                                                        @click="movePlanItem(item, 'up')"
                                                        class="plan-row-action-button"
                                                        :disabled="!canMovePlanItem(item, 'up')"
                                                        title="Nach oben"
                                                    >↑</button>
                                                    <button
                                                        @click="movePlanItem(item, 'down')"
                                                        class="plan-row-action-button"
                                                        :disabled="!canMovePlanItem(item, 'down')"
                                                        title="Nach unten"
                                                    >↓</button>
                                                    <button v-if="!isStructuralPlanItem(item)" @click="toggleActivityMembers(item)" class="plan-row-action-button">{{ $t('diary.assignShort') }}</button>
                                                    <button @click="removePlanItem(item.id)" class="plan-row-action-button plan-row-action-button-danger">{{ $t('common.delete') }}</button>
                                                </div>
                                            </div>
                                        </div>
                                    </td>
                                    <template v-else>
                                        <td v-for="group in groups" :key="`row-${row.key}-group-${group.id}`">
                                            <div v-if="(row.groupItems[group.id] || []).length" class="plan-cell-stack">
                                                <div v-for="item in (row.groupItems[group.id] || [])" :key="`group-item-${item.id}`" class="plan-cell-item">
                                                    <div class="plan-activity-main">
                                                        <span @click="startActivityEdit(item)" class="clickable activity-label">
                                                            <span v-if="hasItemDrawingData(item)"
                                                                @click.stop="openPlanItemVisual(item)"
                                                                class="image-icon" :title="$t('diary.showImage')">🖼️</span>
                                                            {{ getPlanItemDisplayLabel(item) }}
                                                        </span>
                                                        <span v-if="!isStructuralPlanItem(item) && getPlanItemStatus(item).label" class="plan-status-badge" :class="`plan-status-badge-${getPlanItemStatus(item).tone}`">
                                                            {{ getPlanItemStatus(item).label }}
                                                        </span>
                                                        <span v-if="getPlanDurationMinutesDisplay(item)" class="plan-duration-badge">
                                                            {{ getPlanDurationMinutesDisplay(item) }}
                                                        </span>
                                                    </div>
                                                    <div class="plan-row-actions">
                                                        <button @click="startActivityEdit(item)" class="plan-row-action-button">{{ $t('common.edit') }}</button>
                                                        <button
                                                            @click="movePlanItem(item, 'up')"
                                                            class="plan-row-action-button"
                                                            :disabled="!canMovePlanItem(item, 'up')"
                                                            title="Nach oben"
                                                        >↑</button>
                                                        <button
                                                            @click="movePlanItem(item, 'down')"
                                                            class="plan-row-action-button"
                                                            :disabled="!canMovePlanItem(item, 'down')"
                                                            title="Nach unten"
                                                        >↓</button>
                                                        <button v-if="!isStructuralPlanItem(item)" @click="toggleActivityMembers(item)" class="plan-row-action-button">{{ $t('diary.assignShort') }}</button>
                                                        <button @click="removePlanItem(item.id)" class="plan-row-action-button plan-row-action-button-danger">{{ $t('common.delete') }}</button>
                                                    </div>
                                                </div>
                                            </div>
                                            <span v-else class="plan-row-muted">-</span>
                                        </td>
                                    </template>
                                </tr>
                                <tr>
                                    <td>{{ calculateNextTime }}</td>
                                    <td :colspan="groups.length">
                                        <span class="plan-add-hint">{{ $t('diary.planAddHint') }}</span>
                                    </td>
                                </tr>
                            </tbody>
                            <tbody v-else ref="sortableList">
                                <template v-for="(item, index) in filteredTrainingPlan" :key="item.id">
                                    <tr :class="{ 'plan-timeblock-row': item.isTimeblock }" class="plan-sortable-row" :data-plan-id="item.id">
                                        <td class="drag-handle" style="cursor: move;">☰</td> <!-- Drag-Handle -->
                                        <td>{{ formatDisplayTime(item.startTime) }}</td>
                                        <td>
                                            <div class="plan-activity-main">
                                                <span v-if="item.isTimeblock" class="plan-type-badge plan-type-badge-timeblock">{{ $t('diary.timeblock') }}</span>
                                                <span v-else @click="startActivityEdit(item)"
                                                    class="clickable activity-label"
                                                    :title="item.predefinedActivity && item.predefinedActivity.name ? item.predefinedActivity.name : ''">
                                                    <!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
                                                    <span v-if="hasActivityVisual(item.predefinedActivity)"
                                                        @click.stop="openActivityVisual(item.predefinedActivity)"
                                                        class="image-icon" :title="$t('diary.showImage')">🖼️</span>
                                                    {{ (item.predefinedActivity && item.predefinedActivity.code &&
                                                        item.predefinedActivity.code.trim() !== '')
                                                        ? item.predefinedActivity.code
                                                        : (item.predefinedActivity ? item.predefinedActivity.name :
                                                    item.activity) }}
                                                </span>
                                                <span v-if="!isStructuralPlanItem(item) && getPlanItemStatus(item).label" class="plan-status-badge" :class="`plan-status-badge-${getPlanItemStatus(item).tone}`" :title="getPlanItemStatus(item).reason || ''">
                                                    {{ getPlanItemStatus(item).label }}
                                                </span>
                                            </div>
                                        </td>
                                        <td>
                                            <span v-if="item.isTimeblock && getVisibleGroupActivities(item).length" class="plan-row-muted">
                                                {{ getVisibleGroupActivities(item).length }} {{ $t('diary.groupsLabel') }}
                                            </span>
                                            <span v-else>{{ item.planGroup ? item.planGroup.name : '' }}</span>
                                        </td>
                                        <td>
                                            <span class="clickable" @click="startActivityEdit(item)">
                                                {{ getPlanDurationDisplay(item) }}
                                            </span>
                                        </td>
                                        <td>
                                            <div class="plan-row-actions">
                                                <button v-if="!item.isTimeblock" @click="startActivityEdit(item)" class="plan-row-action-button">{{ $t('common.edit') }}</button>
                                                <button v-if="!item.isTimeblock && !isStructuralPlanItem(item)" @click="toggleActivityMembers(item)" :title="$t('diary.assignParticipants')"
                                                    class="plan-row-action-button">{{ $t('diary.assignShort') }}</button>
                                                <button v-if="item.isTimeblock" @click="addGroupActivityToTimeblock(item.id)" :title="$t('diary.addGroupActivity')"
                                                    class="plan-row-action-button plan-row-action-button-primary">{{ $t('diary.addGroupButton') }}</button>
                                                <button @click="removePlanItem(item.id)" class="plan-row-action-button plan-row-action-button-danger">{{ $t('common.delete') }}</button>
                                            </div>
                                        </td>
                                    </tr>
                                    <!-- Formular zum Hinzufügen einer Gruppen-Aktivität direkt nach dem Zeitblock -->
                                    <tr v-if="item.isTimeblock && addNewGroupActivity && selectedTimeblockId === item.id">
                                        <td></td>
                                        <td></td>
                                        <td colspan="2">
                                            <div style="display: flex; gap: 0.5rem; align-items: center; padding: 0.5rem; background: #f0f0f0; border-radius: 4px;">
                                                <div style="flex: 1; position: relative;">
                                                    <input type="text" v-model="newPlanItem.activity" :placeholder="$t('diary.activityPlaceholder')" 
                                                        @input="onNewItemInputChange" style="width: 100%;" />
                                                    <div v-if="newItemShowDropdown && newItemSearchResults.length"
                                                        class="dropdown" style="max-height: 9.5em;">
                                                        <div v-for="s in newItemSearchResults" :key="s.id"
                                                            @click="chooseNewItemSuggestion(s)">
                                                            <span v-if="s.code && s.code.trim() !== ''"><strong>[{{ s.code
                                                                    }}]</strong> </span>{{ s.name }}
                                                        </div>
                                                    </div>
                                                </div>
                                                <select v-model="newPlanItem.groupId" style="flex: 1;">
                                                    <option value="">{{ $t('diary.selectGroup') }}</option>
                                                    <option v-for="group in groups" :key="group.id" :value="String(group.id)">
                                                        {{ group.name }}</option>
                                                </select>
                                            </div>
                                        </td>
                                        <td>
                                            <div style="display:flex; gap:0.35rem; align-items:center;">
                                                <input
                                                    type="text"
                                                    v-model="newPlanItem.durationText"
                                                    @input="calculateDuration"
                                                    :placeholder="$t('diary.durationExampleLong')"
                                                    style="width: 120px;"
                                                />
                                                <input
                                                    type="number"
                                                    v-model="newPlanItem.duration"
                                                    :placeholder="$t('diary.minutes')"
                                                    style="width: 72px;"
                                                />
                                            </div>
                                        </td>
                                        <td>
                                            <span class="add-plan-item" @click="addPlanItem">+</span>
                                            <span class="cancel" @click="cancelAddItem">X</span>
                                        </td>
                                    </tr>
                                    <template v-for="groupItem in getVisibleGroupActivities(item)">
                                        <tr class="plan-group-activity-row">
                                            <td></td>
                                            <td>{{ formatDisplayTime(calculateGroupActivityStartTime(item, groupItem)) }}</td>
                                            <td>
                                                <div class="plan-group-activity-cell">
                                                <span class="plan-type-badge plan-type-badge-group">{{ $t('diary.group') }}</span>
                                                <span @click="startGroupActivityEdit(groupItem)"
                                                    class="clickable activity-label"
                                                    :title="(groupItem.groupPredefinedActivity && groupItem.groupPredefinedActivity.name) ? groupItem.groupPredefinedActivity.name : ''">
                                                    <!-- Icon öffnet Rendering (falls vorhanden) oder Bild im Modal -->
                                                    <span v-if="hasActivityVisual(groupItem.groupPredefinedActivity)"
                                                        @click.stop="openActivityVisual(groupItem.groupPredefinedActivity)"
                                                        class="image-icon" :title="$t('diary.showImage')">🖼️</span>

                                                    {{ (groupItem.groupPredefinedActivity &&
                                                        groupItem.groupPredefinedActivity.code &&
                                                        groupItem.groupPredefinedActivity.code.trim() !== '')
                                                        ? groupItem.groupPredefinedActivity.code
                                                    : groupItem.groupPredefinedActivity.name }}
                                                </span>
                                                <span v-if="!isStructuralPlanItem(groupItem) && getPlanItemStatus(groupItem).label" class="plan-status-badge" :class="`plan-status-badge-${getPlanItemStatus(groupItem).tone}`" :title="getPlanItemStatus(groupItem).reason || ''">
                                                    {{ getPlanItemStatus(groupItem).label }}
                                                </span>
                                                </div>
                                            </td>
                                            <td>{{ groupItem.groupsGroupActivity.name }}</td>
                                            <td>
                                                <span class="clickable" @click="startGroupActivityEdit(groupItem)">
                                                    {{ groupItem.duration || '' }}<span
                                                        v-if="groupItem.durationText && groupItem.durationText.trim() !== ''"> ({{ groupItem.durationText }})</span>
                                                </span>
                                            </td>
                                            <td>
                                                <div class="plan-row-actions">
                                                    <button @click="startGroupActivityEdit(groupItem)" class="plan-row-action-button">{{ $t('common.edit') }}</button>
                                                    <button
                                                        @click="moveGroupActivity(item, groupItem, 'up')"
                                                        class="plan-row-action-button"
                                                        :disabled="!canMoveGroupActivity(item, groupItem, 'up')"
                                                        title="Nach oben"
                                                    >↑</button>
                                                    <button
                                                        @click="moveGroupActivity(item, groupItem, 'down')"
                                                        class="plan-row-action-button"
                                                        :disabled="!canMoveGroupActivity(item, groupItem, 'down')"
                                                        title="Nach unten"
                                                    >↓</button>
                                                    <button v-if="!isStructuralPlanItem(groupItem)" @click="toggleGroupActivityMembers(groupItem)" :title="$t('diary.assignParticipants')"
                                                        class="plan-row-action-button">{{ $t('diary.assignShort') }}</button>
                                                    <button @click="removeGroupActivity(groupItem.id)" class="plan-row-action-button plan-row-action-button-danger" :title="$t('diary.delete')">{{ $t('common.delete') }}</button>
                                                </div>
                                            </td>
                                        </tr>
                                    </template>
                                </template>
                                <!-- Zeile zum Hinzufügen eines neuen Items -->
                                <tr>
                                    <td></td>
                                    <td>{{ calculateNextTime }}</td>
                                    <td colspan="4">
                                        <span class="plan-add-hint">{{ $t('diary.planAddHint') }}</span>
                                    </td>
                                    <td></td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
                <div class="column mobile-sidebar" :class="{ 'mobile-tab-content': true, 'active': activeTab === 'members' || activeTab === 'activities' }" style="padding-bottom:4em">
                    <div class="diary-sidebar-utility">
                        <button @click="addAccident">{{ $t('diary.bookAccident') }}</button>
                    </div>
                    <DiaryActivitiesPanel
                        v-show="!isMobileView || activeTab === 'activities'"
                        :show-activities-box="showActivitiesBox"
                        :new-activity="newActivity"
                        :activities="activities"
                        :available-tags="availableTags"
                        :selected-activity-tags="selectedActivityTags"
                        @toggle-box="toggleActivitiesBox"
                        @update:new-activity="newActivity = $event"
                        @add-activity="addActivity"
                        @update:selected-activity-tags="selectedActivityTags = $event"
                        @add-tag="addNewTag"
                        @remove-tag="removeActivityTag"
                        @add-tag-from-input="addNewTagFromInput"
                    />
                    <DiaryParticipantsPanel
                        v-show="!isMobileView || activeTab === 'members'"
                        :members="filteredDiaryMembers"
                        :participants="participants"
                        :excused-count="excusedActiveMemberCount"
                        :active-member-count="activeMemberCount"
                        :available-participant-count="availableParticipantCount"
                        :gallery-loading="galleryLoading"
                        :participant-search-query="participantSearchQuery"
                        :participant-filter="participantFilter"
                        :groups="groups"
                        :member-groups-map="memberGroupsMap"
                        :participant-status-map="participantStatusMap"
                        @update:participant-search-query="participantSearchQuery = $event"
                        @update:participant-filter="participantFilter = $event"
                        @toggle-participant="toggleParticipant"
                        @toggle-member-status="toggleParticipantStatus"
                        @update-member-group="updateMemberGroup($event.memberId, $event.groupId)"
                        @open-notes="openNotesModal"
                        @show-pic="showPic"
                        @mark-form="markFormHandedOver"
                        @open-orders="openOrdersDialog"
                        @open-tags="openTagInfos"
                        @open-quick-add="openQuickAddDialog"
                        @open-gallery="openGalleryDialog"
                        @open-group-photo-crop="showGroupPhotoCropDialog = true"
                    />
                </div>
            </div>
        </div>

        <!-- Tag History Modal -->
        <TagHistoryDialog
            v-model="showTagHistoryModal"
            :member="tagHistoryMember"
            :tag-history="tagHistory"
            v-model:selected-tags="selectedMemberDayTags"
            :activity-tags="selectedActivityTags"
            @select-tag="addNewTagForDay"
            @close="closeTagHistoryModal"
        />

        <!-- Activity Stats Modal -->
        <MemberActivityStatsDialog
            v-model="showActivityStatsModal"
            :member="activityStatsMember"
            :last-participations="lastParticipations"
            :activity-stats="activityStats"
            @close="closeActivityStatsModal"
        />

        <!-- Notizen Modal -->
        <MemberNotesDialog
            v-model="showNotesModal"
            :member="noteMember"
            :notes="notes"
            v-model:selected-tags="selectedMemberTags"
            :available-tags="availableTags"
            v-model:note-content="newNoteContent"
            @add-note="addMemberNote"
            @delete-note="deleteNote"
            @add-tag="addNewTagForMemberFromSelection"
            @remove-tag="removeMemberDayTag"
            @close="closeNotesModal"
        />
        <!-- Image Dialog für normale Bilder -->
        <ImageDialog
            v-model="showImage"
            :title="$t('diary.activityImage')"
            :image-url="imageUrl"
        />
        
        <!-- Dialog für gerenderte Zeichnungen -->
        <BaseDialog
            v-model="showRenderModal"
            :title="$t('diary.activityDrawing')"
            size="large"
        >
            <div class="render-container">
                <CourtDrawingRender :drawing-data="renderModalData" :width="560" :height="360" />
            </div>
        </BaseDialog>
        <!-- Accident Form Modal -->
        <AccidentFormDialog
            v-model="showAccidentForm"
            v-model:accident="accident"
            :members="members"
            :participants="participants"
            :accidents="accidents"
            @submit="saveAccident"
            @close="closeAccidentForm"
        />

        <!-- Schnell hinzufügen Dialog -->
        <QuickAddMemberDialog
            v-model="showQuickAddDialog"
            v-model:member="newMember"
            @submit="createAndAddMember"
            @close="closeQuickAddDialog"
        />

        <!-- Court Drawing Dialog -->
        <CourtDrawingDialog
            v-model="showDrawingDialog"
            :initial-drawing-data="editingGroupActivity ? (editingGroupActivity.groupPredefinedActivity ? drawingDataFor(editingGroupActivity.groupPredefinedActivity) : (editingGroupActivity.activityItem && editingGroupActivity.activityItem.drawingData ? (typeof editingGroupActivity.activityItem.drawingData === 'string' ? JSON.parse(editingGroupActivity.activityItem.drawingData) : editingGroupActivity.activityItem.drawingData) : null)) : null"
            :initial-code="editingGroupActivity && editingGroupActivity.groupPredefinedActivity ? (editingGroupActivity.groupPredefinedActivity.code || editingGroupActivity.groupPredefinedActivity.name) : (editingGroupActivity && editingGroupActivity.activityItem ? editingGroupActivity.activityItem.activity : null)"
            :initial-name="editingGroupActivity && editingGroupActivity.groupPredefinedActivity ? editingGroupActivity.groupPredefinedActivity.name : (editingGroupActivity && editingGroupActivity.activityItem ? editingGroupActivity.activityItem.activity : null)"
            :initial-description="editingGroupActivity && editingGroupActivity.groupPredefinedActivity ? editingGroupActivity.groupPredefinedActivity.description : null"
            :show-diary-fields="true"
            :show-duration-fields="!addNewGroupActivity && (!editingGroupActivity || editingGroupActivity.isNormalActivity)"
            :show-group-select="addNewGroupActivity && !editingGroupActivity"
            :groups="groups"
            :initial-duration="editingGroupActivity && editingGroupActivity.groupPredefinedActivity ? editingGroupActivity.groupPredefinedActivity.duration : newPlanItem.duration"
            :initial-duration-text="editingGroupActivity && editingGroupActivity.groupPredefinedActivity ? editingGroupActivity.groupPredefinedActivity.durationText : newPlanItem.durationText"
            :initial-group-id="addNewGroupActivity && !editingGroupActivity ? newPlanItem.groupId : ''"
            @ok="handleDrawingDialogOkForDiary"
            @close="editingGroupActivity = null"
        />

        <!-- Mitglieder-Galerie Dialog -->
        <MemberGalleryDialog
            v-model="showGalleryDialog"
            :current-club="currentClub"
            :date="date"
            :is-participant="isParticipant"
            :should-show-member="shouldShowGalleryMember"
            :participant-status-map="participantStatusMap"
            @member-click="handleGalleryMemberClick"
        />

        <GroupPhotoCropDialog
            v-model="showGroupPhotoCropDialog"
            :club-id="currentClub"
            :members="members"
            @member-image-updated="handleDiaryGroupPhotoMemberImageUpdated"
        />

        <MemberOrdersDialog
            v-if="showMemberOrdersDialog && selectedMemberForOrders"
            v-model="showMemberOrdersDialog"
            :member="selectedMemberForOrders"
            :club-id="currentClub"
            @close="closeOrdersDialog"
        />
    </div>
    
    <!-- Info Dialog -->
    <InfoDialog
        v-model="infoDialog.isOpen"
        :title="infoDialog.title"
        :message="infoDialog.message"
        :details="infoDialog.details"
        :type="infoDialog.type"
    />
    
    <!-- Confirm Dialog -->
    <ConfirmDialog
        v-model="confirmDialog.isOpen"
        :title="confirmDialog.title"
        :message="confirmDialog.message"
        :details="confirmDialog.details"
        :type="confirmDialog.type"
        @confirm="handleConfirmResult(true)"
        @cancel="handleConfirmResult(false)"
    />
</template>

<script>
import { mapGetters } from 'vuex';
import apiClient from '../apiClient.js';
import Multiselect from 'vue-multiselect';
import Sortable from 'sortablejs';
import PDFGenerator from '../components/PDFGenerator.js';
import CourtDrawingRender from '../components/CourtDrawingRender.vue';
import CourtDrawingDialog from '../components/CourtDrawingDialog.vue';
import InfoDialog from '../components/InfoDialog.vue';
import ConfirmDialog from '../components/ConfirmDialog.vue';
import ImageDialog from '../components/ImageDialog.vue';
import BaseDialog from '../components/BaseDialog.vue';
import MemberNotesDialog from '../components/MemberNotesDialog.vue';
import TagHistoryDialog from '../components/TagHistoryDialog.vue';
import MemberActivityStatsDialog from '../components/MemberActivityStatsDialog.vue';
import AccidentFormDialog from '../components/AccidentFormDialog.vue';
import QuickAddMemberDialog from '../components/QuickAddMemberDialog.vue';
import MemberGalleryDialog from '../components/MemberGalleryDialog.vue';
import MemberOrdersDialog from '../components/MemberOrdersDialog.vue';
import GroupPhotoCropDialog from '../components/members/GroupPhotoCropDialog.vue';
import DiaryParticipantsPanel from '../components/DiaryParticipantsPanel.vue';
import DiaryActivitiesPanel from '../components/DiaryActivitiesPanel.vue';
import DiaryOverviewPanels from '../components/diary/DiaryOverviewPanels.vue';
import {
    connectSocket,
    disconnectSocket,
    onParticipantAdded,
    onParticipantRemoved,
    onParticipantUpdated,
    onDiaryNoteAdded,
    onDiaryNoteDeleted,
    onDiaryTagAdded,
    onDiaryTagRemoved,
    onDiaryDateUpdated,
    onActivityMemberAdded,
    onActivityMemberRemoved,
    onActivityChanged,
    onMemberChanged,
    onGroupChanged,
    offParticipantAdded,
    offParticipantRemoved,
    offParticipantUpdated,
    offDiaryNoteAdded,
    offDiaryNoteDeleted,
    offDiaryTagAdded,
    offDiaryTagRemoved,
    offDiaryDateUpdated,
    offActivityMemberAdded,
    offActivityMemberRemoved,
    offActivityChanged,
    offMemberChanged,
    offGroupChanged
} from '../services/socketService.js';

const STANDARD_DIARY_ACTIVITY_NAMES = [
    'Begrüßung',
    'Aktivierung',
    'Aufbauen',
    'Turnier',
    'Abbauen',
    'Abschlussgespräch',
];

const normalizeStandardActivityFlag = (activity) => ({
    ...(activity || {}),
    excludeFromStats: Boolean(activity?.excludeFromStats ?? activity?.exclude_from_stats),
});

export default {
    name: 'DiaryView',
    components: { 
        Multiselect, 
        CourtDrawingRender,
        CourtDrawingDialog,
        InfoDialog,
        ConfirmDialog,
        ImageDialog,
        BaseDialog,
        MemberNotesDialog,
        TagHistoryDialog,
        MemberActivityStatsDialog,
        AccidentFormDialog,
        QuickAddMemberDialog,
        MemberGalleryDialog,
        MemberOrdersDialog,
        GroupPhotoCropDialog,
        DiaryParticipantsPanel,
        DiaryActivitiesPanel,
        DiaryOverviewPanels
    },
    data() {
        return {
            // Dialog States
            infoDialog: {
                isOpen: false,
                title: '',
                message: '',
                details: '',
                type: 'info'
            },
            confirmDialog: {
                isOpen: false,
                title: '',
                message: '',
                details: '',
                type: 'info',
                resolveCallback: null
            },
            date: null,
            dates: [],
            showForm: false,
            newDate: '',
            trainingStart: '',
            trainingEnd: '',
            excludeFromBilling: false,
            members: [],
            participants: [],
            showTrainingGroupDialog: false,
            trainingGroups: [],
            selectedTrainingGroupId: null,
            trainingTimes: [],
            suggestedDate: null,
            suggestedStartTime: null,
            suggestedEndTime: null,
            newActivity: '',
            activities: [],
            notes: [],
            newNoteContent: '',
            noteMember: null,
            selectedMemberForOrders: null,
            selectedMember: null,
            showNotesModal: false,
            showMemberOrdersDialog: false,
            selectedActivityTags: [],
            selectedMemberTags: [],
            selectedMemberDayTags: [],
            availableTags: [],
            previousActivityTags: [],
            previousMemberTags: [],
            trainingPlan: [],
            newPlanItem: {
                activity: '',
                duration: '',
                durationText: '',
                groupId: '',
                predefinedActivityId: null,
                isTimeBlock: false,
            },
            standardDiaryActivityDefinitions: STANDARD_DIARY_ACTIVITY_NAMES.map((name) => ({ name })),
            predefinedActivities: [],
            standardPredefinedActivities: [],
            showDropdown: false,
            showImage: false,
            imageUrl: '',
            showRenderModal: false,
            renderModalData: null,
            groups: [],
            currentTimeBlockId: null,
            selectedTimeblockId: null,
            newGroupCount: 2,
            addtype: 'activity',
            addNewItem: false,
            addNewGroupActivity: false,
            addNewTimeblock: false,
            activeOverviewPanel: 'trainingDay',
            editingGroupId: null,
            doMemberTagUpdates: true,
            showTagHistoryModal: false,
            tagHistoryMember: null,
            tagHistory: null,
            showActivityStatsModal: false,
            activityStatsMember: null,
            lastParticipations: [],
            activityStats: [],
            intermediateTimes: [],
            bellSound: null,
            thumbSound: null,
            soundEnabled: true,
            debugSound: true,
            timeChecker: null,
            playedActivityMarks: [],
            showAccidentForm: false,
            accident: {
                memberId: '',
                diaryDateId: '',
                accident: '',
            },
            accidents: [],
            editingActivityId: null, // ID der Aktivität, die gerade bearbeitet wird
            // Suche für Inline-Edit
            showGalleryDialog: false,
            showGroupPhotoCropDialog: false,
            editShowDropdown: false,
            editSearchResults: [],
            editSearchForId: null,
            editingActivityText: '',
            editingDuration: null,
            editingDurationText: '',
            // Suche für Neue-Item-Eingabe
            newItemShowDropdown: false,
            newItemSearchResults: [],
            // Aktivitäten-Box (rechts)
            showActivitiesBox: false,
            // Aktivitäts-Teilnehmer
            activityMembersOpenId: null,
            activityMembersMap: {}, // key: activityId, value: Set(participantIds)
            activityGroupsMap: {}, // key: activityId, value: groupId
            participantMapByMemberId: {}, // key: memberId, value: participantId
            memberGroupsMap: {}, // key: memberId, value: groupId
            participantStatusMap: {}, // key: memberId, value: attendanceStatus
            groupActivityMembersOpenId: null,
            groupActivityMembersMap: {}, // key: groupActivityId, value: Set(participantIds)
            editingGroupActivity: null, // Gruppenaktivität, die gerade bearbeitet wird
            editingGroupActivityId: null, // ID der Gruppenaktivität, die inline bearbeitet wird
            editingGroupActivityText: '', // Text für inline-edit
            editingGroupActivityDuration: null,
            editingGroupActivityDurationText: '',
            editingGroupActivityGroupId: '',
            // Schnell hinzufügen Dialog
            showQuickAddDialog: false,
            newMember: {
                firstName: '',
                lastName: '',
                birthDate: '',
                gender: ''
            },
            // Court Drawing Dialog
            showDrawingDialog: false,
            // Tab-Navigation für Mobile
            activeTab: 'plan', // 'plan', 'members', 'activities'
            isMobileView: typeof window !== 'undefined' ? window.innerWidth <= 768 : false,
            participantSearchQuery: '',
            participantFilter: 'all',
            planGroupFilter: '__all__',
            quickCreateBusy: false
        };
    },
    watch: {
        selectedMemberTags(newTags) {
            this.updateMemberTags(newTags);
        },
        selectedActivityTags(newTags) {
            this.updateActivityTags(newTags);
        },
        currentClub(newClubId, oldClubId) {
            // Wenn Club wechselt, Socket neu verbinden
            if (newClubId && newClubId !== oldClubId) {
                this.removeSocketListeners();
                connectSocket(newClubId);
                this.setupSocketListeners();
            }
        }
    },
    computed: {
        ...mapGetters(['isAuthenticated', 'currentClub', 'currentClubName']),
        calculateNextTime() {
            this.calculateAllItemTimes();
            if (this.trainingPlan.length === 0) {
                return this.trainingStart;
            }
            const lastItem = this.trainingPlan[this.trainingPlan.length - 1];
            return lastItem.endTime;
        },

        filteredPredefinedActivities() {
            const input = this.newPlanItem.activity.toLowerCase();
            return this.predefinedActivities.filter(activity =>
                activity.name.toLowerCase().includes(input)
            );
        },
        presentMembers() {
            // participants enthält memberIds der anwesenden
            const presentSet = new Set(this.participants);
            return this.members.filter(m => presentSet.has(m.id));
        },
        activeMembers() {
            return (this.members || []).filter(member => member && member.active);
        },
        activeMemberCount() {
            return this.activeMembers.length;
        },
        excusedActiveMemberCount() {
            return this.activeMembers.filter(member => this.getParticipantStatus(member.id) === 'excused').length;
        },
        availableParticipantCount() {
            return Math.max(this.activeMemberCount - this.excusedActiveMemberCount, 0);
        },
        timeblockCount() {
            return (this.trainingPlan || []).filter(item => item && item.isTimeblock).length;
        },
        standalonePlanItemCount() {
            return (this.trainingPlan || []).filter(item => item && !item.isTimeblock).length;
        },
        showGroupedPlanTable() {
            return this.planGroupFilter === '__all__' && Array.isArray(this.groups) && this.groups.length > 0;
        },
        groupedPlanRows() {
            if (!this.showGroupedPlanTable) return [];
            const rowsByKey = new Map();
            const toMinutes = (timeValue) => {
                if (!timeValue || typeof timeValue !== 'string' || !timeValue.includes(':')) {
                    return Number.MAX_SAFE_INTEGER;
                }
                const [h, m] = timeValue.split(':').map((part) => parseInt(part, 10));
                if (!Number.isFinite(h) || !Number.isFinite(m)) {
                    return Number.MAX_SAFE_INTEGER;
                }
                return (h * 60) + m;
            };

            for (const item of (this.trainingPlan || [])) {
                if (!item || item.isTimeblock) continue;
                const key = item.startTime || `unknown-${item.id}`;
                if (!rowsByKey.has(key)) {
                    rowsByKey.set(key, {
                        key,
                        startTime: item.startTime || '',
                        sharedItems: [],
                        groupItems: {}
                    });
                }
                const row = rowsByKey.get(key);
                const groupId = Number(item.groupId);
                if (Number.isFinite(groupId) && groupId > 0) {
                    if (!Array.isArray(row.groupItems[groupId])) {
                        row.groupItems[groupId] = [];
                    }
                    row.groupItems[groupId].push(item);
                } else {
                    row.sharedItems.push(item);
                }
            }

            const sortItems = (items) => items.slice().sort((a, b) => {
                const orderA = Number.isFinite(Number(a?.orderId)) ? Number(a.orderId) : Number.MAX_SAFE_INTEGER;
                const orderB = Number.isFinite(Number(b?.orderId)) ? Number(b.orderId) : Number.MAX_SAFE_INTEGER;
                if (orderA !== orderB) return orderA - orderB;
                return Number(a?.id || 0) - Number(b?.id || 0);
            });

            const rows = Array.from(rowsByKey.values()).map((row) => {
                row.sharedItems = sortItems(row.sharedItems);
                for (const group of this.groups || []) {
                    const groupId = Number(group.id);
                    if (Array.isArray(row.groupItems[groupId])) {
                        row.groupItems[groupId] = sortItems(row.groupItems[groupId]);
                    }
                }
                return row;
            });

            return rows.sort((a, b) => {
                const startA = toMinutes(a?.startTime);
                const startB = toMinutes(b?.startTime);
                if (startA !== startB) return startA - startB;
                return String(a?.key || '').localeCompare(String(b?.key || ''));
            });
        },
        filteredTrainingPlan() {
            const allItems = Array.isArray(this.trainingPlan) ? this.trainingPlan : [];
            const toMinutes = (timeValue) => {
                if (!timeValue || typeof timeValue !== 'string' || !timeValue.includes(':')) {
                    return Number.MAX_SAFE_INTEGER;
                }
                const [h, m] = timeValue.split(':').map((part) => parseInt(part, 10));
                if (!Number.isFinite(h) || !Number.isFinite(m)) {
                    return Number.MAX_SAFE_INTEGER;
                }
                return (h * 60) + m;
            };

            const sortByStartTime = (items) => items.slice().sort((a, b) => {
                const startA = toMinutes(a?.startTime);
                const startB = toMinutes(b?.startTime);
                if (startA !== startB) return startA - startB;

                const orderA = Number.isFinite(Number(a?.orderId)) ? Number(a.orderId) : Number.MAX_SAFE_INTEGER;
                const orderB = Number.isFinite(Number(b?.orderId)) ? Number(b.orderId) : Number.MAX_SAFE_INTEGER;
                if (orderA !== orderB) return orderA - orderB;

                return Number(a?.id || 0) - Number(b?.id || 0);
            });

            if (this.planGroupFilter === '__all__') {
                return sortByStartTime(allItems);
            }
            const selectedGroupId = Number(this.planGroupFilter);
            if (!Number.isFinite(selectedGroupId)) {
                return sortByStartTime(allItems);
            }
            const filtered = allItems.filter((item) => {
                if (!item) return false;
                if (item.isTimeblock) {
                    return this.getVisibleGroupActivities(item).length > 0;
                }
                if (!item.groupId) {
                    // Globale Aktivitäten immer sichtbar
                    return true;
                }
                return Number(item.groupId) === selectedGroupId;
            });
            return sortByStartTime(filtered);
        },
        activePlanEditorType() {
            if (this.editingActivityId) return 'activity';
            if (this.editingGroupActivityId) return 'groupActivity';
            return null;
        },
        activePlanEditorItem() {
            if (this.editingActivityId) {
                return (this.trainingPlan || []).find(item => Number(item.id) === Number(this.editingActivityId)) || null;
            }
            if (this.editingGroupActivityId) {
                for (const item of this.trainingPlan || []) {
                    const match = (item.groupActivities || []).find(groupItem => Number(groupItem.id) === Number(this.editingGroupActivityId));
                    if (match) return match;
                }
            }
            return null;
        },
        activeAssignmentType() {
            if (this.activityMembersOpenId) return 'activity';
            if (this.groupActivityMembersOpenId) return 'groupActivity';
            return null;
        },
        activeAssignmentItem() {
            if (this.activityMembersOpenId) {
                return (this.trainingPlan || []).find(item => Number(item.id) === Number(this.activityMembersOpenId)) || null;
            }
            if (this.groupActivityMembersOpenId) {
                for (const item of this.trainingPlan || []) {
                    const match = (item.groupActivities || []).find(groupItem => Number(groupItem.id) === Number(this.groupActivityMembersOpenId));
                    if (match) return match;
                }
            }
            return null;
        },
        openPlanItems() {
            const result = [];
            for (const item of this.trainingPlan || []) {
                if (!item?.isTimeblock && !this.isStructuralPlanItem(item) && this.getPlanItemStatus(item).key === 'open') {
                    result.push(item);
                }
                for (const groupItem of item.groupActivities || []) {
                    if (!this.isStructuralPlanItem(groupItem) && this.getPlanItemStatus(groupItem).key === 'open') {
                        result.push(groupItem);
                    }
                }
            }
            return result;
        },
        standardDiaryActivities() {
            if (this.standardPredefinedActivities.length > 0) {
                return [...this.standardPredefinedActivities].sort((a, b) => {
                    const aIndex = STANDARD_DIARY_ACTIVITY_NAMES.indexOf(a.name);
                    const bIndex = STANDARD_DIARY_ACTIVITY_NAMES.indexOf(b.name);
                    if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
                    if (aIndex !== -1) return -1;
                    if (bIndex !== -1) return 1;
                    return a.name.localeCompare(b.name, 'de-DE');
                });
            }

            return this.standardDiaryActivityDefinitions.map((definition) => {
                const existing = this.predefinedActivities.find((activity) => activity.name === definition.name);
                return existing || definition;
            }).sort((a, b) => {
                const aIndex = STANDARD_DIARY_ACTIVITY_NAMES.indexOf(a.name);
                const bIndex = STANDARD_DIARY_ACTIVITY_NAMES.indexOf(b.name);
                if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
                if (aIndex !== -1) return -1;
                if (bIndex !== -1) return 1;
                return a.name.localeCompare(b.name, 'de-DE');
            });
        },
        filteredDiaryMembers() {
            const search = (this.participantSearchQuery || '').trim().toLowerCase();

            return this.sortedMembers().filter(member => {
                const isPresent = this.isParticipant(member.id);
                const isExcused = this.getParticipantStatus(member.id) === 'excused';

                if (this.participantFilter === 'present' && !isPresent) return false;
                if (this.participantFilter === 'absent' && isPresent) return false;
                if (this.participantFilter === 'excused' && !isExcused) return false;
                if (this.participantFilter === 'test' && !member.testMembership) return false;

                if (!search) return true;

                const haystack = [
                    member.firstName,
                    member.lastName,
                    member.phone,
                    member.email
                ]
                    .filter(Boolean)
                    .join(' ')
                    .toLowerCase();

                return haystack.includes(search);
            });
        },

        isNewMemberValid() {
            return this.newMember.firstName.trim() !== '' &&
                (this.newMember.gender === 'male' || this.newMember.gender === 'female' || this.newMember.gender === 'diverse');
        },

        canDeleteCurrentDate() {
            if (!this.date) return false;

            // Prüfe ob keine Inhalte vorhanden sind
            const hasTrainingPlan = this.trainingPlan && this.trainingPlan.length > 0;
            const hasParticipants = this.participants && this.participants.length > 0;
            const hasActivities = this.activities && this.activities.length > 0;
            const hasAccidents = this.accidents && this.accidents.length > 0;
            const hasNotes = this.notes && this.notes.length > 0;

            // Kann gelöscht werden wenn alle Listen leer sind
            return !hasTrainingPlan && !hasParticipants && !hasActivities && !hasAccidents && !hasNotes;
        },
        diaryTimeRangeLabel() {
            const formattedStart = this.formatDisplayTime(this.trainingStart);
            const formattedEnd = this.formatDisplayTime(this.trainingEnd);
            if (formattedStart && formattedEnd) {
                return `${formattedStart} - ${formattedEnd}`;
            }
            if (formattedStart) {
                return formattedStart;
            }
            if (formattedEnd) {
                return formattedEnd;
            }
            return this.$t('diary.trainingWindowUnset');
        },
        normalizedNextStartTime() {
            const raw = this.calculateNextTime;
            if (!raw) return '–';
            const value = String(raw);
            return value.length >= 5 ? value.slice(0, 5) : value;
        },
        diaryStatusText() {
            if (!this.date) {
                return this.$t('diary.noActiveTrainingDay');
            }

            const hasTimes = Boolean(this.trainingStart || this.trainingEnd);
            const hasPlan = this.trainingPlan.length > 0;
            const hasActivities = this.activities.length > 0;

            if (hasTimes && hasPlan && this.openPlanItems.length === 0) {
                return this.$t('diary.statusReady');
            }

            if (!hasPlan && !hasActivities && !hasTimes) {
                return this.$t('diary.statusEmpty');
            }

            return this.$t('diary.statusInProgress');
        }
    },
    methods: {
        isDiaryDayConfigured() {
            const hasTimes = Boolean(this.trainingStart || this.trainingEnd);
            const hasPlan = Array.isArray(this.trainingPlan) && this.trainingPlan.length > 0;
            return hasTimes && hasPlan;
        },
        toggleOverviewPanel(panel) {
            this.activeOverviewPanel = this.activeOverviewPanel === panel ? null : panel;
        },
        // Dialog Helper Methods
        async showInfo(title, message, details = '', type = 'info') {
            this.infoDialog = {
                isOpen: true,
                title,
                message,
                details,
                type
            };
        },
        
        async showConfirm(title, message, details = '', type = 'info') {
            return new Promise((resolve) => {
                this.confirmDialog = {
                    isOpen: true,
                    title,
                    message,
                    details,
                    type,
                    resolveCallback: resolve
                };
            });
        },
        
        handleConfirmResult(confirmed) {
            if (this.confirmDialog.resolveCallback) {
                this.confirmDialog.resolveCallback(confirmed);
                this.confirmDialog.resolveCallback = null;
            }
            this.confirmDialog.isOpen = false;
        },
        async openGalleryDialog() {
            if (!this.currentClub) {
                return;
            }
            this.showGalleryDialog = true;
        },
        async handleGalleryMemberClick(member) {
            if (!this.date) {
                return;
            }
            console.log('[handleGalleryMemberClick] Clicked member:', member);
            await this.toggleParticipant(member.memberId);
        },
        async handleDiaryGroupPhotoMemberImageUpdated(event) {
            const { memberId } = event || {};
            const member = this.members.find(entry => String(entry.id) === String(memberId));
            if (member) {
                member.hasImage = true;
            }
            await this.showInfo(this.$t('messages.success'), this.$t('members.groupPhotoCropSaved'), '', 'success');
        },
        
        hasItemDrawingData(item) {
            if (!item) return false;
            try {
                // Prüfe direktes drawingData am item
                if (item.drawingData) {
                    if (typeof item.drawingData === 'string' && item.drawingData.trim() !== '') return true;
                    if (typeof item.drawingData === 'object' && Object.keys(item.drawingData).length > 0) return true;
                }
                // Prüfe auch über predefinedActivity
                if (item.predefinedActivity && this.hasActivityVisual(item.predefinedActivity)) return true;
                if (item.groupPredefinedActivity && this.hasActivityVisual(item.groupPredefinedActivity)) return true;
            } catch (e) { }
            return false;
        },
        getPlanItemVisualSource(item) {
            if (!item) return null;
            if (item.predefinedActivity) return item.predefinedActivity;
            if (item.groupPredefinedActivity) return item.groupPredefinedActivity;
            if (!this.hasItemDrawingData(item)) return null;
            return {
                name: item.activity || '',
                code: item.activity || '',
                drawingData: item.drawingData || null,
                renderCode: item.renderCode || '',
                renderSpec: item.renderSpec || null,
                imageLink: item.imageLink || '',
                images: Array.isArray(item.images) ? item.images : []
            };
        },
        async openPlanItemVisual(item) {
            const source = this.getPlanItemVisualSource(item);
            if (source) {
                await this.openActivityVisual(source);
            }
        },
        
        hasActivityVisual(pa) {
            if (!pa) return false;
            try {
                // direktes drawingData am PA (kann String oder Objekt sein)
                if (pa.drawingData) {
                    if (typeof pa.drawingData === 'string' && pa.drawingData.trim() !== '') return true;
                    if (typeof pa.drawingData === 'object' && Object.keys(pa.drawingData).length > 0) return true;
                }
                // Bildliste - prüfe sowohl auf drawingData als auch auf normale Bilder
                if (Array.isArray(pa.images) && pa.images.length > 0) {
                    // Prüfe auf Bilder mit drawingData
                    if (pa.images.some(img => {
                        if (!img || !img.drawingData) return false;
                        if (typeof img.drawingData === 'string' && img.drawingData.trim() !== '') return true;
                        if (typeof img.drawingData === 'object' && Object.keys(img.drawingData).length > 0) return true;
                        return false;
                    })) return true;
                    // Prüfe auf normale Bilder (auch ohne drawingData)
                    if (pa.images.some(img => img && (img.imagePath || img.id))) return true;
                }
                // gerenderter Code / renderSpec
                if (pa.renderCode && pa.renderCode.trim() !== '') return true;
                if (pa.renderSpec && Object.keys(pa.renderSpec).length) return true;
                // imageLink für normale Bilder - nur wenn es tatsächlich ein Bild gibt
                // imageLink enthält eine Image-ID (z.B. /image/123), wenn ein Bild vorhanden ist
                // Der Fallback-Pfad ohne Image-ID (/image) wird ignoriert
                if (pa.imageLink && pa.imageLink.trim() !== '') {
                    // Prüfe, ob imageLink eine Image-ID enthält (dann ist es ein echtes Bild)
                    // Format: /api/predefined-activities/{id}/image/{imageId}
                    const imageIdMatch = pa.imageLink.match(/\/image\/(\d+)/);
                    if (imageIdMatch) return true;
                    // Oder prüfe, ob images Array vorhanden ist (dann gibt es Bilder)
                    if (Array.isArray(pa.images) && pa.images.length > 0) return true;
                }
            } catch (e) { }
            return false;
        },
        drawingDataFor(pa) {
            // Zeichnungsdaten können bereits als Objekt vorliegen oder als JSON-String
            try {
                if (!pa) return null;
                if (pa.drawingData && typeof pa.drawingData === 'object') {
                    const data = { ...pa.drawingData };
                    // Kürzel aus PA anreichern
                    if (pa.code && !data.code) data.code = pa.code;
                    if (pa.renderCode && !data.code) data.code = pa.renderCode;
                    // Falls Startposition nicht gesetzt (oder nur "AS"), aus renderCode ableiten
                    this._ensureStartPositionFromRenderCode(pa, data);
                    return data;
                }
                if (pa.drawingData && typeof pa.drawingData === 'string') {
                    const parsed = JSON.parse(pa.drawingData);
                    if (pa.code && !parsed.code) parsed.code = pa.code;
                    if (pa.renderCode && !parsed.code) parsed.code = pa.renderCode;
                    this._ensureStartPositionFromRenderCode(pa, parsed);
                    return parsed;
                }
                // Fallback: falls über images[0].drawingData geliefert wurde
                if (pa.images && pa.images.length) {
                    // Nimm das erste Bild, das drawingData enthält
                    const withData = pa.images.find(img => !!img.drawingData);
                    if (withData) {
                        const parsedImg = typeof withData.drawingData === 'string'
                            ? JSON.parse(withData.drawingData)
                            : withData.drawingData;
                        if (pa.code && !parsedImg.code) parsedImg.code = pa.code;
                        if (pa.renderCode && !parsedImg.code) parsedImg.code = pa.renderCode;
                        this._ensureStartPositionFromRenderCode(pa, parsedImg);
                        return parsedImg;
                    }
                }
            } catch (e) {
                // Fehler beim Parsen ignorieren
            }
            return null;
        },
        _ensureStartPositionFromRenderCode(pa, data) {
            try {
                if (!data) return;
                // Immer renderCode mitgeben, wenn vorhanden
                if (pa && pa.renderCode) {
                    data.renderCode = pa.renderCode;
                }
                const hasExplicit = data.selectedStartPosition === 'AS1' || data.selectedStartPosition === 'AS2' || data.selectedStartPosition === 'AS3';
                if (hasExplicit) return;
                const code = pa && (pa.code || pa.renderCode) ? String(pa.code || pa.renderCode) : '';
                if (!code) return;
                // Suche nach ASvL/ASvM/ASvR
                const m = code.match(/ASv([LMR])/);
                if (m) {
                    const map = { L: 'AS1', M: 'AS2', R: 'AS3' };
                    data.selectedStartPosition = map[m[1]] || 'AS2';
                }
            } catch (e) { }
        },
        async init() {
            if (this.isAuthenticated && this.currentClub) {
                const response = await apiClient.get(`/diary/${this.currentClub}`);
                this.dates = response.data.map(entry => ({ id: entry.id, date: entry.date }));

                // Automatisch das Datum mit den meisten Einträgen auswählen
                await this.autoSelectDateWithEntries();

                await this.loadTags();
                await this.loadPredefinedActivities();
            }
        },

        async autoSelectDateWithEntries() {
            if (this.dates.length === 0) {
                this.date = null;
                return;
            }

            const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD Format

            // 1. Zuerst prüfe das heutige Datum
            const todayEntry = this.dates.find(date => date.date === today);
            if (todayEntry) {
                const todayEntries = await this.countEntriesForDate(todayEntry.id);
                if (todayEntries > 0) {
                    this.date = todayEntry;
                    await this.handleDateChange();
                    return;
                }
            }

            // 2. Falls heutiges Datum nicht gefunden oder keine Einträge vorhanden
            // → Wähle das erste Datum aus der Liste
            if (this.dates.length > 0) {
                this.date = this.dates[0];
                await this.handleDateChange();
            } else {
                this.date = null;
            }
        },

        async countEntriesForDate(dateId) {
            try {
                // Lade Teilnehmer
                const participantsResponse = await apiClient.get(`/participants/${dateId}`);
                const participantCount = participantsResponse.data.length;

                // Lade Aktivitäten
                const activitiesResponse = await apiClient.get(`/activities/${dateId}`);
                const activityCount = activitiesResponse.data.length;

                // Lade Trainingplan
                const trainingPlanResponse = await apiClient.get(`/diary-date-activities/${this.currentClub}/${dateId}`);
                const trainingPlanCount = trainingPlanResponse.data.length;

                // Gesamtanzahl der Einträge
                return participantCount + activityCount + trainingPlanCount;
            } catch (error) {
                return 0;
            }
        },

        async refreshDates(selectId) {
            const response = await apiClient.get(`/diary/${this.currentClub}`);
            this.dates = response.data.map(entry => ({ id: entry.id, date: entry.date }));
            // neueste zuerst
            this.dates.sort((a, b) => new Date(b.date) - new Date(a.date));
            if (selectId) {
                const match = this.dates.find(d => String(d.id) === String(selectId));
                if (match) this.date = { id: match.id, date: match.date };
            }
        },

        setCurrentDate() {
            const today = new Date().toISOString().split('T')[0];
            this.newDate = today;
        },

        async openNewDateDialog() {
            // Zeige Dialog zur Trainingsgruppen-Auswahl
            await this.loadTrainingGroups();
            this.showTrainingGroupDialog = true;
            this.showForm = false;
        },

        diaryDateKey(entry) {
            if (!entry || entry.date == null) return '';
            return String(entry.date).substring(0, 10);
        },

        localYyyyMmDd(d) {
            const y = d.getFullYear();
            const m = String(d.getMonth() + 1).padStart(2, '0');
            const day = String(d.getDate()).padStart(2, '0');
            return `${y}-${m}-${day}`;
        },

        /** Wochentag aus API (0=So … 6=Sa) zuverlässig als Zahl – vermeidet Strict-===-Fehler bei String-Werten. */
        trainingWeekdayNumber(tt) {
            if (tt == null || tt.weekday === undefined || tt.weekday === null) return NaN;
            const w = Number(tt.weekday);
            return Number.isFinite(w) ? w : parseInt(String(tt.weekday), 10);
        },

        trainingStartToMinutes(start) {
            const s = String(start || '').trim();
            const base = s.length >= 5 ? s.substring(0, 5) : s;
            const parts = base.split(':');
            if (parts.length < 2) return null;
            const h = parseInt(parts[0], 10);
            const m = parseInt(parts[1], 10);
            if (!Number.isFinite(h) || !Number.isFinite(m)) return null;
            return h * 60 + m;
        },

        findNextQuickSlotAcrossGroups(groups) {
            if (!Array.isArray(groups) || groups.length === 0) return null;
            const eligible = groups.filter((g) => !g.excludeFromQuickDiaryCreate);
            const existing = new Set((this.dates || []).map((d) => this.diaryDateKey(d)));
            const today = new Date();
            for (let dayOffset = 0; dayOffset <= 366; dayOffset++) {
                const checkDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + dayOffset);
                const checkWeekday = checkDate.getDay();
                const dateStr = this.localYyyyMmDd(checkDate);
                if (existing.has(dateStr)) continue;
                const candidates = [];
                for (const g of eligible) {
                    for (const tt of g.trainingTimes || []) {
                        if (this.trainingWeekdayNumber(tt) !== checkWeekday) continue;
                        if (!tt.startTime || !String(tt.startTime).trim()) continue;
                        const startMin = this.trainingStartToMinutes(tt.startTime);
                        if (startMin == null) continue;
                        candidates.push({
                            startMin,
                            dateStr,
                            sortOrder: Number.isFinite(Number(g.sortOrder)) ? Number(g.sortOrder) : 1e9,
                            groupId: Number(g.id) || 0,
                            timeId: Number(tt.id) || 0,
                            startTime: this.formatTimeForInput(tt.startTime),
                            endTime: this.formatTimeForInput(tt.endTime),
                        });
                    }
                }
                if (!candidates.length) continue;
                candidates.sort((a, b) => {
                    if (a.startMin !== b.startMin) return a.startMin - b.startMin;
                    if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder;
                    if (a.groupId !== b.groupId) return a.groupId - b.groupId;
                    return a.timeId - b.timeId;
                });
                const best = candidates[0];
                return {
                    date: best.dateStr,
                    startTime: best.startTime,
                    endTime: best.endTime,
                };
            }
            return null;
        },

        async quickCreateNextTraining() {
            if (!this.currentClub || this.quickCreateBusy) return;
            this.quickCreateBusy = true;
            try {
                const response = await apiClient.get(`/training-times/${this.currentClub}`);
                const groups = Array.isArray(response.data) ? response.data : [];
                const slot = this.findNextQuickSlotAcrossGroups(groups);
                if (!slot) {
                    this.showInfo(this.$t('messages.info'), this.$t('diary.quickCreateNoSlot'), '', 'info');
                    return;
                }
                const post = await apiClient.post(`/diary/${this.currentClub}`, {
                    date: slot.date,
                    trainingStart: slot.startTime || null,
                    trainingEnd: slot.endTime || null,
                    excludeFromBilling: false,
                });
                await this.refreshDates(post.data.id);
                await this.handleDateChange();
            } catch (error) {
                console.error('[quickCreateNextTraining]', error);
                this.showInfo(this.$t('messages.error'), this.$t('diary.quickCreateFailed'), '', 'error');
            } finally {
                this.quickCreateBusy = false;
            }
        },
        
        async handleDateChange() {
            this.showForm = false;
            if (this.date) {
                const dateId = this.date.id;
                const response = await apiClient.get(`/diary/${this.currentClub}`);
                const dateData = response.data.find(entry => entry.id === dateId);
                this.trainingStart = dateData.trainingStart;
                this.trainingEnd = dateData.trainingEnd;
                this.excludeFromBilling = Boolean(dateData.excludeFromBilling);
                this.selectedActivityTags = dateData.diaryTags.map(tag => ({
                    id: tag.id,
                    name: tag.name
                }));
                this.previousActivityTags = [...this.selectedActivityTags];
                await this.loadMembers();
                await this.loadParticipants(dateId);
                await this.loadActivities(dateId);
                await this.loadTrainingPlan();
                this.initializeSortable();
                await this.loadGroups();
                this.activeOverviewPanel = this.isDiaryDayConfigured() ? null : 'trainingDay';
                this.startCheckingTime();
            } else {
                this.newDate = '';
                this.trainingStart = '';
                this.trainingEnd = '';
                this.excludeFromBilling = false;
                this.participants = [];
            }
        },

        initializeSortable() {
            const el = this.$refs.sortableList;
            if (!el) return;
            Sortable.create(el, {
                draggable: '.plan-sortable-row',
                handle: ".drag-handle",
                onEnd: this.onDragEnd,
            });
        },

        async createDate() {
            try {
                const response = await apiClient.post(`/diary/${this.currentClub}`, {
                    date: this.newDate,
                    trainingStart: this.trainingStart || null,
                    trainingEnd: this.trainingEnd || null,
                    excludeFromBilling: this.excludeFromBilling,
                });
                this.dates.push({ id: response.data.id, date: response.data.date });
                // Liste nach Datum sortieren (neueste zuerst)
                await this.refreshDates(response.data.id);
                this.showForm = false;
                this.newDate = '';
                this.trainingStart = response.data.trainingStart;
                this.trainingEnd = response.data.trainingEnd;
                this.excludeFromBilling = Boolean(response.data.excludeFromBilling);
                // Direkt auf das leere Tagebuch des neuen Datums wechseln
                await this.handleDateChange();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async updateTrainingTimes() {
            try {
                const dateId = this.date.id;
                await apiClient.put(`/diary/${this.currentClub}`, {
                    dateId,
                    trainingStart: this.trainingStart || null,
                    trainingEnd: this.trainingEnd || null,
                    excludeFromBilling: this.excludeFromBilling,
                });
                this.showInfo(this.$t('messages.success'), this.$t('diary.trainingTimesUpdated'), '', 'success');
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async updateExcludeFromBillingImmediate(nextValue) {
            if (!this.date?.id) {
                this.excludeFromBilling = Boolean(nextValue);
                return;
            }
            const previousValue = Boolean(this.excludeFromBilling);
            this.excludeFromBilling = Boolean(nextValue);
            try {
                await apiClient.put(`/diary/${this.currentClub}`, {
                    dateId: this.date.id,
                    trainingStart: this.trainingStart || null,
                    trainingEnd: this.trainingEnd || null,
                    excludeFromBilling: this.excludeFromBilling,
                });
            } catch (error) {
                this.excludeFromBilling = previousValue;
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async loadMembers() {
            const response = await apiClient.get(`/clubmembers/get/${this.currentClub}/false`);
            // Erstelle ein neues Array, um Vue-Reaktivität sicherzustellen
            this.members = Array.isArray(response.data) ? [...response.data] : [];
        },
        
        async loadTrainingGroups() {
            try {
                const response = await apiClient.get(`/training-groups/${this.currentClub}`);
                this.trainingGroups = Array.isArray(response.data) ? response.data : [];
            } catch (error) {
                console.error('[loadTrainingGroups] Error:', error);
                this.trainingGroups = [];
            }
        },
        
        async onTrainingGroupSelected() {
            if (!this.selectedTrainingGroupId) {
                this.suggestedDate = null;
                this.suggestedStartTime = null;
                this.suggestedEndTime = null;
                return;
            }
            
            try {
                // Lade Trainingszeiten für diese Gruppe
                const response = await apiClient.get(`/training-times/${this.currentClub}`);
                const groups = Array.isArray(response.data) ? response.data : [];
                const selectedGroup = groups.find(g => g.id === parseInt(this.selectedTrainingGroupId));
                
                if (!selectedGroup || !selectedGroup.trainingTimes || selectedGroup.trainingTimes.length === 0) {
                    this.suggestedDate = null;
                    this.suggestedStartTime = null;
                    this.suggestedEndTime = null;
                    return;
                }
                
                // Finde den nächsten verfügbaren Wochentag
                const nextDate = this.findNextAvailableDate(selectedGroup.trainingTimes);
                if (nextDate) {
                    this.suggestedDate = nextDate.date;
                    this.suggestedStartTime = nextDate.startTime;
                    this.suggestedEndTime = nextDate.endTime;
                } else {
                    this.suggestedDate = null;
                    this.suggestedStartTime = null;
                    this.suggestedEndTime = null;
                }
            } catch (error) {
                console.error('[onTrainingGroupSelected] Error:', error);
                this.suggestedDate = null;
                this.suggestedStartTime = null;
                this.suggestedEndTime = null;
            }
        },
        
        findNextAvailableDate(trainingTimes) {
            if (!trainingTimes || trainingTimes.length === 0) {
                return null;
            }
            
            // Sortiere Trainingszeiten nach Wochentag und Startzeit
            const sortedTimes = [...trainingTimes].sort((a, b) => {
                if (a.weekday !== b.weekday) return a.weekday - b.weekday;
                return a.startTime.localeCompare(b.startTime);
            });
            
            const today = new Date();
            
            // Prüfe die nächsten 14 Tage (2 Wochen)
            for (let dayOffset = 0; dayOffset < 14; dayOffset++) {
                const checkDate = new Date(today);
                checkDate.setDate(today.getDate() + dayOffset);
                const checkWeekday = checkDate.getDay();
                
                // Finde Trainingszeiten für diesen Wochentag
                const timesForWeekday = sortedTimes.filter(tt => this.trainingWeekdayNumber(tt) === checkWeekday);
                
                if (timesForWeekday.length > 0) {
                    // Nimm die erste Trainingszeit für diesen Tag
                    const time = timesForWeekday[0];
                    // Prüfe, ob dieses Datum bereits existiert
                    const dateStr = this.localYyyyMmDd(checkDate);
                    const exists = this.dates.some(d => this.diaryDateKey(d) === dateStr);
                    
                    if (!exists) {
                        return {
                            date: dateStr,
                            startTime: this.formatTimeForInput(time.startTime),
                            endTime: this.formatTimeForInput(time.endTime)
                        };
                    }
                }
            }
            
            return null;
        },
        
        formatTimeForInput(time) {
            if (!time) return '';
            return time.substring(0, 5); // HH:MM für time input
        },
        
        applySuggestion() {
            if (this.suggestedDate) {
                this.newDate = this.suggestedDate;
                this.trainingStart = this.suggestedStartTime || '';
                this.trainingEnd = this.suggestedEndTime || '';
            }
            this.closeTrainingGroupDialog();
            this.showForm = true;
        },
        
        skipSuggestion() {
            this.closeTrainingGroupDialog();
            this.showForm = true;
        },
        
        closeTrainingGroupDialog() {
            this.showTrainingGroupDialog = false;
            this.selectedTrainingGroupId = null;
            this.suggestedDate = null;
            this.suggestedStartTime = null;
            this.suggestedEndTime = null;
        },

        async loadParticipants(dateId) {
            const response = await apiClient.get(`/participants/${dateId}`);
            const participantRows = response.data || [];
            this.participants = participantRows
                .filter(participant => !participant.attendanceStatus || participant.attendanceStatus === 'present')
                .map(participant => participant.memberId);
            this.participantMapByMemberId = participantRows.reduce((map, p) => {
                map[p.memberId] = p.id;
                return map;
            }, {});
            this.participantStatusMap = participantRows.reduce((map, p) => {
                map[p.memberId] = p.attendanceStatus || 'present';
                return map;
            }, {});
            this.memberGroupsMap = {};
            participantRows.forEach(p => {
                const groupValue = (p.groupId !== null && p.groupId !== undefined) ? String(p.groupId) : '';
                if (this.$set) {
                    this.$set(this.memberGroupsMap, p.memberId, groupValue);
                } else {
                    this.memberGroupsMap = {
                        ...this.memberGroupsMap,
                        [p.memberId]: groupValue
                    };
                }
            });
        },

        async loadActivities(dateId) {
            const response = await apiClient.get(`/activities/${dateId}`);
            this.activities = response.data;
        },

        async loadTags() {
            const response = await apiClient.get('/tags');
            this.availableTags = response.data;
        },

        async loadPredefinedActivities() {
            try {
                const response = await apiClient.get('/predefined-activities');
                this.predefinedActivities = (response.data || []).map(normalizeStandardActivityFlag);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorLoadingPredefinedActivities'), '', 'error');
            }
        },

        async loadStandardPredefinedActivities() {
            try {
                const response = await apiClient.get('/predefined-activities', {
                    params: { scope: 'standard' }
                });
                this.standardPredefinedActivities = (response.data || []).map(normalizeStandardActivityFlag);
            } catch (error) {
                this.standardPredefinedActivities = [];
            }
        },

        async loadGroups() {
            try {
                const response = await apiClient.get(`/group/${this.currentClub}/${this.date.id}`);
                this.groups = response.data;
                // Setze newGroupCount basierend auf vorhandenen Gruppen
                this.newGroupCount = this.groups.length > 0 ? 1 : 2;
            } catch (error) {
                // ignore
            }
        },

        isParticipant(memberId) {
            return this.participants.includes(memberId);
        },

        getParticipantStatus(memberId) {
            return this.participantStatusMap[memberId] || '';
        },
        getVisibleGroupActivities(timeblockItem) {
            const entries = Array.isArray(timeblockItem?.groupActivities) ? timeblockItem.groupActivities : [];
            if (this.planGroupFilter === '__all__') {
                return entries;
            }
            const selectedGroupId = Number(this.planGroupFilter);
            if (!Number.isFinite(selectedGroupId)) {
                return entries;
            }
            return entries.filter((entry) => Number(entry?.groupsGroupActivity?.id) === selectedGroupId);
        },

        shouldShowGalleryMember(member) {
            return this.getParticipantStatus(member.memberId) !== 'excused';
        },

        async toggleParticipant(memberId) {
            const isParticipant = this.isParticipant(memberId);
            const dateId = this.date.id;
            if (isParticipant) {
                await apiClient.post('/participants/remove', {
                    diaryDateId: dateId,
                    memberId
                });
                this.participants = this.participants.filter(id => id !== memberId);
                const nextStatusMap = { ...this.participantStatusMap };
                const nextParticipantMap = { ...this.participantMapByMemberId };
                const nextGroupMap = { ...this.memberGroupsMap };
                delete nextStatusMap[memberId];
                delete nextParticipantMap[memberId];
                delete nextGroupMap[memberId];
                this.participantStatusMap = nextStatusMap;
                this.participantMapByMemberId = nextParticipantMap;
                this.memberGroupsMap = nextGroupMap;
            } else {
                const response = await apiClient.post('/participants/add', {
                    diaryDateId: dateId,
                    memberId
                });
                this.participants = [...new Set([...this.participants, memberId])];
                this.participantStatusMap = {
                    ...this.participantStatusMap,
                    [memberId]: 'present'
                };
                this.participantMapByMemberId = {
                    ...this.participantMapByMemberId,
                    [memberId]: response.data.id
                };
            }
        },

        async updateParticipantStatus(memberId, status) {
            const dateId = this.date.id;
            const response = await apiClient.put(`/participants/${dateId}/${memberId}/status`, {
                attendanceStatus: status
            });
            const participant = response.data;

            this.participants = this.participants.filter(id => id !== memberId);
            this.participantStatusMap = {
                ...this.participantStatusMap,
                [memberId]: participant.attendanceStatus
            };
            this.participantMapByMemberId = {
                ...this.participantMapByMemberId,
                [memberId]: participant.id
            };
            this.memberGroupsMap = {
                ...this.memberGroupsMap,
                [memberId]: ''
            };
        },

        async clearParticipantStatus(memberId) {
            const dateId = this.date.id;

            if (this.isParticipant(memberId)) {
                this.participantStatusMap = {
                    ...this.participantStatusMap,
                    [memberId]: 'present'
                };
                return;
            }

            await apiClient.post('/participants/remove', {
                diaryDateId: dateId,
                memberId
            });
            const nextStatusMap = { ...this.participantStatusMap };
            const nextParticipantMap = { ...this.participantMapByMemberId };
            const nextGroupMap = { ...this.memberGroupsMap };
            delete nextStatusMap[memberId];
            delete nextParticipantMap[memberId];
            delete nextGroupMap[memberId];
            this.participantStatusMap = nextStatusMap;
            this.participantMapByMemberId = nextParticipantMap;
            this.memberGroupsMap = nextGroupMap;
        },

        async toggleParticipantStatus(memberId) {
            if (this.getParticipantStatus(memberId) === 'excused') {
                await this.clearParticipantStatus(memberId);
                return;
            }

            await this.updateParticipantStatus(memberId, 'excused');
        },

        async markFormHandedOver(member) {
            try {
                const memberData = {
                    id: member.id,
                    firstname: member.firstName,
                    lastname: member.lastName,
                    street: member.street,
                    city: member.city,
                    birthdate: member.birthDate,
                    phone: member.phone,
                    email: member.email,
                    gender: member.gender || 'unknown',
                    active: member.active,
                    testMembership: member.testMembership || false,
                    picsInInternetAllowed: member.picsInInternetAllowed || false,
                    memberFormHandedOver: true,
                    ttr: member.ttr,
                    qttr: member.qttr
                };
                
                await apiClient.post(`/clubmembers/set/${this.currentClub}`, memberData);
                // Lokales Member-Objekt aktualisieren
                member.memberFormHandedOver = true;
                this.showInfo(this.$t('messages.success'), this.$t('diary.formMarkedAsHandedOver'), '', 'success');
            } catch (error) {
                console.error('Fehler beim Markieren des Formulars:', error);
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorMarkingForm'), '', 'error');
            }
        },

        async addActivity() {
            const dateId = this.date.id;
            if (this.newActivity) {
                const response = await apiClient.post('/activities/add', {
                    diaryDateId: dateId,
                    description: this.newActivity,
                    tags: this.selectedActivityTags.map(tag => tag.id)
                });
                this.activities.push(response.data[0]);
                this.newActivity = '';
                this.selectedActivityTags = [];
            }
        },

        async selectMember(member) {
            this.selectedMember = member;
            // Öffne das Notizen-Modal für den ausgewählten Teilnehmer
            await this.openNotesModal(member);
        },

        async openNotesModal(member) {
            this.noteMember = member;
            this.loadMemberNotesAndTags(this.date.id, member.id);
            this.showNotesModal = true;
        },
        openOrdersDialog(member) {
            this.selectedMemberForOrders = member;
            this.showMemberOrdersDialog = true;
        },
        closeOrdersDialog() {
            this.showMemberOrdersDialog = false;
            this.selectedMemberForOrders = null;
        },

        async loadMemberNotesAndTags(diaryDateId, memberId) {
            this.doMemberTagUpdates = false;
            try {
                const notesResponse = await apiClient.get(`/diarymember/${this.currentClub}/note`, {
                    params: { diaryDateId, memberId }
                });
                this.notes = notesResponse.data;
                const tagsResponse = await apiClient.get(`/diarymember/${this.currentClub}/tag`, {
                    params: { diaryDateId, memberId }
                });
                this.selectedMemberTags = tagsResponse.data.map(tag => ({
                    id: tag.tag.id,
                    label: tag.tag.label
                }));
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
            this.doMemberTagUpdates = true;
        },

        async addMemberNote() {
            if (this.newNoteContent && this.selectedMember) {
                const response = await apiClient.post(`/diarymember/${this.currentClub}/note`, {
                    memberId: this.selectedMember.id,
                    diaryDateId: this.date.id,
                    content: this.newNoteContent
                });
                this.notes = response.data;
                this.newNoteContent = '';
                this.selectedTagsNotes = [];
            } else {
                this.showInfo(this.$t('messages.note'), this.$t('diary.selectParticipantAndNote'), '', 'warning');
            }
        },

        async deleteNote(noteId) {
            const response = await apiClient.delete(`/diarymember/${this.currentClub}/note/${noteId}`, {
                clubId: this.currentClub
            });
            this.notes = response.data;
        },

        closeNotesModal() {
            this.showNotesModal = false;
        },

        async addNewTagFromInput(event) {
            const inputValue = event.target.value.trim();
            if (inputValue) {
                await this.addNewTag(inputValue);
            }
        },

        async addNewTag(newTagName) {
            try {
                const response = await apiClient.post('/tags', { name: newTagName });
                const newTag = response.data[0];
                this.availableTags.push(newTag);
                this.selectedActivityTags.push(newTag);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async addNewTagForMemberFromInput(event) {
            const inputValue = event.target.value.trim();
            if (inputValue) {
                await this.addNewTagForMember(inputValue);
            }
        },

        async addNewTagForMember(newTagName) {
            try {
                const response = await apiClient.post('/tags', { name: newTagName });
                const newTag = response.data;
                this.availableTags.push(newTag);
                this.selectedMemberTags.push(newTag);
                await this.linkTagToMemberAndDate(newTag);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async linkTagToDiaryDate(tag) {
            if (!tag || !tag.id) {
                return;
            }
            try {
                const tagId = tag.id;
                const response = await apiClient.post(`/diary/tag/${this.currentClub}/add-tag`, {
                    diaryDateId: this.date.id,
                    tagId: tagId
                });
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async linkTagToMemberAndDate(tag) {
            try {
                const tagId = tag.id;
                await apiClient.post(`/diarymember/${this.currentClub}/tag`, {
                    diaryDateId: this.date.id,
                    memberId: this.selectedMember.id,
                    tagId: tagId
                });
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async updateActivityTags() {
            try {
                const selectedTags = this.selectedActivityTags;
                if (!Array.isArray(selectedTags)) {
                    throw new TypeError('Expected selectedTags to be an array');
                }
                for (let tag of selectedTags) {
                    if (tag && tag.id && !this.previousActivityTags.some(prevTag => prevTag.id === tag.id)) {
                        await this.linkTagToDiaryDate(tag);
                    }
                }
                this.previousActivityTags = [...selectedTags];
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async updateMemberTags() {
            if (!this.doMemberTagUpdates || !this.selectedMember) {
                return;
            }
            try {
                for (let tag of this.selectedMemberTags) {
                    if (!this.previousMemberTags.includes(tag)) {
                        await this.linkTagToMemberAndDate(tag);
                    }
                }
                this.previousMemberTags = [...this.selectedMemberTags];
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async removeMemberTag(tagId) {
            try {
                await apiClient.post(`/diarymember/${this.currentClub}/tag/remove`, {
                    diaryDateId: this.date.id,
                    memberId: this.selectedMember.id,
                    tagId: tagId
                });
                this.selectedMemberTags = this.selectedMemberTags.filter(tag => tag.id !== tagId);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async removeMemberNote(noteContent) {
            try {
                await apiClient.post(`/diarymember/${this.currentClub}/note/remove`, {
                    diaryDateId: this.date.id,
                    memberId: this.selectedMember.id,
                    content: noteContent
                });
                this.notes = this.notes.filter(note => note.content !== noteContent);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async removeActivityTag(tag) {
            try {
                const tagId = tag.id;
                await apiClient.delete(`/diary/${this.currentClub}/tag`, {
                    params: { tagId }
                });
                this.selectedActivityTags = this.selectedActivityTags.filter(t => t.id !== tagId);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async handleActivityTagInput(tags) {
            const newTags = tags.filter(tag => !this.previousActivityTags.some(prevTag => prevTag.id === tag.id));
            for (const tag of newTags) {
                await this.linkTagToDiaryDate(tag);
            }
            this.previousActivityTags = [...tags];
        },

        selectPredefinedActivity(activity) {
            this.newPlanItem.activity = activity.name;
            this.newPlanItem.durationText = activity.durationText;
            this.newPlanItem.duration = activity.duration || '';
            this.newPlanItem.predefinedActivityId = activity.id || null;
            this.showDropdown = false;
        },

        async ensureStandardDiaryActivity(definition) {
            const existing = this.predefinedActivities.find((activity) => activity.name === definition.name);

            if (existing) {
                if (existing.excludeFromStats) {
                    return existing;
                }

                await apiClient.put(`/predefined-activities/${existing.id}`, {
                    name: existing.name,
                    code: existing.code,
                    description: existing.description,
                    durationText: existing.durationText,
                    duration: existing.duration,
                    imageLink: existing.imageLink,
                    drawingData: existing.drawingData,
                    excludeFromStats: true,
                });
                await this.loadPredefinedActivities();
                await this.loadStandardPredefinedActivities();
                return this.predefinedActivities.find((activity) => activity.name === definition.name) || existing;
            }

            const created = await apiClient.post('/predefined-activities', {
                name: definition.name,
                code: definition.code || null,
                description: definition.description || '',
                durationText: definition.durationText || '',
                duration: definition.duration || null,
                excludeFromStats: true,
            }).then((response) => response.data);
            await this.loadPredefinedActivities();
            await this.loadStandardPredefinedActivities();
            return created;
        },

        async addStandardPlanActivity(activity) {
            try {
                const standardActivity = await this.ensureStandardDiaryActivity(activity);
                this.newPlanItem.activity = standardActivity.name;
                this.newPlanItem.durationText = standardActivity.durationText || (standardActivity.duration ? String(standardActivity.duration) : '');
                this.newPlanItem.duration = standardActivity.duration || '';
                this.newPlanItem.predefinedActivityId = standardActivity.id || null;
                await this.addPlanItem();
            } catch (error) {
                const msg = getSafeErrorMessage(error, this.$t('diary.standardActivityAddError'));
                this.showInfo(this.$t('messages.error'), msg, '', 'error');
            }
        },

        async addPlanItem() {
            try {
                if (this.addNewItem || this.addNewTimeblock) {
                    // Sicherstellen, dass das ausgewählte Datum existiert
                    const list = await apiClient.get(`/diary/${this.currentClub}`).then(r => r.data);
                    if (!list.some(e => String(e.id) === String(this.date?.id))) {
                        await this.refreshDates();
                        this.showInfo(this.$t('messages.note'), this.$t('diary.dateNoLongerCurrent'), '', 'warning');
                        return;
                    }
                    if (!this.addNewTimeblock && (this.groups || []).length > 0) {
                        const selectedGroupId = this.planGroupFilter !== '__all__'
                            ? Number(this.planGroupFilter)
                            : null;
                        await apiClient.post(`/diary-date-activities/${this.currentClub}`, {
                            diaryDateId: this.date.id,
                            activity: this.newPlanItem.activity,
                            predefinedActivityId: this.newPlanItem.predefinedActivityId,
                            isTimeblock: false,
                            duration: this.newPlanItem.duration,
                            durationText: this.newPlanItem.durationText,
                            groupId: Number.isFinite(selectedGroupId) ? selectedGroupId : null,
                            orderId: this.trainingPlan.length
                        });
                    } else {
                        await apiClient.post(`/diary-date-activities/${this.currentClub}`, {
                            diaryDateId: this.date.id,
                            activity: this.addNewTimeblock ? '' : this.newPlanItem.activity,
                            predefinedActivityId: this.newPlanItem.predefinedActivityId,
                            isTimeblock: this.addNewTimeblock,
                            duration: this.newPlanItem.duration,
                            durationText: this.newPlanItem.durationText,
                            orderId: this.trainingPlan.length
                        });
                    }
                } else if (this.addNewGroupActivity) {
                    if (!this.newPlanItem.groupId || !this.newPlanItem.activity) {
                        this.showInfo(this.$t('messages.note'), this.$t('diary.selectGroupAndActivity'), '', 'warning');
                        return;
                    }
                    await apiClient.post(`/diary-date-activities/group`, {
                        clubId: this.currentClub,
                        diaryDateId: this.date.id,
                        activity: this.newPlanItem.activity,
                        predefinedActivityId: this.newPlanItem.predefinedActivityId,
                        groupId: Number(this.newPlanItem.groupId),
                        timeblockId: this.selectedTimeblockId,
                        duration: this.newPlanItem.duration || null,
                        durationText: this.newPlanItem.durationText || null
                    });
                }
                this.addNewTimeblock = false;
                this.addNewItem = false;
                this.addNewGroupActivity = false;
                this.selectedTimeblockId = null;
                this.newPlanItem = { activity: '', duration: '', durationText: '', groupId: '', predefinedActivityId: null };
                this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
                this.calculateIntermediateTimes();
            } catch (error) {
                const rawMsg = error?.response?.data?.error || '';
                const msg = getSafeErrorMessage(error, 'Ein Fehler ist aufgetreten.');
                if (rawMsg.toLowerCase().includes('foreign key') || rawMsg.toLowerCase().includes('constraint')) {
                    await this.refreshDates();
                    this.showInfo('Hinweis', 'Datum war nicht (mehr) vorhanden. Die Datums-Auswahl wurde aktualisiert. Bitte erneut versuchen.', '', 'warning');
                } else {
                    this.showInfo('Fehler', msg, '', 'error');
                }
            }
        },

        async deleteCurrentDate() {
            if (!this.canDeleteCurrentDate) {
                this.showInfo(this.$t('messages.note'), this.$t('diary.dateCannotBeDeleted'), this.$t('diary.dateCannotBeDeletedDetails'), 'warning');
                return;
            }
            const confirmed = await this.showConfirm(this.$t('diary.confirmDelete'), this.$t('diary.confirmDeleteDate'), this.$t('diary.confirmDeleteDateDetails'), 'danger');
            if (!confirmed) return;
            try {
                await apiClient.delete(`/diary/${this.currentClub}/${this.date.id}`);
                await this.refreshDates();
                this.date = null;
                this.trainingStart = '';
                this.trainingEnd = '';
                this.participants = [];
                this.trainingPlan = [];
            } catch (e) {
                const msg = getSafeErrorMessage(e, 'Fehler beim Löschen.');
                this.showInfo('Fehler', msg, '', 'error');
            }
        },

        async updatePlanItemGroup(planItemId, groupId) {
            try {
                await apiClient.put(`/diary-date-activities/${this.currentClub}/${planItemId}/group`, {
                    groupId: groupId
                });
                this.calculateIntermediateTimes();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },

        async removePlanItem(planItemId) {
            try {
                await apiClient.delete(`/diary-date-activities/${this.currentClub}/${planItemId}`);
                this.trainingPlan = this.trainingPlan.filter(item => item.id !== planItemId);
                this.calculateIntermediateTimes();
            } catch (e) {
                const msg = getSafeErrorMessage(e, 'Fehler beim Löschen.');
                this.showInfo('Fehler', msg, '', 'error');
            }
        },

        isTimeGreater(time1, time2) {
            const [hours1, minutes1] = time1.split(':').map(Number);
            const [hours2, minutes2] = time2.split(':').map(Number);

            if (hours1 > hours2) return true;
            if (hours1 < hours2) return false;
            return minutes1 > minutes2;
        },
        calculateAllItemTimes() {
            const initialTime = this.trainingStart || '00:00';
            let globalCursor = initialTime;
            const groupCursorMap = new Map();
            const items = Array.isArray(this.trainingPlan) ? this.trainingPlan : [];

            for (const item of items) {
                const hasGroup = Number.isFinite(Number(item?.groupId)) && Number(item.groupId) > 0;
                const duration = Number.isFinite(Number(item?.duration)) ? Number(item.duration) : 0;

                if (!hasGroup) {
                    let maxGroupCursor = globalCursor;
                    for (const cursor of groupCursorMap.values()) {
                        if (this.isTimeGreater(cursor, maxGroupCursor)) {
                            maxGroupCursor = cursor;
                        }
                    }
                    const startTime = this.isTimeGreater(maxGroupCursor, globalCursor) ? maxGroupCursor : globalCursor;
                    item.startTime = startTime;
                    item.endTime = this.addDurationToTime(startTime, duration);
                    globalCursor = item.endTime;
                    for (const [groupId, cursor] of groupCursorMap.entries()) {
                        if (this.isTimeGreater(globalCursor, cursor)) {
                            groupCursorMap.set(groupId, globalCursor);
                        }
                    }
                    continue;
                }

                const groupId = Number(item.groupId);
                if (!groupCursorMap.has(groupId)) {
                    groupCursorMap.set(groupId, globalCursor);
                }
                const groupCursor = groupCursorMap.get(groupId) || globalCursor;
                item.startTime = groupCursor;
                item.endTime = this.addDurationToTime(groupCursor, duration);
                groupCursorMap.set(groupId, item.endTime);
            }
        },

        calculatePlanItemTime(index) {
            this.calculateAllItemTimes();
            return this.trainingPlan[index].startTime;
        },
        addDurationToTime(startTime, duration) {
            let [hours, minutes] = startTime.split(':').map(Number);
            minutes += Number(duration);
            if (minutes >= 60) {
                hours += Math.floor(minutes / 60);
                minutes = minutes % 60;
            }
            hours = hours % 24;
            return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
        },
        getGroupActivitiesForGroup(timeblockItem, groupId) {
            const normalizedGroupId = Number(groupId);
            const items = Array.isArray(timeblockItem?.groupActivities) ? timeblockItem.groupActivities : [];
            return items
                .filter((entry) => Number(entry?.groupsGroupActivity?.id) === normalizedGroupId)
                .slice()
                .sort((a, b) => {
                    const orderA = Number.isFinite(Number(a?.orderId)) ? Number(a.orderId) : 0;
                    const orderB = Number.isFinite(Number(b?.orderId)) ? Number(b.orderId) : 0;
                    if (orderA !== orderB) return orderA - orderB;
                    return Number(a?.id || 0) - Number(b?.id || 0);
                });
        },
        calculateGroupActivityStartTime(timeblockItem, groupItem) {
            const baseStart = timeblockItem?.startTime || this.trainingStart;
            if (!baseStart || !groupItem?.groupsGroupActivity?.id) {
                return baseStart || '';
            }
            const orderedGroupItems = this.getGroupActivitiesForGroup(timeblockItem, groupItem.groupsGroupActivity.id);
            let current = baseStart;
            for (const item of orderedGroupItems) {
                if (Number(item?.id) === Number(groupItem?.id)) {
                    return current;
                }
                const dur = Number(item?.duration || 0);
                if (dur > 0) {
                    current = this.addDurationToTime(current, dur);
                }
            }
            return current;
        },
        canMoveGroupActivity(timeblockItem, groupItem, direction) {
            const groupId = groupItem?.groupsGroupActivity?.id;
            if (!groupId) return false;
            const orderedGroupItems = this.getGroupActivitiesForGroup(timeblockItem, groupId);
            const index = orderedGroupItems.findIndex((entry) => Number(entry?.id) === Number(groupItem?.id));
            if (index < 0) return false;
            if (direction === 'up') return index > 0;
            if (direction === 'down') return index < orderedGroupItems.length - 1;
            return false;
        },
        async moveGroupActivity(timeblockItem, groupItem, direction) {
            if (!this.canMoveGroupActivity(timeblockItem, groupItem, direction)) {
                return;
            }
            const groupId = groupItem?.groupsGroupActivity?.id;
            const orderedGroupItems = this.getGroupActivitiesForGroup(timeblockItem, groupId);
            const index = orderedGroupItems.findIndex((entry) => Number(entry?.id) === Number(groupItem?.id));
            const targetIndex = direction === 'up' ? index - 1 : index + 1;
            const targetItem = orderedGroupItems[targetIndex];
            if (!targetItem) return;
            try {
                const currentOrder = Number(groupItem.orderId || index + 1);
                const targetOrder = Number(targetItem.orderId || targetIndex + 1);
                await apiClient.put(`/diary-date-activities/group/${this.currentClub}/${groupItem.id}`, {
                    orderId: targetOrder
                });
                await apiClient.put(`/diary-date-activities/group/${this.currentClub}/${targetItem.id}`, {
                    orderId: currentOrder
                });
                await this.loadTrainingPlan();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        calculateDuration() {
            const input = this.newPlanItem.durationText;
            let calculatedDuration = 0;
            const multiplyPattern = /(\d+)\s*[x*]\s*(\d+)/i;
            const match = input.match(multiplyPattern);
            if (match) {
                const [, num1, num2] = match;
                calculatedDuration = parseInt(num1) * parseInt(num2);
            } else if (!isNaN(input)) {
                calculatedDuration = parseInt(input);
            }
            calculatedDuration = Math.ceil(calculatedDuration / 5) * 5;
            if (!this.newPlanItem.durationText || this.newPlanItem.durationText === input) {
                this.newPlanItem.duration = calculatedDuration;
                this.newPlanItem = { ...this.newPlanItem, duration: calculatedDuration };
            }
        },
        calculateDurationForEdit() {
            const input = this.editingDurationText;
            let calculatedDuration = 0;
            const multiplyPattern = /(\d+)\s*[x*]\s*(\d+)/i;
            const match = input.match(multiplyPattern);
            if (match) {
                const [, num1, num2] = match;
                calculatedDuration = parseInt(num1) * parseInt(num2);
            } else if (!isNaN(input) && input.trim() !== '') {
                calculatedDuration = parseInt(input);
            }
            if (calculatedDuration > 0) {
                calculatedDuration = Math.ceil(calculatedDuration / 5) * 5;
                this.editingDuration = calculatedDuration;
            }
        },
        calculateDurationForEditGroupActivity() {
            const input = this.editingGroupActivityDurationText;
            let calculatedDuration = 0;
            const multiplyPattern = /(\d+)\s*[x*]\s*(\d+)/i;
            const match = String(input || '').match(multiplyPattern);
            if (match) {
                const [, num1, num2] = match;
                calculatedDuration = parseInt(num1, 10) * parseInt(num2, 10);
            } else if (!isNaN(input) && String(input).trim() !== '') {
                calculatedDuration = parseInt(input, 10);
            }
            if (calculatedDuration > 0) {
                calculatedDuration = Math.ceil(calculatedDuration / 5) * 5;
                this.editingGroupActivityDuration = calculatedDuration;
            }
        },
        getPlanDurationDisplay(item) {
            if (!item?.isTimeblock) {
                if (!item) return '';
                return `${item.duration || ''}${item.durationText && item.durationText.trim() !== '' ? ` (${item.durationText})` : ''}`;
            }
            const maxDuration = this.getTimeblockMaxGroupDuration(item);
            if (maxDuration > 0) {
                return `${maxDuration}`;
            }
            return `${item.duration || ''}${item.durationText && item.durationText.trim() !== '' ? ` (${item.durationText})` : ''}`;
        },
        getPlanDurationMinutesDisplay(item) {
            return typeof item?.durationText === 'string' ? item.durationText.trim() : '';
        },
        getTimeblockMaxGroupDuration(timeblockItem) {
            const entries = Array.isArray(timeblockItem?.groupActivities) ? timeblockItem.groupActivities : [];
            if (!entries.length) return 0;
            const totalsByGroup = new Map();
            for (const entry of entries) {
                const groupId = Number(entry?.groupsGroupActivity?.id);
                const duration = Number(entry?.duration || 0);
                if (!Number.isFinite(groupId) || !Number.isFinite(duration) || duration <= 0) continue;
                totalsByGroup.set(groupId, (totalsByGroup.get(groupId) || 0) + duration);
            }
            return Math.max(0, ...Array.from(totalsByGroup.values()));
        },
        async removePlanItem(planItemId) {
            try {
                await apiClient.delete(`/diary-date-activities/${this.currentClub}/${planItemId}`);
                this.trainingPlan = this.trainingPlan.filter(item => item.id !== planItemId);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        async removeGroupActivity(groupActivityId) {
            try {
                await apiClient.delete(`/diary-date-activities/group/${this.currentClub}/${groupActivityId}`);
                // Entferne die GroupActivity aus dem trainingPlan
                for (const item of this.trainingPlan) {
                    if (item.groupActivities) {
                        const index = item.groupActivities.findIndex(ga => ga.id === groupActivityId);
                        if (index !== -1) {
                            item.groupActivities.splice(index, 1);
                            break;
                        }
                    }
                }
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        getOrderedPlanItems() {
            return (Array.isArray(this.trainingPlan) ? this.trainingPlan : [])
                .filter(item => item && !item.isTimeblock)
                .slice()
                .sort((a, b) => {
                    const orderA = Number.isFinite(Number(a?.orderId)) ? Number(a.orderId) : Number.MAX_SAFE_INTEGER;
                    const orderB = Number.isFinite(Number(b?.orderId)) ? Number(b.orderId) : Number.MAX_SAFE_INTEGER;
                    if (orderA !== orderB) return orderA - orderB;
                    return Number(a?.id || 0) - Number(b?.id || 0);
                });
        },
        canMovePlanItem(item, direction) {
            const orderedItems = this.getOrderedPlanItems();
            const index = orderedItems.findIndex(entry => Number(entry?.id) === Number(item?.id));
            if (index < 0) return false;
            if (direction === 'up') return index > 0;
            if (direction === 'down') return index < orderedItems.length - 1;
            return false;
        },
        async movePlanItem(item, direction) {
            if (!this.canMovePlanItem(item, direction)) {
                return;
            }
            const orderedItems = this.getOrderedPlanItems();
            const index = orderedItems.findIndex(entry => Number(entry?.id) === Number(item?.id));
            const targetIndex = direction === 'up' ? index - 1 : index + 1;
            const targetItem = orderedItems[targetIndex];
            if (!targetItem) return;

            const currentOrder = Number.isFinite(Number(item.orderId)) ? Number(item.orderId) : index + 1;
            const targetOrder = Number.isFinite(Number(targetItem.orderId)) ? Number(targetItem.orderId) : targetIndex + 1;

            try {
                await apiClient.put(`/diary-date-activities/${this.currentClub}/${item.id}`, {
                    orderId: targetOrder
                });
                await apiClient.put(`/diary-date-activities/${this.currentClub}/${targetItem.id}`, {
                    orderId: currentOrder
                });
                await this.loadTrainingPlan();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        async onDragEnd(evt) {
            const oldIndex = Number.isInteger(evt.oldDraggableIndex) ? evt.oldDraggableIndex : evt.oldIndex;
            const newIndex = Number.isInteger(evt.newDraggableIndex) ? evt.newDraggableIndex : evt.newIndex;
            const visibleItems = this.filteredTrainingPlan.slice();
            const movedId = evt?.item?.dataset?.planId;
            const movedItem = movedId
                ? this.trainingPlan.find(item => Number(item.id) === Number(movedId))
                : visibleItems[oldIndex];
            if (!movedItem) {
                return;
            }
            const targetItem = visibleItems[newIndex];
            const targetOrder = targetItem && Number(targetItem.id) !== Number(movedItem.id)
                ? Number(targetItem.orderId)
                : newIndex + 1;
            try {
                await apiClient.put(`/diary-date-activities/${this.currentClub}/${movedItem.id}/order`, {
                    orderId: targetOrder
                });
                await this.loadTrainingPlan();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        /*        async loadMemberImage(member) {
                    try {
                        const response = await apiClient.get(`/clubmembers/image/${this.currentClub}/${member.id}`, {
                            responseType: 'blob',
                        });
                        const imageUrl = URL.createObjectURL(response.data);
                        member.imageUrl = imageUrl;
                    } catch (error) {
                        member.imageUrl = null;
                    }
                },*/
        async generatePDF() {
            const pdf = new PDFGenerator(20, 10, this.$t);
            pdf.addTrainingPlan(this.currentClubName, this.date.date, this.trainingStart, this.trainingEnd, this.trainingPlan);
            pdf.save('trainingsplan.pdf');
        },
        async generateTrainingDayPDF() {
            if (!this.date || !this.participants || this.participants.length === 0) {
                this.showInfo('Fehler', 'Keine Teilnehmer für diesen Trainingstag vorhanden.', '', 'error');
                return;
            }

            try {
                // Lade alle Aktivitäts-Mitglieder-Zuordnungen
                await this.loadAllActivityMembers();

                // Filtere Mitglieder: nur die, die auch Teilnehmer sind
                const participantMembers = this.members.filter(m => 
                    m && m.id && this.participants.includes(m.id)
                );

                // Verwende trainingPlan statt activities, da die Aktivitäten dort sind
                // Filtere Zeitblöcke komplett aus, da sie immer mehrere Gruppen umfassen
                const activitiesForPDF = this.trainingPlan.filter(item => !item.isTimeblock);

                // Debug-Ausgaben
                console.log('[generateTrainingDayPDF] participantMembers:', participantMembers.length);
                console.log('[generateTrainingDayPDF] trainingPlan items:', this.trainingPlan.length);
                console.log('[generateTrainingDayPDF] activitiesForPDF:', activitiesForPDF.length);
                console.log('[generateTrainingDayPDF] activityMembersMap keys:', Object.keys(this.activityMembersMap || {}));
                console.log('[generateTrainingDayPDF] groupActivityMembersMap keys:', Object.keys(this.groupActivityMembersMap || {}));
                console.log('[generateTrainingDayPDF] participantMapByMemberId:', this.participantMapByMemberId);

                const pdf = new PDFGenerator(20, 10, this.$t);
                pdf.addTrainingDaySummary(
                    this.currentClubName,
                    this.date.date,
                    this.trainingStart,
                    this.trainingEnd,
                    participantMembers,
                    activitiesForPDF,
                    this.activityMembersMap,
                    this.groupActivityMembersMap,
                    this.participantMapByMemberId,
                    this.groups,
                    this.trainingPlan,
                    this.memberGroupsMap
                );
                
                const dateStr = new Date(this.date.date).toLocaleDateString('de-DE').replace(/\./g, '-');
                pdf.save(`trainingstag-${dateStr}.pdf`);
            } catch (error) {
                console.error('Fehler beim Generieren des Trainingstag-PDFs:', error);
                this.showInfo('Fehler', 'Fehler beim Generieren des PDFs.', error.message || '', 'error');
            }
        },
        async loadAllActivityMembers() {
            // Lade für alle Aktivitäten im trainingPlan die Mitglieder-Zuordnungen
            for (const activity of this.trainingPlan) {
                if (activity && activity.id) {
                    await this.ensureActivityMembersLoaded(activity.id);
                }
                // Lade auch für Gruppenaktivitäten
                if (activity && activity.groupActivities) {
                    for (const groupActivity of activity.groupActivities) {
                        if (groupActivity && groupActivity.id) {
                            await this.ensureGroupActivityMembersLoaded(groupActivity.id);
                        }
                    }
                }
            }
        },
        sortedMembers() {
            // Erstelle eine Kopie des Arrays, um Mutation zu vermeiden
            // Sortierung: zuerst nach Vorname, dann nach Nachname (beides case-insensitive, deutsch)
            // Fallback: ID, damit die Reihenfolge bei komplett gleichen Namen stabil ist
            const locale = 'de-DE';
            const options = { sensitivity: 'base' };

            const safe = (value) => (value ?? '').toString().trim();

            return [...this.members].sort((a, b) => {
                const firstNameA = safe(a.firstName);
                const firstNameB = safe(b.firstName);
                const firstNameComparison = firstNameA.localeCompare(firstNameB, locale, options);

                if (firstNameComparison !== 0) {
                    return firstNameComparison;
                }

                const lastNameA = safe(a.lastName);
                const lastNameB = safe(b.lastName);
                const lastNameComparison = lastNameA.localeCompare(lastNameB, locale, options);

                if (lastNameComparison !== 0) {
                    return lastNameComparison;
                }

                // Stabiler Fallback, falls sowohl Vor- als auch Nachname identisch sind
                const idA = Number.isFinite(a.id) ? a.id : parseInt(a.id, 10) || 0;
                const idB = Number.isFinite(b.id) ? b.id : parseInt(b.id, 10) || 0;
                return idA - idB;
            });
        },
        async showPic(member) {
            this.loadMemberImage(member);
            this.showImage = true;
        },
        closeImage() {
            this.showImage = false;
            this.showRenderModal = false;
            this.renderModalData = null;
            // Revoke blob URL wenn vorhanden
            if (this.imageUrl && this.imageUrl.startsWith('blob:')) {
                URL.revokeObjectURL(this.imageUrl);
            }
            this.imageUrl = '';
        },

        async showActivityImage(imageLink) {
            try {
                // Vorherige Object-URL freigeben
                if (this.imageUrl && this.imageUrl.startsWith('blob:')) {
                    URL.revokeObjectURL(this.imageUrl);
                }

                if (imageLink && imageLink.startsWith('/api/')) {
                    // Über API mit Auth und als Blob laden → vermeidet ORB
                    const path = imageLink.replace(/^\/api\//, '');
                    const resp = await apiClient.get(`/${path}`, { responseType: 'blob' });
                    this.imageUrl = URL.createObjectURL(resp.data);
                } else {
                    this.imageUrl = imageLink;
                }
                this.showImage = true;
            } catch (e) {
                console.error('Bild laden fehlgeschlagen:', e);
                this.showInfo('Fehler', 'Bild konnte nicht geladen werden.', '', 'error');
            }
        },
        async openActivityVisual(pa) {
            // Bevorzugt Rendering, ansonsten Bild
            const data = this.drawingDataFor(pa);
            if (data) {
                // Erzeuge temporär ein PNG im Client: Canvas offscreen rendern über Renderer-Komponente ist aufwändig.
                // Einfacher: öffne ein kleines Modal mit der Renderer-Komponente statt imageUrl.
                this.renderModalData = data;
                this.showRenderModal = true;
            } else if (pa.imageLink) {
                await this.showActivityImage(pa.imageLink);
            }
        },
        async loadMemberImage(member) {
            try {
                const response = await apiClient.get(`/clubmembers/image/${this.currentClub}/${member.id}`, {
                    responseType: 'blob',
                });
                this.imageUrl = URL.createObjectURL(response.data);
                this.showImage = true;
            } catch (error) {
                this.imageUrl = null;
            }
        },
        recalculateTimes() {
            let currentTime = this.trainingStart;
            this.trainingPlan.forEach((item, index) => {
                item.startTime = currentTime;
                currentTime = this.addDurationToTime(currentTime, item.duration);
            });
        },
        async createGroups() {
            try {
                // Validierung: Wenn keine Gruppen existieren, müssen mindestens 2 erstellt werden
                if (this.groups.length === 0 && this.newGroupCount < 2) {
                    this.showInfo(this.$t('messages.error'), this.$t('diary.mustCreateAtLeastTwoGroups'), '', 'error');
                    this.newGroupCount = 2;
                    return;
                }

                // Bestimme Startnummer basierend auf vorhandenen Gruppen
                const existingNumbers = (this.groups || [])
                    .map(g => parseInt((g.name || '').trim(), 10))
                    .filter(n => Number.isFinite(n));
                const startNumber = existingNumbers.length > 0 ? Math.max(...existingNumbers) + 1 : 1;

                // Erstelle die gewünschte Anzahl Gruppen mit fortlaufender Nummerierung
                for (let i = 0; i < this.newGroupCount; i++) {
                    const groupNumber = startNumber + i;
                    const form = {
                        clubid: this.currentClub,
                        dateid: this.date.id,
                        name: groupNumber.toString(),
                        lead: '', // Leiter wird leer gelassen
                    }
                    await apiClient.post('/group', form);
                }
                const countCreated = this.newGroupCount;
                await this.loadGroups();
                // Setze newGroupCount zurück: 1 wenn bereits Gruppen existieren, 2 wenn keine
                this.newGroupCount = this.groups.length > 0 ? 1 : 2;
                const message = countCreated === 1 
                    ? this.$t('diary.oneGroupAdded')
                    : this.$t('diary.groupsCreated', { count: countCreated });
                this.showInfo(this.$t('messages.success'), message, '', 'success');
            } catch (error) {
                console.error('Fehler beim Erstellen der Gruppen:', error);
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorCreatingGroups'), '', 'error');
            }
        },
        parentIsTimeblock() {
            return this.trainingPlan && this.trainingPlan.length > 0 ? (this.trainingPlan[this.trainingPlan.length - 1].isTimeblock) : false;
        },
        openNewPlanItem() {
            this.addNewItem = true;
            this.addNewGroupActivity = false;
            this.addNewTimeblock = false;
        },
        cancelAddItem() {
            this.addNewItem = false;
            this.addNewGroupActivity = false;
            this.addNewTimeblock = false;
            this.selectedTimeblockId = null;
        },
        addTimeblock() {
            this.addNewTimeblock = true;
            this.addNewGroupActivity = false;
            this.addNewItem = false;
        },
        async addGroupActivity() {
            this.addNewGroupActivity = true;
            this.addNewItem = false;
            this.addNewTimeblock = false;
            this.selectedTimeblockId = null; // Verwende den letzten Zeitblock
            if (this.planGroupFilter !== '__all__') {
                this.newPlanItem.groupId = String(this.planGroupFilter);
            }
        },
        addGroupActivityToTimeblock(timeblockId) {
            this.addNewGroupActivity = true;
            this.addNewItem = false;
            this.addNewTimeblock = false;
            this.selectedTimeblockId = timeblockId;
            if (this.planGroupFilter !== '__all__') {
                this.newPlanItem.groupId = String(this.planGroupFilter);
            }
        },
        getFormattedDate(date) {
            return (new Date(date)).toLocaleDateString('de-DE', { year: 'numeric', month: '2-digit', day: '2-digit' });
        },
        formatDisplayTime(timeValue) {
            if (!timeValue) return '';
            const value = String(timeValue);
            return value.length >= 5 ? value.slice(0, 5) : value;
        },
        getPlanItemDisplayLabel(item) {
            if (!item) return '';
            const predefined = item.predefinedActivity || item.groupPredefinedActivity;
            if (predefined?.code && predefined.code.trim() !== '') {
                return predefined.code;
            }
            if (predefined?.name) {
                return predefined.name;
            }
            return item.activity || '';
        },
        editGroup(groupId) {
            this.editingGroupId = groupId;
        },
        updateGroupField({ groupId, field, value }) {
            this.groups = this.groups.map(group =>
                Number(group.id) === Number(groupId)
                    ? { ...group, [field]: value }
                    : group
            );
        },
        async saveGroup(group) {
            try {
                await apiClient.put(`/group/${group.id}`, {
                    name: group.name,
                    lead: group.lead,
                    clubid: this.currentClub,
                    dateid: this.date.id,
                });
                this.editingGroupId = null;
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorOccurred'), '', 'error');
            }
        },
        cancelEditGroup() {
            this.editingGroupId = null;
        },
        async deleteGroup(groupId) {
            try {
                const group = this.groups.find(g => g.id === groupId);
                if (!group) {
                    return;
                }
                
                const confirmed = confirm(this.$t('diary.confirmDeleteGroup', { name: group.name }));
                if (!confirmed) {
                    return;
                }
                
                await apiClient.delete(`/group/${groupId}`, {
                    data: {
                        clubid: this.currentClub,
                        dateid: this.date.id
                    }
                });
                
                await this.loadGroups();
                this.showInfo(this.$t('messages.success'), this.$t('diary.groupDeletedSuccessfully'), '', 'success');
            } catch (error) {
                console.error(this.$t('diary.errorDeletingGroup'), error);
                this.showInfo(this.$t('messages.error'), this.$t('diary.errorDeletingGroup'), '', 'error');
            }
        },
        async openTagInfos(member) {
            if (!member) {
                return;
            }
            this.showActivityStatsModal = true;
            this.activityStatsMember = member;
            
            try {
                // Lade letzte 3 Teilnahmen
                const lastParticipationsResponse = await apiClient.get(`/member-activities/${this.currentClub}/${member.id}/last-participations?limit=3`);
                this.lastParticipations = lastParticipationsResponse.data || [];
                
                // Lade Statistik der Übungen
                const statsResponse = await apiClient.get(`/member-activities/${this.currentClub}/${member.id}?period=all`);
                this.activityStats = statsResponse.data || [];
            } catch (error) {
                console.error('Error loading activity stats:', error);
                this.showInfo('Fehler', 'Fehler beim Laden der Statistiken.', '', 'error');
                this.lastParticipations = [];
                this.activityStats = [];
            }
        },
        closeTagHistoryModal() {
            this.showTagHistoryModal = false;
            this.tagHistoryMember = null;
        },
        closeActivityStatsModal() {
            this.showActivityStatsModal = false;
            this.activityStatsMember = null;
            this.lastParticipations = [];
            this.activityStats = [];
        },
        async addNewTagForDay(tag) {
            await apiClient.post(`/diarydatetags/${this.currentClub}`, {
                dateId: this.date.id,
                memberId: this.tagHistoryMember.id,
                tag: tag,
            });
        },
        async removeDayTag(tag) {
        },
        async addNewDayTagFromInput(event) {
            const tag = event.target.value;
            if (tag) {
                await this.addNewTagForDay(tag);
            }
        },

        startCheckingTime() {
            if (this.timeChecker) clearInterval(this.timeChecker);
            this.playedActivityMarks = [];
            this.timeChecker = setInterval(() => {
                const now = new Date();
                const currentTime = now.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
                const currentHHMM = currentTime.slice(0, 5);
                if (!this.trainingStart) {
                    return;
                }

                const bellTimes = [this.trainingStart, this.trainingEnd].filter(Boolean);
                for (const bellTime of bellTimes) {
                    const key = `bell:${bellTime}`;
                    if (currentHHMM === bellTime && !this.playedActivityMarks.includes(key)) {
                        this.playBellSound();
                        this.playedActivityMarks.push(key);
                    }
                }

                try { this.calculateAllItemTimes(); } catch (e) { }
                const items = Array.isArray(this.trainingPlan) ? this.trainingPlan : [];
                const startTimes = items
                    .map(it => (it && it.startTime ? it.startTime.slice(0, 5) : null))
                    .filter(Boolean);

                for (const startTime of startTimes) {
                    if (startTime === this.trainingStart) continue;
                    const key = `thumb:${startTime}`;
                    if (currentHHMM === startTime && !this.playedActivityMarks.includes(key)) {
                        this.playThumbSound();
                        this.playedActivityMarks.push(key);
                    }
                }
            }, 1000);
        },

        playBellSound() {
            if (!this.soundEnabled) return;
            try {
                if (this.bellSound) {
                    this.bellSound.pause();
                    this.bellSound.currentTime = 0;
                    this.bellSound.play();
                }
            } catch (e) {
                // ignore
            }
        },

        playThumbSound() {
            if (!this.soundEnabled) return;
            try {
                if (this.thumbSound) {
                    this.thumbSound.pause();
                    this.thumbSound.currentTime = 0;
                    this.thumbSound.play();
                }
            } catch (e) {
                // ignore
            }
        },

        calculateIntermediateTimes() {
            // Stelle sicher, dass alle startTime-Werte aktuell sind
            try { this.calculateAllItemTimes(); } catch (e) { }
            if (!this.trainingPlan || this.trainingPlan.length === 0) {
                this.intermediateTimes = [];
                return;
            }
            function withSeconds(hhmm) {
                if (!hhmm) return null;
                const parts = hhmm.split(':');
                if (parts.length < 3) return hhmm + ':00';
                return hhmm;
            }
            const times = [];
            for (const item of this.trainingPlan) {
                if (item && item.startTime) {
                    const t = withSeconds(item.startTime);
                    if (t) times.push(t);
                }
            }
            const normalizedStart = withSeconds(this.trainingStart);
            const unique = Array.from(new Set(times));
            const filtered = unique.filter(t => t !== normalizedStart);
            filtered.sort();
            this.intermediateTimes = filtered;

        },

        async addAccident() {
            this.accidents = [];
            this.showAccidentForm = !this.showAccidentForm;
            await this.getAccidents();
        },

        async saveAccident() {
            const accident = this.accident;
            accident['clubId'] = this.currentClub;
            accident['diaryDateId'] = this.date.id;
            const response = await apiClient.post('/accident', this.accident);
            this.getAccidents();
        },

        async getAccidents() {
            const response = await apiClient.get(`/accident/${this.currentClub}/${this.date.id}`);
            this.accidents = response.data;
        },

        closeAccidentForm() {
            this.showAccidentForm = false;
        },

        startActivityEdit(item) {
            this.editingActivityId = item.id;
            this.$nextTick(() => {
                if (this.$refs.activityInput && this.$refs.activityInput[0]) {
                    this.$refs.activityInput[0].focus();
                } else if (this.$refs.activityInput) {
                    this.$refs.activityInput.focus();
                }
            });
            this.editingActivityText = item.predefinedActivity ? item.predefinedActivity.name : item.activity || '';
            this.editingDuration = item.duration || null;
            this.editingDurationText = item.durationText || '';
        },

        async saveActivityEdit(item) {
            try {
                await apiClient.put(`/diary-date-activities/${this.currentClub}/${item.id}`, {
                    customActivityName: this.editingActivityText,
                    duration: this.editingDuration || null,
                    durationText: this.editingDurationText || null,
                    groupId: item.groupId,
                });

                // Lade die Daten neu, um die Änderungen anzuzeigen
                await this.loadTrainingPlan();

                this.editingActivityId = null;
                this.editingActivityText = '';
                this.editingDuration = null;
                this.editingDurationText = '';
            } catch (error) {
                const msg = getSafeErrorMessage(error, 'Fehler beim Erstellen der Aktivität');
                this.showInfo('Fehler', msg, '', 'error');
            }
        },

        async searchPredefinedActivities(term) {
            if (!term || term.trim().length < 2) {
                return [];
            }
            try {
                const r = await apiClient.get('/predefined-activities/search/query', { params: { q: term, limit: 10 } });
                return r.data || [];
            } catch (e) {
                return [];
            }
        },

        async onEditInputChangeText(item) {
            const term = this.editingActivityText;
            this.editSearchForId = item.id;
            if (!term || term.trim().length < 2) {
                this.editShowDropdown = false;
                this.editSearchResults = [];
                return;
            }
            const results = await this.searchPredefinedActivities(term);
            this.editSearchResults = results;
            this.editShowDropdown = results.length > 0;
        },

        chooseEditSuggestion(s, item) {
            this.editingActivityText = (s.code && s.code.trim() !== '') ? s.code : s.name;
            this.editShowDropdown = false;
            this.editSearchResults = [];
        },

        async onNewItemInputChange() {
            const term = this.newPlanItem.activity;
            if (!term || term.trim().length < 2) {
                this.newItemShowDropdown = false;
                this.newItemSearchResults = [];
                return;
            }
            const results = await this.searchPredefinedActivities(term);
            this.newItemSearchResults = results;
            this.newItemShowDropdown = results.length > 0;
        },

        chooseNewItemSuggestion(s) {
            this.newPlanItem.activity = (s.code && s.code.trim() !== '') ? s.code : s.name;
            this.newPlanItem.durationText = s.durationText || '';
            this.newPlanItem.duration = s.duration || '';
            this.newPlanItem.predefinedActivityId = s.id || null;
            this.newItemShowDropdown = false;
            this.newItemSearchResults = [];
        },

        async handleDrawingDialogOkForDiary(result) {
            if (!result || !result.code) {
                this.showInfo('Fehler', 'Keine Übungsdaten erhalten', '', 'error');
                this.editingGroupActivity = null;
                return;
            }

            try {
                const code = result.code.trim();
                
                // Wenn eine Gruppenaktivität oder normale Aktivität bearbeitet wird
                if (this.editingGroupActivity && this.editingGroupActivity.groupPredefinedActivity) {
                    const predefinedActivityId = this.editingGroupActivity.groupPredefinedActivity.id;
                    
                    let finalPredefinedActivityId = predefinedActivityId;
                    
                    // Wenn keine predefinedActivityId vorhanden ist, erstelle eine neue
                    if (!predefinedActivityId) {
                        const newActivityData = {
                            name: result.name || (result.fields && result.fields.name) || this.editingGroupActivity.groupPredefinedActivity.name || '',
                            code: code,
                            description: result.description || (result.fields && result.fields.description) || this.editingGroupActivity.groupPredefinedActivity.description || '',
                            durationText: (result.fields && result.fields.durationText) || this.editingGroupActivity.groupPredefinedActivity.durationText || '',
                            duration: (result.fields && result.fields.duration) || this.editingGroupActivity.groupPredefinedActivity.duration || null,
                            drawingData: result.drawingData || null
                        };
                        
                        const createResponse = await apiClient.post('/predefined-activities', newActivityData);
                        finalPredefinedActivityId = createResponse.data.id;
                        
                        // Wenn es eine normale Aktivität war, verknüpfe die DiaryDateActivity mit der neuen PredefinedActivity
                        if (this.editingGroupActivity.isNormalActivity && this.editingGroupActivity.activityItem) {
                            const activityItem = this.editingGroupActivity.activityItem;
                            if (activityItem.id && this.currentClub) {
                                // currentClub ist die Club-ID (Zahl), nicht ein Objekt
                                await apiClient.put(`/diary-date-activities/${this.currentClub}/${activityItem.id}`, {
                                    predefinedActivityId: finalPredefinedActivityId
                                });
                            }
                        }
                    } else {
                        // Aktualisiere die existierende PredefinedActivity
                        const updateData = {
                            name: result.name || (result.fields && result.fields.name) || this.editingGroupActivity.groupPredefinedActivity.name || '',
                            code: code,
                            description: result.description || (result.fields && result.fields.description) || this.editingGroupActivity.groupPredefinedActivity.description || '',
                            durationText: (result.fields && result.fields.durationText) || this.editingGroupActivity.groupPredefinedActivity.durationText || '',
                            duration: (result.fields && result.fields.duration) || this.editingGroupActivity.groupPredefinedActivity.duration || null,
                            imageLink: this.editingGroupActivity.groupPredefinedActivity.imageLink || '',
                            drawingData: result.drawingData || null
                        };
                        
                        await apiClient.put(`/predefined-activities/${predefinedActivityId}`, updateData);
                    }
                    
                    // Lade den Trainingsplan neu
                    if (this.date && this.date.id) {
                        await this.loadTrainingPlan();
                    }
                    
                    // Wenn es eine normale Aktivität war, beende auch den Inline-Edit-Modus
                    if (this.editingGroupActivity.isNormalActivity && this.editingGroupActivity.activityItem) {
                        this.editingActivityId = null;
                        this.editingActivityText = '';
                    }
                    
                    this.editingGroupActivity = null;
                    return;
                }
                
                // Suche nach existierender Aktivität mit diesem Code
                const searchResults = await this.searchPredefinedActivities(code);
                const existing = searchResults.find(a => a.code && a.code.trim().toLowerCase() === code.toLowerCase());

                let activityToUse;
                
                if (existing) {
                    // Aktivität existiert bereits - aktualisiere drawingData falls vorhanden
                    if (result.drawingData) {
                        // Lade die vollständige Aktivität, um alle Felder zu behalten
                        const fullActivity = await apiClient.get(`/predefined-activities/${existing.id}`).then(r => r.data);
                        
                        // Aktualisiere die Aktivität mit drawingData
                        const updateData = {
                            name: fullActivity.name || result.name || (result.fields && result.fields.name) || '',
                            code: fullActivity.code || code,
                            description: fullActivity.description || result.description || (result.fields && result.fields.description) || '',
                            durationText: fullActivity.durationText || '',
                            duration: fullActivity.duration || null,
                            imageLink: fullActivity.imageLink || '',
                            drawingData: result.drawingData
                        };
                        
                        const updateResponse = await apiClient.put(`/predefined-activities/${existing.id}`, updateData);
                        activityToUse = updateResponse.data;
                    } else {
                        // Kein drawingData - verwende die existierende Aktivität
                        activityToUse = existing;
                    }
                } else {
                    // Erstelle neue PredefinedActivity
                    const newActivity = {
                        name: result.name || (result.fields && result.fields.name) || '',
                        code: code,
                        description: result.description || (result.fields && result.fields.description) || '',
                        durationText: (result.fields && result.fields.durationText) || '',
                        duration: (result.fields && result.fields.duration) || null,
                        drawingData: result.drawingData || null
                    };
                    
                    const response = await apiClient.post('/predefined-activities', newActivity);
                    activityToUse = response.data;
                }

                // Setze die Aktivität im Formular
                this.chooseNewItemSuggestion(activityToUse);
                if (result.fields && result.fields.duration !== undefined && result.fields.duration !== null && result.fields.duration !== '') {
                    this.newPlanItem.duration = result.fields.duration;
                }
                if (result.fields && typeof result.fields.durationText === 'string') {
                    this.newPlanItem.durationText = result.fields.durationText;
                }
                if (this.addNewGroupActivity && result.fields && result.fields.groupId) {
                    this.newPlanItem.groupId = String(result.fields.groupId);
                }
                
                // Erstelle automatisch den Plan-Eintrag
                await this.addPlanItem();
                
                // Lade den Trainingsplan neu, damit das Icon sofort angezeigt wird
                if (this.date && this.date.id) {
                    await this.loadTrainingPlan();
                }
                
            } catch (error) {
                const msg = getSafeErrorMessage(error, 'Fehler beim Erstellen der Aktivität');
                this.showInfo('Fehler', msg, '', 'error');
            } finally {
                this.editingGroupActivity = null;
            }
        },
        
        editActivity(item) {
            if (!item) {
                this.showInfo('Fehler', 'Keine Aktivität zum Bearbeiten gefunden', '', 'error');
                return;
            }
            
            // Wenn keine predefinedActivity vorhanden ist, aber drawingData, erstelle eine temporäre Struktur
            let predefinedActivity = item.predefinedActivity;
            if (!predefinedActivity && item.drawingData) {
                // Erstelle eine temporäre Struktur für die Bearbeitung
                predefinedActivity = {
                    id: null,
                    name: item.activity || '',
                    code: item.activity || '',
                    description: '',
                    drawingData: item.drawingData
                };
            }
            
            if (!predefinedActivity) {
                this.showInfo('Fehler', 'Keine Aktivität zum Bearbeiten gefunden', '', 'error');
                return;
            }
            
            // Verwende editingGroupActivity auch für normale Aktivitäten, da die Struktur ähnlich ist
            this.editingGroupActivity = { 
                groupPredefinedActivity: predefinedActivity,
                isNormalActivity: true,
                activityItem: item
            };
            this.showDrawingDialog = true;
        },
        
        editGroupActivity(groupItem) {
            if (!groupItem || !groupItem.groupPredefinedActivity) {
                this.showInfo('Fehler', 'Keine Aktivität zum Bearbeiten gefunden', '', 'error');
                return;
            }
            this.editingGroupActivity = groupItem;
            this.showDrawingDialog = true;
        },
        
        startGroupActivityEdit(groupItem) {
            console.log('[startGroupActivityEdit] groupItem.id:', groupItem.id, 'type:', typeof groupItem.id);
            this.editingGroupActivityId = Number(groupItem.id);
            this.editSearchForId = Number(groupItem.id);
            console.log('[startGroupActivityEdit] editingGroupActivityId set to:', this.editingGroupActivityId);
            this.$nextTick(() => {
                const inputs = this.$el.querySelectorAll('input[type="text"]');
                const lastInput = inputs[inputs.length - 1];
                if (lastInput) {
                    lastInput.focus();
                }
            });
            this.editingGroupActivityText = groupItem.groupPredefinedActivity 
                ? (groupItem.groupPredefinedActivity.code && groupItem.groupPredefinedActivity.code.trim() !== '' 
                    ? groupItem.groupPredefinedActivity.code 
                    : groupItem.groupPredefinedActivity.name)
                : '';
            this.editingGroupActivityDuration = groupItem.duration ?? null;
            this.editingGroupActivityDurationText = groupItem.durationText || '';
            this.editingGroupActivityGroupId = groupItem?.groupsGroupActivity?.id ? String(groupItem.groupsGroupActivity.id) : '';
        },
        
        async onEditGroupActivityInputChange(groupItem) {
            const term = this.editingGroupActivityText;
            this.editSearchForId = groupItem.id;
            if (!term || term.trim().length < 2) {
                this.editShowDropdown = false;
                this.editSearchResults = [];
                return;
            }
            const results = await this.searchPredefinedActivities(term);
            this.editSearchResults = results;
            this.editShowDropdown = results.length > 0;
        },
        
        chooseEditGroupActivitySuggestion(s, groupItem) {
            this.editingGroupActivityText = (s.code && s.code.trim() !== '') ? s.code : s.name;
            this.editShowDropdown = false;
            this.editSearchResults = [];
        },
        
        async saveGroupActivityEdit(groupItem) {
            try {
                if (!this.editingGroupActivityText || !this.editingGroupActivityText.trim()) {
                    this.showInfo(this.$t('messages.note'), this.$t('diary.activityRequired'), '', 'warning');
                    return;
                }
                
                // Suche nach der PredefinedActivity
                const searchResults = await this.searchPredefinedActivities(this.editingGroupActivityText.trim());
                const existing = searchResults.find(a => {
                    const searchTerm = this.editingGroupActivityText.trim().toLowerCase();
                    return (a.code && a.code.trim().toLowerCase() === searchTerm) || 
                           (a.name && a.name.trim().toLowerCase() === searchTerm);
                });
                
                if (!existing) {
                    this.showInfo(this.$t('messages.note'), this.$t('diary.activityNotFound'), '', 'warning');
                    return;
                }
                
                // Aktualisiere die Gruppenaktivität mit der neuen PredefinedActivity
                await apiClient.put(`/diary-date-activities/group/${this.currentClub}/${groupItem.id}`, {
                    predefinedActivityId: existing.id,
                    duration: this.editingGroupActivityDuration || null,
                    durationText: this.editingGroupActivityDurationText || null,
                    groupId: this.editingGroupActivityGroupId ? Number(this.editingGroupActivityGroupId) : null
                });
                
                // Lade den Trainingsplan neu
                await this.loadTrainingPlan();
                
                this.editingGroupActivityId = null;
                this.editingGroupActivityText = '';
                this.editingGroupActivityDuration = null;
                this.editingGroupActivityDurationText = '';
                this.editingGroupActivityGroupId = '';
                this.editShowDropdown = false;
                this.editSearchResults = [];
            } catch (error) {
                const msg = getSafeErrorMessage(error, 'Fehler beim Speichern der Gruppenaktivität');
                this.showInfo('Fehler', msg, '', 'error');
            }
        },
        
        cancelGroupActivityEdit() {
            this.editingGroupActivityId = null;
            this.editingGroupActivityText = '';
            this.editingGroupActivityDuration = null;
            this.editingGroupActivityDurationText = '';
            this.editingGroupActivityGroupId = '';
            this.editShowDropdown = false;
            this.editSearchResults = [];
        },
        cancelCurrentPlanEdit() {
            if (this.activePlanEditorType === 'groupActivity') {
                this.cancelGroupActivityEdit();
                return;
            }
            this.cancelActivityEdit();
        },
        closeCurrentAssignmentPanel() {
            this.activityMembersOpenId = null;
            this.groupActivityMembersOpenId = null;
        },

        async loadTrainingPlan() {
            try {
                this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
                this.calculateIntermediateTimes();
                this.activityMembersMap = {};
                this.groupActivityMembersMap = {};
                await this.loadAllActivityMembers();
            } catch (error) {
                console.error('Fehler beim Laden des Trainingsplans:', error);
            }
        },

        cancelActivityEdit() {
            this.editingActivityId = null;
            this.editingActivityText = '';
            this.editingDuration = null;
            this.editingDurationText = '';
        },
        toggleActivitiesBox() {
            this.showActivitiesBox = !this.showActivitiesBox;
        },

        async toggleActivityMembers(item) {
            if (this.activityMembersOpenId === item.id) {
                this.activityMembersOpenId = null;
                return;
            }
            
            this.activityMembersOpenId = item.id;
            
            // Verwende $set für Vue 2 Reaktivität
            if (this.$set) {
                this.$set(this, 'activityMembersOpenId', item.id);
            }
            
            await this.ensureActivityMembersLoaded(item.id);
            
            // Force update um sicherzustellen, dass das Dropdown angezeigt wird
            await this.$nextTick();
            this.$forceUpdate();
        },

        async ensureActivityMembersLoaded(activityId) {
            if (this.activityMembersMap[activityId]) return;
            try {
                const r = await apiClient.get(`/diary-member-activities/${this.currentClub}/${activityId}`);
                const setIds = new Set(r.data.map(x => x.participantId));
                this.$set ? this.$set(this.activityMembersMap, activityId, setIds) : (this.activityMembersMap[activityId] = setIds);
            } catch (e) {
                this.activityMembersMap[activityId] = new Set();
            }
        },

        isAssignedToActivity(activityId, memberId) {
            const participantId = this.participantIdForMember(memberId);
            const setIds = this.activityMembersMap[activityId];
            return setIds ? setIds.has(participantId) : false;
        },

        participantIdForMember(memberId) {
            // In diesem UI haben wir nur memberIds; Participant-IDs müssen über current date abgeleitet werden.
            // Vereinfachung: Participant-ID ist Kombination aus (date.id, memberId) → wir müssen sie vom Backend bekommen.
            // Als Pragmatik: wir holen sie über /participants und mappen nach memberId. Bereits vorhanden in participants-Liste? Nein, nur IDs.
            // Für add/remove nutzen wir einen Helper-Endpoint? Wir haben bereits /participants für dateId → wir bauen Map:
            // Wir speichern eine lokale Map beim Laden der Teilnehmer.
            const map = this.participantMapByMemberId || {};
            return map[memberId];
        },
        isStructuralPlanItem(item) {
            const activity = item?.groupPredefinedActivity || item?.predefinedActivity || null;
            return Boolean(activity?.excludeFromStats);
        },
        getPlanItemStatus(item) {
            if (!item) {
                return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' };
            }

            if (this.isStructuralPlanItem(item)) {
                return { key: 'ready', label: '', tone: 'ready' };
            }

            if (item.isTimeblock) {
                const groupActivities = item.groupActivities || [];
                if (groupActivities.length === 0) {
                    return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' };
                }
                const allReady = groupActivities.every(groupItem => this.getPlanItemStatus(groupItem).key === 'ready');
                return allReady
                    ? { key: 'ready', label: this.$t('diary.statusReadyShort'), tone: 'ready' }
                    : { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' };
            }

            const assignedCount = item.groupPredefinedActivity
                ? this.presentMembers.filter(member => this.isAssignedToGroupActivity(item.id, member.id)).length
                : this.presentMembers.filter(member => this.isAssignedToActivity(item.id, member.id)).length;

            if (assignedCount > 0) {
                return { key: 'ready', label: '', tone: 'ready' };
            }

            return { key: 'open', label: this.$t('diary.statusOpenShort'), tone: 'open' };
        },

        async toggleMemberForActivity(activityId, memberId, checked) {
            let participantId = this.participantIdForMember(memberId);
            try {
                if (checked) {
                    // Falls Mitglied noch kein Participant ist: zuerst hinzufügen
                    if (!participantId) {
                        const created = await apiClient.post('/participants/add', {
                            diaryDateId: this.date.id,
                            memberId: memberId,
                        });
                        participantId = created.data.id;
                        if (!this.participantMapByMemberId) this.participantMapByMemberId = {};
                        this.participantMapByMemberId[memberId] = participantId;
                        if (!this.participants.includes(memberId)) this.participants.push(memberId);
                    }
                    // Danach Zuordnung zur Aktivität anlegen
                    await apiClient.post(`/diary-member-activities/${this.currentClub}/${activityId}`, { participantIds: [participantId] });
                    if (!this.activityMembersMap[activityId]) this.activityMembersMap[activityId] = new Set();
                    this.activityMembersMap[activityId].add(participantId);
                } else {
                    // Nur die Aktivitäts-Zuordnung entfernen (Participant bleibt)
                    if (!participantId) return;
                    await apiClient.delete(`/diary-member-activities/${this.currentClub}/${activityId}/${participantId}`);
                    if (this.activityMembersMap[activityId]) this.activityMembersMap[activityId].delete(participantId);
                }
            } catch (e) {
                this.showInfo('Fehler', 'Fehler beim Aktualisieren der Aktivitäts-Teilnehmer', '', 'error');
            }
        },

        // Gruppenzuordnung für Aktivitäten
        hasActivityMembers(activityId) {
            const setIds = this.activityMembersMap[activityId];
            return setIds && setIds.size > 0;
        },

        // Bulk-Zuordnungen für Aktivitäten
        async assignAllMembersToActivity(activityId) {
            try {
                // Alle anwesenden Mitglieder zur Aktivität hinzufügen
                for (const member of this.presentMembers) {
                    if (!this.isAssignedToActivity(activityId, member.id)) {
                        await this.toggleMemberForActivity(activityId, member.id, true);
                    }
                }
            } catch (error) {
                console.error('Fehler beim Zuordnen aller Teilnehmer:', error);
                this.showInfo('Fehler', 'Fehler beim Zuordnen aller Teilnehmer', '', 'error');
            }
        },

        async assignGroupToActivity(activityId, groupId) {
            if (!groupId) return; // Leere Auswahl ignorieren
            
            try {
                const normalizedGroupId = String(groupId);
                // Alle Mitglieder der gewählten Gruppe zur Aktivität hinzufügen
                const groupMembers = this.presentMembers.filter(member => 
                    this.getMemberGroup(member.id) === normalizedGroupId
                );
                
                for (const member of groupMembers) {
                    if (!this.isAssignedToActivity(activityId, member.id)) {
                        await this.toggleMemberForActivity(activityId, member.id, true);
                    }
                }
            } catch (error) {
                console.error('Fehler beim Zuordnen der Gruppe:', error);
                this.showInfo('Fehler', 'Fehler beim Zuordnen der Gruppe', '', 'error');
            }
        },

        // Group Activity Members Methods
        async toggleGroupActivityMembers(groupItem) {
            if (this.groupActivityMembersOpenId === groupItem.id) {
                this.groupActivityMembersOpenId = null;
                return;
            }
            
            this.groupActivityMembersOpenId = groupItem.id;
            
            // Verwende $set für Vue 2 Reaktivität
            if (this.$set) {
                this.$set(this, 'groupActivityMembersOpenId', groupItem.id);
            }
            
            await this.ensureGroupActivityMembersLoaded(groupItem.id);
            
            // Force update um sicherzustellen, dass das Dropdown angezeigt wird
            await this.$nextTick();
            this.$forceUpdate();
        },

        async ensureGroupActivityMembersLoaded(groupActivityId) {
            if (this.groupActivityMembersMap[groupActivityId]) return;
            try {
                const r = await apiClient.get(`/diary-member-activities/${this.currentClub}/${groupActivityId}`);
                const setIds = new Set(r.data.map(x => x.participantId));
                this.$set ? this.$set(this.groupActivityMembersMap, groupActivityId, setIds) : (this.groupActivityMembersMap[groupActivityId] = setIds);
            } catch (e) {
                this.groupActivityMembersMap[groupActivityId] = new Set();
            }
        },

        isAssignedToGroupActivity(groupActivityId, memberId) {
            const participantId = this.participantIdForMember(memberId);
            const setIds = this.groupActivityMembersMap[groupActivityId];
            return setIds ? setIds.has(participantId) : false;
        },

        async toggleMemberForGroupActivity(groupActivityId, memberId, checked) {
            let participantId = this.participantIdForMember(memberId);
            try {
                if (checked) {
                    // Falls Mitglied noch kein Participant ist: zuerst hinzufügen
                    if (!participantId) {
                        const created = await apiClient.post('/participants/add', {
                            diaryDateId: this.date.id,
                            memberId: memberId,
                        });
                        participantId = created.data.id;
                        if (!this.participantMapByMemberId) this.participantMapByMemberId = {};
                        this.participantMapByMemberId[memberId] = participantId;
                        if (!this.participants.includes(memberId)) this.participants.push(memberId);
                    }
                    // Zuordnung erstellen
                    await apiClient.post(`/diary-member-activities/${this.currentClub}/${groupActivityId}`, {
                        participantIds: [participantId],
                    });
                    const setIds = this.groupActivityMembersMap[groupActivityId] || new Set();
                    setIds.add(participantId);
                    this.$set ? this.$set(this.groupActivityMembersMap, groupActivityId, setIds) : (this.groupActivityMembersMap[groupActivityId] = setIds);
                } else {
                    // Zuordnung entfernen
                    await apiClient.delete(`/diary-member-activities/${this.currentClub}/${groupActivityId}/${participantId}`);
                    const setIds = this.groupActivityMembersMap[groupActivityId];
                    if (setIds) {
                        setIds.delete(participantId);
                    }
                }
            } catch (error) {
                console.error('Fehler beim Zuordnen des Teilnehmers zu Gruppen-Aktivität:', error);
                this.showInfo('Fehler', 'Teilnehmer konnte nicht zugeordnet werden.', '', 'error');
            }
        },

        async assignAllMembersToGroupActivity(groupActivityId) {
            try {
                // Alle anwesenden Mitglieder zur Gruppen-Aktivität hinzufügen
                for (const member of this.presentMembers) {
                    if (!this.isAssignedToGroupActivity(groupActivityId, member.id)) {
                        await this.toggleMemberForGroupActivity(groupActivityId, member.id, true);
                    }
                }
            } catch (error) {
                console.error('Fehler beim Zuordnen aller Teilnehmer:', error);
                this.showInfo('Fehler', 'Fehler beim Zuordnen aller Teilnehmer', '', 'error');
            }
        },

        async assignGroupToGroupActivity(groupActivityId, groupId) {
            if (!groupId) return; // Leere Auswahl ignorieren
            
            try {
                const normalizedGroupId = String(groupId);
                // Alle Mitglieder der gewählten Gruppe zur Gruppen-Aktivität hinzufügen
                const groupMembers = this.presentMembers.filter(member => 
                    this.getMemberGroup(member.id) === normalizedGroupId
                );
                
                for (const member of groupMembers) {
                    if (!this.isAssignedToGroupActivity(groupActivityId, member.id)) {
                        await this.toggleMemberForGroupActivity(groupActivityId, member.id, true);
                    }
                }
            } catch (error) {
                console.error('Fehler beim Zuordnen der Gruppe:', error);
                this.showInfo('Fehler', 'Fehler beim Zuordnen der Gruppe', '', 'error');
            }
        },

        // Gruppenzuordnung für Teilnehmer
        getMemberGroup(memberId) {
            if (!this.memberGroupsMap) {
                return '';
            }
            const value = this.memberGroupsMap[memberId];
            if (value === undefined || value === null) {
                return '';
            }
            return String(value);
        },

        async updateMemberGroup(memberId, groupId) {
            try {
                const selectedGroupId = groupId ? String(groupId) : '';

                // Sofortige UI-Aktualisierung für bessere Reaktivität
                if (this.$set) {
                    this.$set(this.memberGroupsMap, memberId, selectedGroupId);
                } else {
                    // Vue 3: Reaktivität wird automatisch gewährleistet
                    this.memberGroupsMap = {
                        ...this.memberGroupsMap,
                        [memberId]: selectedGroupId
                    };
                }

                // API-Call im Hintergrund
                await apiClient.put(`/participants/${this.date.id}/${memberId}/group`, {
                    groupId: selectedGroupId ? Number(selectedGroupId) : null
                });

                // Synchronisiere die Teilnehmerliste, damit Anzeige und Datenlage übereinstimmen
                // Verwende $nextTick, um sicherzustellen, dass die UI-Aktualisierung zuerst erfolgt
                await this.$nextTick();
                await this.loadParticipants(this.date.id);
            } catch (error) {
                console.error('Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung:', error);
                // Bei Fehler: Lade die Daten neu, um den korrekten Zustand wiederherzustellen
                await this.loadParticipants(this.date.id);
                this.showInfo('Fehler', 'Fehler beim Aktualisieren der Teilnehmer-Gruppenzuordnung', '', 'error');
            }
        },

        // Schnell hinzufügen Dialog Methoden
        openQuickAddDialog() {
            this.showQuickAddDialog = true;

            this.newMember = {
                firstName: '',
                lastName: '',
                birthDate: '',
                gender: ''
            };
        },

        closeQuickAddDialog() {
            this.showQuickAddDialog = false;
            this.newMember = {
                firstName: '',
                lastName: '',
                birthDate: '',
                gender: ''
            };
        },

        async createAndAddMember(memberData) {
            // Verwende die übergebenen Daten oder die lokalen Daten als Fallback
            const data = memberData || this.newMember;
            
            if (!data.firstName || data.firstName.trim() === '') {
                this.showInfo('Fehler', 'Vorname ist erforderlich', '', 'error');
                return;
            }

            try {
                // Erstelle neues Mitglied
                const memberDataToSend = {
                    firstName: data.firstName.trim(),
                    lastName: data.lastName.trim(),
                    birthDate: data.birthDate || '',
                    gender: data.gender
                };

                const response = await apiClient.post(`/clubmembers/set/${this.currentClub}`, {
                    id: null, // null für neues Mitglied
                    firstname: memberDataToSend.firstName,
                    lastname: memberDataToSend.lastName,
                    street: '',
                    city: '',
                    birthdate: memberDataToSend.birthDate,
                    phone: '',
                    email: '',
                    active: true,
                    testMembership: true,
                    picsInInternetAllowed: false,
                    gender: memberDataToSend.gender
                });

                if (response.data.result === 'success') {
                    // Lade die aktualisierte Mitgliederliste
                    const membersResponse = await apiClient.get(`/clubmembers/get/${this.currentClub}/false`);
                    this.members = membersResponse.data;

                    // Finde das neu erstellte Mitglied (das letzte in der Liste)
                    const newMember = this.members[this.members.length - 1];

                    // Füge das neue Mitglied als Teilnehmer hinzu
                    await this.toggleParticipant(newMember.id);

                    // Schließe den Dialog
                    this.closeQuickAddDialog();

                    // Zeige Erfolgsmeldung
                    this.showInfo('Erfolg', `Mitglied "${newMember.firstName} ${newMember.lastName}" wurde erfolgreich erstellt und hinzugefügt!`, '', 'success');
                } else {
                    throw new Error('Fehler beim Erstellen des Mitglieds');
                }

            } catch (error) {
                console.error('Fehler beim Erstellen des Mitglieds:', error);
                this.showInfo('Fehler', 'Fehler beim Erstellen des Mitglieds', getSafeErrorMessage(error), 'error');
            }
        },
        
        // Socket.IO Event-Handler
        setupSocketListeners() {
            // Event-Handler für Teilnehmer-Änderungen
            onParticipantAdded(this.handleParticipantAdded);
            onParticipantRemoved(this.handleParticipantRemoved);
            onParticipantUpdated(this.handleParticipantUpdated);
            
            // Event-Handler für Tagebuch-Änderungen
            onDiaryNoteAdded(this.handleDiaryNoteAdded);
            onDiaryNoteDeleted(this.handleDiaryNoteDeleted);
            onDiaryTagAdded(this.handleDiaryTagAdded);
            onDiaryTagRemoved(this.handleDiaryTagRemoved);
            onDiaryDateUpdated(this.handleDiaryDateUpdated);
            
            // Event-Handler für Aktivitäts-Änderungen
            onActivityMemberAdded(this.handleActivityMemberAdded);
            onActivityMemberRemoved(this.handleActivityMemberRemoved);
            onActivityChanged(this.handleActivityChanged);
            
            // Event-Handler für Member-Änderungen
            onMemberChanged(this.handleMemberChanged);
            
            // Event-Handler für Gruppen-Änderungen
            onGroupChanged(this.handleGroupChanged);
        },
        
        removeSocketListeners() {
            offParticipantAdded(this.handleParticipantAdded);
            offParticipantRemoved(this.handleParticipantRemoved);
            offParticipantUpdated(this.handleParticipantUpdated);
            offDiaryNoteAdded(this.handleDiaryNoteAdded);
            offDiaryNoteDeleted(this.handleDiaryNoteDeleted);
            offDiaryTagAdded(this.handleDiaryTagAdded);
            offDiaryTagRemoved(this.handleDiaryTagRemoved);
            offDiaryDateUpdated(this.handleDiaryDateUpdated);
            offActivityMemberAdded(this.handleActivityMemberAdded);
            offActivityMemberRemoved(this.handleActivityMemberRemoved);
            offActivityChanged(this.handleActivityChanged);
            offMemberChanged(this.handleMemberChanged);
            offGroupChanged(this.handleGroupChanged);
        },
        
        async handleParticipantAdded(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Teilnehmer neu
                await this.loadParticipants(data.dateId);
            }
        },
        
        async handleParticipantRemoved(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Entferne aus participants-Array
                this.participants = this.participants.filter(memberId => memberId !== data.participantId);
                const nextParticipantMap = { ...this.participantMapByMemberId };
                const nextGroupMap = { ...this.memberGroupsMap };
                const nextStatusMap = { ...this.participantStatusMap };
                delete nextParticipantMap[data.participantId];
                delete nextGroupMap[data.participantId];
                delete nextStatusMap[data.participantId];
                this.participantMapByMemberId = nextParticipantMap;
                this.memberGroupsMap = nextGroupMap;
                this.participantStatusMap = nextStatusMap;
            }
        },
        
        async handleParticipantUpdated(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date !== 'new' && String(this.date.id) === String(data.dateId)) {
                const status = data.participant.attendanceStatus || 'present';
                const groupValue = (data.participant.groupId !== null && data.participant.groupId !== undefined) 
                    ? String(data.participant.groupId) 
                    : '';

                if (this.$set) {
                    this.$set(this.memberGroupsMap, data.participant.memberId, groupValue);
                    this.$set(this.participantStatusMap, data.participant.memberId, status);
                    this.$set(this.participantMapByMemberId, data.participant.memberId, data.participant.id);
                } else {
                    this.memberGroupsMap = {
                        ...this.memberGroupsMap,
                        [data.participant.memberId]: groupValue
                    };
                    this.participantStatusMap = {
                        ...this.participantStatusMap,
                        [data.participant.memberId]: status
                    };
                    this.participantMapByMemberId = {
                        ...this.participantMapByMemberId,
                        [data.participant.memberId]: data.participant.id
                    };
                }

                if (status === 'present') {
                    this.participants = [...new Set([...this.participants, data.participant.memberId])];
                } else {
                    this.participants = this.participants.filter(memberId => memberId !== data.participant.memberId);
                }

                await this.$nextTick();
                this.$forceUpdate();
            }
        },
        
        async handleDiaryNoteAdded(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Notizen neu, falls das betroffene Mitglied ausgewählt ist
                if (this.selectedMember && data.note.memberId === this.selectedMember.id) {
                    try {
                        const notesResponse = await apiClient.get(`/notes?diaryDateId=${this.date.id}&memberId=${this.selectedMember.id}`);
                        this.notes = notesResponse.data;
                    } catch (error) {
                        console.error('Fehler beim Laden der Notizen:', error);
                    }
                }
            }
        },
        
        async handleDiaryNoteDeleted(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Entferne Notiz aus notes-Array
                this.notes = this.notes.filter(note => note.id !== data.noteId);
            }
        },
        
        async handleDiaryTagAdded(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Tags neu
                await this.loadTags();
                // Aktualisiere selectedActivityTags
                if (data.tag && !this.selectedActivityTags.find(t => t.id === data.tag.id)) {
                    this.selectedActivityTags.push({
                        id: data.tag.id,
                        name: data.tag.name
                    });
                }
            }
        },
        
        async handleDiaryTagRemoved(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Entferne Tag aus selectedActivityTags
                this.selectedActivityTags = this.selectedActivityTags.filter(t => t.id !== data.tagId);
            }
        },
        
        async handleDiaryDateUpdated(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Aktualisiere Trainingszeiten
                if (data.updates.trainingStart !== undefined) {
                    this.trainingStart = data.updates.trainingStart;
                }
                if (data.updates.trainingEnd !== undefined) {
                    this.trainingEnd = data.updates.trainingEnd;
                }
                if (data.updates.excludeFromBilling !== undefined) {
                    this.excludeFromBilling = Boolean(data.updates.excludeFromBilling);
                }
            }
        },
        
        async handleActivityMemberAdded(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Training Plan neu
                try {
                    this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
                    this.calculateIntermediateTimes();
                } catch (error) {
                    console.error('Fehler beim Neuladen des Trainingsplans:', error);
                }
            }
        },
        
        async handleActivityMemberRemoved(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Training Plan neu
                try {
                    this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
                    this.calculateIntermediateTimes();
                } catch (error) {
                    console.error('Fehler beim Neuladen des Trainingsplans:', error);
                }
            }
        },
        
        async handleActivityChanged(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date.id === data.dateId) {
                // Lade Training Plan neu
                try {
                    this.trainingPlan = await apiClient.get(`/diary-date-activities/${this.currentClub}/${this.date.id}`).then(response => response.data);
                    this.calculateIntermediateTimes();
                } catch (error) {
                    console.error('Fehler beim Neuladen des Trainingsplans:', error);
                }
            }
        },
        
        async handleMemberChanged(data) {
            // Prüfe, ob der Club übereinstimmt
            if (data.clubId && String(data.clubId) === String(this.currentClub)) {
                // Lade Mitgliederliste neu
                try {
                    await this.loadMembers();
                    // Force Vue update
                    this.$forceUpdate();
                } catch (error) {
                    console.error('Fehler beim Neuladen der Mitgliederliste:', error);
                }
            }
        },
        
        async handleGroupChanged(data) {
            // Nur aktualisieren, wenn das aktuelle Datum betroffen ist
            if (this.date && this.date !== 'new' && String(this.date.id) === String(data.dateId)) {
                try {
                    await this.loadGroups();
                    // Force Vue update
                    this.$forceUpdate();
                } catch (error) {
                    console.error('Fehler beim Neuladen der Gruppenliste:', error);
                }
            }
        },
        updateViewportState() {
            this.isMobileView = typeof window !== 'undefined' ? window.innerWidth <= 768 : false;
        }
    },
    async mounted() {
        await this.init();
        await this.loadStandardPredefinedActivities();
        
        // Socket.IO verbinden
        if (this.currentClub) {
            connectSocket(this.currentClub);
            this.setupSocketListeners();
        }
        
        // Versuche, Audio erst bei Nutzerinteraktion zu initialisieren (Autoplay-Policy)
        const tryInit = () => {
            if (!this.bellSound) this.bellSound = new Audio('/sound/bell-123742.mp3');
            if (!this.thumbSound) this.thumbSound = new Audio('/sound/thump-105302.mp3');
            this.soundEnabled = true;
            window.removeEventListener('click', tryInit, { once: true });
        };
        window.addEventListener('click', tryInit, { once: true });
        window.addEventListener('resize', this.updateViewportState);
    },
    beforeUnmount() {
        if (this.timeChecker) {
            clearInterval(this.timeChecker);
        }
        
        // Socket.IO Event-Listener entfernen
        this.removeSocketListeners();
        
        // Socket.IO trennen
        disconnectSocket();
        window.removeEventListener('resize', this.updateViewportState);
    }
};
</script>

<style scoped>
form {
    margin-top: 20px;
}

form div {
    margin-bottom: 10px;
}

.diary-general-card {
    margin-top: 1rem;
    margin-bottom: 1rem;
    padding: 1rem 1.25rem;
    border: 1px solid #d9e4ec;
    border-radius: 12px;
    background: #f9fbfd;
}

.diary-general-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
}

.diary-general-header h3 {
    margin: 0.2rem 0 0;
}

.diary-general-label {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #517287;
}

.diary-general-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 0.9rem;
}

.diary-general-stat {
    min-width: 130px;
}

.diary-general-stat span {
    display: block;
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #5f7b8b;
}

.diary-general-form {
    margin-top: 1rem;
}

.diary-overview-panels {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
    margin-bottom: 1rem;
}

.diary-overview-switcher {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.diary-overview-switch {
    padding: 0.5rem 0.8rem;
    border: 1px solid #cfdbe3;
    border-radius: 999px;
    background: #fff;
    color: #315066;
    font-weight: 600;
    cursor: pointer;
}

.diary-overview-switch.active {
    background: #e6f0f6;
    border-color: #9bb9cb;
    color: #173042;
}

.diary-toggle-card {
    border: 1px solid #d9e4ec;
    border-radius: 12px;
    background: #f9fbfd;
    overflow: hidden;
}

.diary-toggle-head {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    padding: 0.65rem 0.9rem;
    background: transparent;
    border: none;
    cursor: pointer;
    text-align: left;
}

.diary-toggle-head > div {
    min-width: 0;
    line-height: 1.2;
}

.diary-toggle-head strong {
    display: block;
    margin-top: 0.1rem;
    font-size: 0.98rem;
    line-height: 1.2;
}

.diary-toggle-symbol {
    font-size: 1.15rem;
    line-height: 1;
    color: #315066;
}

.diary-toggle-body {
    padding: 0 0.9rem 0.9rem;
}

.diary-toggle-body-open {
    padding-top: 0.9rem;
}

.diary-groups-grid {
    display: grid;
    grid-template-columns: 1.4fr 1fr;
    gap: 1rem;
}

.diary-groups-grid h4 {
    margin-top: 0;
}

button[type="button"] {
    margin-left: 10px;
}

h3 {
    display: block;
}

form {
    margin-top: 20px;
}

form div {
    margin-bottom: 10px;
}

button[type="button"] {
    margin-left: 10px;
}

h3 {
    display: block;
}

.columns {
    display: flex;
    justify-content: space-between;
    width: calc(100% - 1em);
    overflow: visible;
    height: 100%;
}

.diary-header-row {
    display: flex;
    align-items: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

/* Global `label { display: inline-flex }` würde sonst alle Kinder in eine Zeile zwängen und Buttons schrumpfen lassen. */
.diary-header-row > label {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    flex: 1 1 auto;
    min-width: 0;
    max-width: 100%;
    margin: 0;
    cursor: default;
}

.diary-header-row > label > select {
    flex: 1 1 12rem;
    min-width: min(12rem, 100%);
    max-width: 100%;
}

.diary-header-row > label > .btn-primary,
.diary-header-row > label > .btn-secondary {
    flex-shrink: 0;
    white-space: nowrap;
}

.gallery-trigger {
    align-self: flex-end;
}

.column:first-child {
    flex: 1;
    overflow: visible;
    height: 100%;
    justify-self: start;
    display: flex;
    flex-direction: column;
}

.column:last-child {
    overflow: auto;
}

textarea {
    width: 100%;
    margin-bottom: 10px;
}

ul {
    list-style-type: none;
    padding: 0;
}

.modal {
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    z-index: 1000;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 50%;
    height: 50%;
    overflow: auto;
    background-color: rgba(200, 200, 200, 0.5);
}

.modal-content {
    background-color: #fefefe;
    padding: 20px;
    border: 1px solid #555;
    width: 100%;
    height: 100%;
    position: relative;
    box-shadow: 4px 3px 2px #999;
}

.close {
    position: absolute;
    top: 10px;
    right: 15px;
    color: #aaa;
    font-size: 28px;
    font-weight: bold;
}

.close:hover,
.close:focus {
    color: black;
    text-decoration: none;
    cursor: pointer;
}

ul {
    list-style-type: none;
    padding: 0;
}

li {
    padding: 0;
    margin-bottom: 5px;
}

li.participant-row {
    display: flex !important;
    align-items: center;
    gap: 0.5rem;
    flex-direction: row;
}

li.participant-row .checkbox-label {
    margin: 0 !important;
    padding: 0;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    flex: 0 0 auto !important;
}

li.participant-row .participant-name {
    flex: 0 1 auto;
    min-width: 0;
    order: 1;
}

li.participant-row .participant-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
    flex-shrink: 0;
    order: 2;
}

/* Teilnehmer-Farben (wie in MembersView) */
.row-inactive {
    opacity: .6;
}

.row-test {
    background-color: #fff3cd;
}

.row-test-form {
    background-color: #ffffcc;
}

/* Icon für Mitgliedsformular ausgehändigt (wie Info- und Picture-Button) */
.form-handover-icon {
    margin-left: 0.25rem;
}

.warning-icon {
    margin-right: 0.25rem;
    font-size: 0.8rem;
}

.warning-icon-severe {
    font-size: 0.8rem;
    animation: pulse-warning 2s infinite;
}

@keyframes pulse-warning {
    0%, 100% {
        opacity: 1;
        transform: scale(1);
    }
    50% {
        opacity: 0.7;
        transform: scale(1.1);
    }
}

.multiselect {
    margin-bottom: 10px;
    width: 100%;
}

.collapsible-box {
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    padding: 0.5rem;
    background: white;
}

table {
    width: 100%;
    border-collapse: collapse;
    overflow: visible;
}

thead,
tbody,
tr,
td,
th {
    overflow: visible;
}

td {
    position: static;
}

/* Bearbeitungszelle soll relativer Kontext sein */
.clickable,
td>div[style*="position: relative"] {
    position: relative;
}

th,
td {
    padding: 8px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}

input[type="text"] {
    width: 100%;
    padding: 5px;
    box-sizing: border-box;
}

input[type="time"] {
    width: 7em;
}

input[type="number"] {
    width: 5em;
    padding: 5px;
    box-sizing: border-box;
}

.dropdown {
    border: 1px solid #ccc;
    max-height: 200px;
    overflow-y: auto;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 2px;
    background-color: white;
    z-index: 9999;
    width: 100%;
    box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
    max-width: 30em;
}

.dropdown div {
    padding: 8px;
    cursor: pointer;
}

.dropdown div:hover {
    background-color: #f0f0f0;
}

.clickable {
    cursor: pointer;
    color: var(--primary-color);
    transition: color 0.2s ease;
}

.clickable:hover {
    color: var(--primary-hover);
    text-decoration: underline;
}

.highlighted {
    background-color: #45a049;
    color: white;
    padding: 0.2em;
    border-radius: 4px;
}

.add-plan-item {
    border: 1px solid black;
    cursor: pointer;
    display: inline-block;
    width: 1.2em;
    height: 1.2em;
    text-align: center;
    line-height: 1.2em;
    font-weight: bold;
    margin-left: 5px;
    border-radius: 2px;
}

.cancel {
    border: 1px solid black;
    cursor: pointer;
    display: inline-block;
    width: 1.2em;
    height: 1.2em;
    text-align: center;
    line-height: 1.2em;
    font-weight: bold;
    margin-left: 5px;
    color: #ff0000;
    font-weight: bold;
    border-radius: 2px;
}

.add-plan-item:hover {
    background-color: #45a049;
    color: white;
}

.drag-handle {
    cursor: pointer;
}

.modal-body {
    display: flex;
    justify-content: space-between;
}

.modal-left {
    flex: 0 0 250px;
    display: flex;
    justify-content: center;
    align-items: center;
    padding-right: 20px;
}

.modal-right {
    flex: 1;
}

.img-icon {
    cursor: pointer;
}

img {
    max-width: 75%;
    max-height: 75%;
    position: absolute;
    left: 12.5%;
    top: 12.5%;
    box-shadow: 3px 3px 2px;
    border: 3px double #aaa;
}

.memberImage {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.8);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
    margin: 0;
    padding: 0;
}

.memberImage>img {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    display: block;
    margin: 0 auto;
}

.memberImage>div,
.memberImage canvas {
    /* falls Komponenten-Inhalt (Renderer) da ist, mittig zeigen */
    display: block;
    margin: 0 auto;
}

.groups {
    display: flex;
    flex-direction: row;
}

.diary {
    width: 100%;
    height: 100%;
    overflow: visible;
    display: flex;
    flex-direction: column;
}

.tag-header {
    margin: 0
}

.tag-list {
    margin: 0 0 1em 1.5em;
}

.accidentForm {
    display: block;
    position: fixed;
    width: 70em;
    height: 40em;
    top: calc(50% - 20em);
    left: calc(50% - 35em);
    border: 2px solid #555;
    box-shadow: 4px 4px 3px #aaa;
    overflow: hidden;
    padding: 3px;
    background-color: #fff;
}

.collapsible-box {
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius);
    padding: 0.5rem;
    background: white;
}

.collapsible-box h3 {
    margin-top: 0;
    margin-bottom: 10px;
    cursor: pointer;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.collapsible-box h3 span {
    font-size: 1.2em;
    transition: transform 0.3s ease;
}

.collapsible-box.collapsed h3 span {
    transform: rotate(0deg);
}

.collapsible-box.expanded h3 span {
    transform: rotate(90deg);
}

.person-btn {
    margin-right: 0.5rem;
}

.image-icon {
    margin-right: 8px;
    cursor: pointer;
    font-size: 16px;
    opacity: 0.7;
    transition: opacity 0.2s;
}

.image-icon:hover {
    opacity: 1;
}

/* Schnell hinzufügen Button */
.add-participant {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid #dee2e6;
}

.quick-add-btn {
    background-color: #17a2b8;
    color: white;
    border: none;
    padding: 0.5rem 1rem;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.9em;
    transition: background-color 0.2s ease;
    white-space: nowrap;
}

.quick-add-btn:hover {
    background-color: #138496;
}

.quick-add-btn:active {
    background-color: #117a8b;
}

/* Modal Dialog Styles */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.modal {
    background: var(--surface-color);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow: 0 18px 48px rgba(15, 23, 42, 0.18);
    max-width: 500px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
}

.modal-header {
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--border-color);
    background: linear-gradient(180deg, rgba(47, 122, 95, 0.12), rgba(47, 122, 95, 0.04));
}

.modal-header h3 {
    margin: 0;
    color: var(--text-color);
}

.modal-body {
    padding: 1.5rem;
    flex: 1;
    display: flex;
    flex-direction: column;
}


.modal-body .form-row {
    display: flex !important;
    gap: 1rem;
    margin-bottom: 1rem;
    flex-wrap: nowrap;
}

.modal-body .form-row .form-group {
    flex: 1;
    margin-bottom: 0;
    min-width: 0;
}

.modal-body .form-row:last-child {
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-color);
    flex-wrap: nowrap;
}

.form-group {
    margin-bottom: 1rem;
}

.form-group label {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: 500;
    color: var(--text-color);
}

.form-group input,
.form-group select {
    width: 100%;
    padding: 0.75rem 0.875rem;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    font-size: 1rem;
    background: var(--surface-muted);
    color: var(--text-color);
}

.form-group input:focus,
.form-group select:focus {
    outline: none;
    border-color: var(--primary-color);
    box-shadow: 0 0 0 3px rgba(47, 122, 95, 0.14);
}

.modal .btn-secondary {
    background: var(--surface-color) !important;
    color: var(--text-color) !important;
    border: 1px solid var(--border-color) !important;
    padding: 0.5rem 1rem !important;
    border-radius: 10px !important;
    cursor: pointer !important;
    font-size: 0.9rem !important;
}

.modal .btn-secondary:hover {
    background: var(--surface-muted) !important;
    border-color: var(--primary-soft) !important;
}

.modal .btn-primary {
    background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)) !important;
    color: var(--text-on-primary) !important;
    border: 1px solid transparent !important;
    padding: 0.5rem 1rem !important;
    border-radius: 10px !important;
    cursor: pointer !important;
    font-size: 0.9rem !important;
}

.btn-palette {
    background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
    color: var(--text-on-primary);
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 0.25rem;
    font-size: 1rem;
    cursor: pointer;
    transition: all 0.2s ease;
    width: 1.75rem;
    height: 0.75rem;
    margin: 0 !important;
    margin-left: 0 !important;
    display: flex;
    align-items: center;
    justify-content: center;
}

.btn-palette:hover {
    opacity: 0.95;
    transform: translateY(-1px);
}

.modal .btn-primary:hover {
    opacity: 0.95 !important;
}

.modal .btn-primary:disabled {
    background-color: #6c757d !important;
    cursor: not-allowed !important;
    opacity: 0.6 !important;
}

/* Notes Modal Styles */
.notes-modal-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.notes-header-info {
    padding: 0.5rem;
    background: var(--background-light);
    border-radius: 4px;
    font-size: 0.9rem;
    color: var(--text-muted);
}

.notes-body {
    display: flex;
    gap: 1.5rem;
}

.notes-left {
    flex-shrink: 0;
}

.member-image {
    width: 250px;
    height: 250px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border-color);
}

.notes-right {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.note-textarea {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid var(--border-color);
    border-radius: 4px;
    font-family: inherit;
    resize: vertical;
}

.notes-list h4 {
    margin: 0 0 0.5rem 0;
    font-size: 1rem;
}

.notes-list ul {
    list-style: none;
    padding: 0;
    margin: 0;
}

.note-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem;
    margin-bottom: 0.5rem;
    background: var(--background-light);
    border-radius: 4px;
}

.note-content {
    flex: 1;
}

.diary-workspace-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1rem;
    padding: 1rem 1.25rem;
    border: 1px solid #d9e4ec;
    border-radius: 12px;
    background: linear-gradient(180deg, #f8fbfd 0%, #eef5f9 100%);
}

.diary-workspace-copy h3 {
    margin: 0.1rem 0 0.25rem;
    font-size: 1.15rem;
}

.diary-workspace-label {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #517287;
}

.diary-workspace-status {
    margin: 0;
    font-size: 0.92rem;
    color: #45606f;
}

.diary-workspace-stats {
    display: grid;
    grid-template-columns: repeat(4, minmax(110px, 1fr));
    gap: 0.75rem;
    width: min(560px, 100%);
}

.diary-stat-card {
    padding: 0.8rem 0.9rem;
    border-radius: 10px;
    background: #fff;
    border: 1px solid #d9e4ec;
}

.diary-stat-label {
    display: block;
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #5f7b8b;
}

.diary-stat-value {
    display: block;
    margin-top: 0.25rem;
    font-size: 1rem;
    color: #173042;
}

@media (min-width: 769px) and (max-width: 1100px) {
    .diary-overview-panels {
        display: grid;
        grid-template-columns: 1fr;
        gap: 0.65rem;
        margin-bottom: 0.8rem;
    }

    .diary-overview-switcher {
        gap: 0.4rem;
    }

    .diary-overview-switch {
        padding: 0.42rem 0.68rem;
        font-size: 0.9rem;
    }

    .diary-toggle-card {
        border-radius: 10px;
    }

    .diary-toggle-head {
        gap: 0.7rem;
        padding: 0.7rem 0.85rem;
    }

    .diary-toggle-body {
        padding: 0 0.85rem 0.8rem;
    }

    .diary-general-label {
        font-size: 0.72rem;
    }

    .diary-toggle-head strong {
        display: block;
        font-size: 0.95rem;
        line-height: 1.25;
    }

    .diary-toggle-symbol {
        font-size: 1.1rem;
    }

    .diary-workspace-header {
        gap: 0.75rem;
        margin-bottom: 0;
        padding: 0.75rem 0.85rem;
        border-radius: 10px;
    }

    .diary-workspace-copy h3 {
        font-size: 1rem;
    }

    .diary-workspace-status {
        font-size: 0.88rem;
    }

    .diary-workspace-stats {
        grid-template-columns: repeat(2, minmax(92px, 1fr));
        gap: 0.5rem;
        width: 100%;
    }

    .diary-stat-card {
        padding: 0.6rem 0.7rem;
        border-radius: 8px;
    }

    .diary-stat-label {
        font-size: 0.68rem;
    }

    .diary-stat-value {
        margin-top: 0.15rem;
        font-size: 0.92rem;
    }

    .diary-groups-grid {
        grid-template-columns: 1fr;
        gap: 0.75rem;
    }
}

.participant-toolbar {
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    margin-bottom: 0.85rem;
}

.participant-search-input {
    width: 100%;
    padding: 0.55rem 0.7rem;
    border: 1px solid #ccd8e0;
    border-radius: 8px;
    background: #fff;
}

.participant-filter-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.45rem;
}

.participant-filter-chip {
    border: 1px solid #ccd8e0;
    background: #f3f7fa;
    color: #365266;
    border-radius: 999px;
    padding: 0.35rem 0.75rem;
    font-size: 0.85rem;
    cursor: pointer;
}

.participant-filter-chip.active {
    background: #dcebf5;
    border-color: #8eb7d1;
    color: #14374c;
    font-weight: 600;
}

.plan-toolbar {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    align-items: flex-start;
    margin-bottom: 1rem;
    padding: 0.9rem 1rem;
    border: 1px solid #d9e4ec;
    border-radius: 10px;
    background: #f8fbfd;
}

.plan-toolbar-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.plan-toolbar-stat {
    min-width: 100px;
}

.plan-toolbar-label {
    display: block;
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: #5f7b8b;
}

.plan-toolbar-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: flex-end;
}

.plan-empty-state {
    margin-bottom: 0.9rem;
    padding: 0.8rem 0.9rem;
    border-radius: 8px;
    background: #f3f7fa;
    color: #516978;
}

.plan-composer {
    margin-bottom: 1rem;
    padding: 0.95rem 1rem;
    border: 1px solid #d9e4ec;
    border-radius: 10px;
    background: #f8fbfd;
}

.plan-composer-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.85rem;
}

.plan-quick-actions {
    margin-bottom: 0.9rem;
    padding: 0.85rem;
    border: 1px solid var(--border-color, #d9e4ec);
    border-radius: 10px;
    background: var(--surface-subtle, #f3f7fa);
}

.plan-quick-actions-label {
    display: block;
    margin-bottom: 0.65rem;
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text-muted, #4d6979);
}

.plan-quick-actions-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 0.65rem;
}

.plan-quick-action {
    justify-content: flex-start;
}

.plan-quick-action-meta {
    color: var(--text-muted, #4d6979);
    font-weight: 500;
}

.plan-composer-grid {
    display: grid;
    grid-template-columns: 1.8fr 1fr 1.2fr;
    gap: 0.85rem;
}

.plan-composer-field label {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 0.82rem;
    font-weight: 700;
    color: #4d6979;
}

.plan-composer-field input,
.plan-composer-field select {
    width: 100%;
}

.plan-composer-activity-input {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
}

.plan-composer-input-wrap {
    flex: 1;
    position: relative;
}

.plan-composer-duration {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

.plan-composer-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.9rem;
}

.plan-row-actions {
    position: relative;
    display: inline-flex;
    gap: 0.35rem;
    align-items: center;
    flex-wrap: wrap;
}

.plan-cell-stack {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.plan-cell-item {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    padding: 0.35rem 0.4rem;
    border: 1px solid #e4edf2;
    border-radius: 8px;
    background: #f9fcfe;
}

.plan-row-action-button {
    border: 1px solid #cfdbe3;
    background: #f3f7fa;
    color: #274455;
    border-radius: 7px;
    padding: 0.22rem 0.55rem;
    font-size: 0.78rem;
    cursor: pointer;
}

.plan-row-action-button-primary {
    background: #dcebf5;
    border-color: #8eb7d1;
}

.plan-row-action-button-danger {
    background: #fff0f0;
    border-color: #dfb4b4;
    color: #8a2f2f;
}

.plan-timeblock-row {
    background: #f8fbfd;
}

.plan-group-activity-row td {
    background: #fcfdfe;
}

.plan-group-activity-cell {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    padding-left: 0.75rem;
}

.plan-activity-main {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    flex-wrap: wrap;
}

.plan-type-badge {
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    padding: 0.1rem 0.5rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.plan-type-badge-timeblock {
    background: #dcebf5;
    color: #173c52;
}

.plan-type-badge-group {
    background: #e9f3e6;
    color: #245037;
}

.plan-row-muted {
    color: #607785;
    font-size: 0.84rem;
}

.plan-status-badge {
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    padding: 0.1rem 0.45rem;
    font-size: 0.72rem;
    font-weight: 700;
}

.plan-status-badge-ready {
    background: #e9f3e6;
    color: #245037;
}

.plan-status-badge-open {
    background: #fff2d9;
    color: #7a5a12;
}

.plan-duration-badge {
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    padding: 0.1rem 0.45rem;
    font-size: 0.72rem;
    font-weight: 700;
    background: #eaf1f5;
    color: #39566a;
}

.diary-readiness-panel {
    margin-bottom: 1rem;
    padding: 0.9rem 1rem;
    border: 1px solid #d9e4ec;
    border-radius: 10px;
    background: #f8fbfd;
}

.diary-readiness-header {
    margin-bottom: 0.75rem;
}

.diary-readiness-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(120px, 1fr));
    gap: 0.75rem;
}

.diary-readiness-item {
    padding: 0.7rem 0.8rem;
    border-radius: 8px;
    background: #fff2d9;
    color: #7a5a12;
}

.diary-readiness-item.ready {
    background: #e9f3e6;
    color: #245037;
}

.diary-readiness-item span {
    display: block;
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.plan-editor {
    margin-bottom: 1rem;
    padding: 0.95rem 1rem;
    border: 1px solid #d9e4ec;
    border-radius: 10px;
    background: #fffaf2;
}

.plan-editor-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.85rem;
}

.plan-editor-grid {
    display: grid;
    grid-template-columns: 1.8fr 1fr;
    gap: 0.85rem;
}

.plan-editor-field label {
    display: block;
    margin-bottom: 0.3rem;
    font-size: 0.82rem;
    font-weight: 700;
    color: #4d6979;
}

.plan-editor-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 0.9rem;
}

.plan-assignment-panel {
    margin-bottom: 1rem;
    padding: 0.95rem 1rem;
    border: 1px solid #d9e4ec;
    border-radius: 10px;
    background: #f6faf7;
}

.plan-assignment-toolbar {
    display: flex;
    gap: 0.6rem;
    align-items: center;
    margin-bottom: 0.85rem;
    flex-wrap: wrap;
}

.plan-assignment-list {
    display: grid;
    grid-template-columns: repeat(2, minmax(180px, 1fr));
    gap: 0.45rem 0.8rem;
}

.plan-assignment-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.plan-add-hint {
    color: #607785;
    font-style: italic;
}

/* Tab-Navigation für Mobile */
.mobile-tabs {
    display: none;
    width: 100%;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 1rem;
    background: var(--surface-muted);
    position: sticky;
    top: 0;
    z-index: 100;
}

.tab-button {
    flex: 1;
    padding: 0.75rem 1rem;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 1rem;
    border-bottom: 3px solid transparent;
    transition: all 0.3s ease;
    color: var(--text-muted);
}

.mobile-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.5rem;
    margin-left: 0.35rem;
    padding: 0.05rem 0.35rem;
    border-radius: 999px;
    background: rgba(47, 122, 95, 0.1);
    font-size: 0.78rem;
}

.tab-button:hover {
    background: var(--surface-color);
    color: var(--text-color);
}

.tab-button.active {
    border-bottom-color: var(--primary-color);
    color: var(--primary-strong);
    font-weight: 600;
    background: var(--surface-color);
}

/* Mobile Tab Content */
.mobile-tab-content {
    display: block;
}

.mobile-tab-section {
    display: block;
}

.desktop-sidebar {
    display: block;
}

/* Diary Content Container */
.diary-content {
    overflow: visible;
}

/* Responsive Design */
@media (max-width: 768px) {
    .diary-workspace-header {
        flex-direction: column;
    }

    .diary-workspace-stats {
        grid-template-columns: repeat(2, minmax(120px, 1fr));
    }

    .plan-toolbar {
        flex-direction: column;
    }

    .plan-composer-grid {
        grid-template-columns: 1fr;
    }

    .plan-editor-grid {
        grid-template-columns: 1fr;
    }

    .diary-readiness-grid {
        grid-template-columns: 1fr 1fr;
    }

    .plan-assignment-list {
        grid-template-columns: 1fr;
    }

    .plan-composer-actions {
        justify-content: flex-start;
    }

    .plan-editor-actions {
        justify-content: flex-start;
    }

    .plan-toolbar-actions {
        justify-content: flex-start;
    }

    .diary-groups-grid {
        grid-template-columns: 1fr;
    }

    .mobile-tabs {
        display: flex;
    }
    
    .diary-content {
        overflow: visible;
        padding-bottom: 2rem;
    }
    
    /* Sicherstellen, dass Tab-Content genug Platz am Ende hat */
    .column.mobile-tab-content.active {
        padding-bottom: 3rem;
    }
    
    .columns {
        display: block;
        flex-direction: column;
        width: 100%;
        overflow: visible;
        height: auto;
    }
    
    .column {
        display: block;
        width: 100%;
        max-width: 100%;
        overflow: visible;
        height: auto;
    }
    
    .column.mobile-tab-content {
        display: none;
    }
    
    .column.mobile-tab-content.active {
        display: block;
    }
    
    .mobile-sidebar .desktop-sidebar {
        display: none !important;
    }
    
    .mobile-sidebar .mobile-tab-section {
        display: block;
    }
    
    /* Besseres Scrollen - nur eine Haupt-Scrollbar */
    .diary {
        overflow-x: hidden;
        overflow-y: visible;
        -webkit-overflow-scrolling: touch;
        height: auto;
        min-height: 100dvh;
    }
    
    .columns {
        overflow: visible;
    }
    
    .column:first-child {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        overflow-y: visible;
    }
    
    .column:last-child {
        overflow: visible;
    }

    .mobile-sidebar {
        padding-bottom: 6rem !important;
    }

    .mobile-sidebar .diary-sidebar-section {
        margin-top: 0;
        min-width: 0;
    }
    
    /* Tabelle horizontal scrollbar nur wenn nötig */
    table {
        display: block;
        overflow-x: auto;
        white-space: nowrap;
        -webkit-overflow-scrolling: touch;
        overflow-y: visible;
    }
    
    table thead,
    table tbody,
    table tr {
        display: table;
        width: 100%;
        table-layout: fixed;
    }
    
    /* Teilnehmerliste ohne eigene Scrollbar - nutzt Haupt-Scroll */
    .mobile-tab-section ul {
        overflow: visible;
    }
    
    /* Tab-Content ohne eigene Scrollbar */
    .mobile-tab-content {
        overflow: visible;
    }
    
    .mobile-tab-section {
        overflow: visible;
    }
    
    .notes-body {
        flex-direction: column;
    }
    
    .member-image {
        width: 100%;
        height: auto;
        max-height: 300px;
    }
    
    /* Header Row anpassen */
    .diary-header-row {
        flex-direction: column;
        align-items: stretch;
    }
    
    .diary-header-row label {
        width: 100%;
    }
    
    .diary-header-row button {
        width: 100%;
        margin-top: 0.5rem;
    }
}

.dialog-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.dialog-content {
    background: #fff;
    border-radius: 8px;
    padding: 24px;
    max-width: 500px;
    width: 90%;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.dialog-content h3 {
    margin: 0 0 20px 0;
    font-size: 1.2rem;
}

.dialog-body {
    margin-bottom: 20px;
}

.dialog-body label {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
}

.dialog-body .input-field {
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 1rem;
}

.suggestion-info {
    background: #e3f2fd;
    border: 1px solid #90caf9;
    border-radius: 4px;
    padding: 12px;
    margin-top: 16px;
}

.suggestion-info p {
    margin: 4px 0;
}

.dialog-actions {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    flex-wrap: wrap;
}

.dialog-actions button {
    padding: 8px 16px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.9rem;
}

.dialog-actions .btn-primary {
    background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
    color: var(--text-on-primary);
}

.dialog-actions .btn-primary:hover:not(:disabled) {
    opacity: 0.95;
}

.dialog-actions .btn-primary:disabled {
    background: #ccc;
    cursor: not-allowed;
}

.dialog-actions .btn-secondary {
    background: #6c757d;
    color: #fff;
}

.dialog-actions .btn-secondary:hover {
    background: #5a6268;
}

@media (min-width: 769px) {
    .mobile-tabs {
        display: none !important;
    }
    
    .mobile-tab-section {
        display: none !important;
    }
    
    .desktop-sidebar {
        display: block !important;
    }
    
    .column.mobile-tab-content {
        display: block !important;
    }
    
    .mobile-sidebar .desktop-sidebar {
        display: block !important;
    }
}

/* Member Group Select - Chrome Fix */
.member-group-select {
    font-size: 10px !important;
    padding: 2px 4px !important;
    border: 1px solid #ccc !important;
    border-radius: 3px !important;
    background-color: white !important;
    color: #333 !important;
    -webkit-appearance: menulist !important;
    appearance: menulist !important;
}

.member-group-select option {
    background-color: white !important;
    color: #333 !important;
    padding: 4px !important;
}

.member-group-select:focus {
    outline: 2px solid #007bff !important;
    outline-offset: 2px !important;
}

/* Render Container */
.render-container {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 1rem;
    background: #f5f5f5;
    border-radius: 4px;
}
</style>
