<template>
    <div class="schedule-view">
        <ScheduleLayoutShell
            ref="scheduleShell"
            :selected-season-id="selectedSeasonId"
            :show-gallery-button="Boolean(playerSelectionDialog.match)"
            :gallery-loading="galleryLoading"
            :hovered-match="hoveredMatch"
            :filtered-schedule-teams-count="filteredScheduleTeams.length"
            :teams-count="teams.length"
            :matches-count="matches.length"
            :completed-matches-count="completedMatchesCount"
            :pending-matches-count="pendingMatchesCount"
            :next-scheduled-match-label="nextScheduledMatchLabel"
            :team-search-query="teamSearchQuery"
            :overall-schedule-label="$t('schedule.overallSchedule')"
            :adult-schedule-label="$t('schedule.adultSchedule')"
            :selected-league="selectedLeague"
            :filtered-schedule-teams="filteredScheduleTeams"
            :selected-team="selectedTeam"
            :workspace-description="workspaceDescription"
            :active-tab="activeTab"
            :table-count="leagueTable.length"
            :fetching-team-data="fetchingTeamData"
            :fetching-table="fetchingTable"
            @update:selected-season-id="selectedSeasonId = $event"
            @season-change="onSeasonChange"
            @open-import-modal="openImportModal"
            @open-gallery-dialog="openGalleryDialog"
            @update:team-search-query="teamSearchQuery = $event"
            @load-all-matches="loadAllMatches"
            @load-adult-matches="loadAdultMatches"
            @load-team="loadMatchesForTeam"
            @fetch-team-data-manually="fetchTeamDataManually"
            @generate-pdf="generatePDF"
            @fetch-table="fetchTableFromMyTischtennis"
            @update:active-tab="activeTab = $event"
        >
            <template #schedule-panel>
                <div v-if="selectedTeam" class="league-match-scope-card">
                    <div class="league-match-scope-header">
                        <strong>{{ $t('schedule.matchOverviewTitle') }}</strong>
                        <span>{{ $t('schedule.matchOverviewDescription') }}</span>
                    </div>
                    <div class="league-match-scope-controls">
                        <button
                            type="button"
                            class="team-filter-chip"
                            :class="{ active: leagueMatchScope === 'own' }"
                            @click="setLeagueMatchScope('own')"
                        >
                            {{ $t('schedule.ownTeamMatches') }}
                        </button>
                        <button
                            type="button"
                            class="team-filter-chip"
                            :class="{ active: leagueMatchScope === 'all' }"
                            @click="setLeagueMatchScope('all')"
                        >
                            {{ $t('schedule.allLeagueMatches') }}
                        </button>
                        <button
                            type="button"
                            class="team-filter-chip"
                            :class="{ active: leagueMatchScope === 'other' }"
                            @click="setLeagueMatchScope('other')"
                        >
                            {{ $t('schedule.otherTeamMatches') }}
                        </button>
                        <select
                            v-if="leagueMatchScope === 'other'"
                            v-model="selectedComparisonTeamName"
                            class="league-match-scope-select"
                            @change="applyLeagueMatchScope"
                        >
                            <option value="">{{ $t('schedule.selectOtherTeam') }}</option>
                            <option v-for="teamName in leagueTeamOptions" :key="teamName" :value="teamName">
                                {{ teamName }}
                            </option>
                        </select>
                    </div>
                </div>
                <div v-if="matches.length > 0">
                    <table id="schedule-table">
                        <thead>
                            <tr>
                                <th>{{ $t('schedule.date') }}</th>
                                <th>{{ $t('schedule.time') }}</th>
                                <th>{{ $t('schedule.homeTeam') }}</th>
                                <th>{{ $t('schedule.guestTeam') }}</th>
                                <th>{{ $t('schedule.result') }}</th>
                                <th
                                    v-if="selectedLeague === $t('schedule.overallSchedule') || selectedLeague === $t('schedule.adultSchedule')">
                                    {{ $t('schedule.ageClass') }}</th>
                                <th>{{ $t('schedule.code') }}</th>
                                <th>{{ $t('schedule.homePin') }}</th>
                                <th>{{ $t('schedule.guestPin') }}</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="match in matches" :key="match.id" 
                                @mouseover="hoveredMatch = match"
                                @mouseleave="hoveredMatch = null" 
                                @click="openPlayerSelectionDialog(match)"
                                :class="getRowClass(match.date)"
                                style="cursor: pointer;">
                                <td>{{ formatDate(match.date) }}</td>
                                <td>{{ match.time ? match.time.toString().slice(0, 5) + ' ' + $t('common.time') : 'N/A' }}</td>
                                <td :class="{ 'highlighted-club': isClubHighlighted(match.homeTeam?.name) }">
                                    {{ match.homeTeam?.name || 'N/A' }}
                                </td>
                                <td :class="{ 'highlighted-club': isClubHighlighted(match.guestTeam?.name) }">
                                    {{ match.guestTeam?.name || 'N/A' }}
                                </td>
                                <td class="result-cell" :class="getResultClass(match)">
                                    <span v-if="match.isCompleted" class="result-score">
                                        {{ match.homeMatchPoints }}:{{ match.guestMatchPoints }}
                                    </span>
                                    <span v-else class="result-pending">—</span>
                                </td>
                                <td
                                    v-if="selectedLeague === $t('schedule.overallSchedule') || selectedLeague === $t('schedule.adultSchedule')">
                                    {{ match.leagueDetails?.name || 'N/A' }}</td>
                                <td class="code-cell match-report-cell" @click.stop="openMatchReport(match)">
                                    <span v-if="match.code && selectedLeague && selectedLeague !== ''">
                                        <button @click.stop="openMatchReport(match)" class="nuscore-link"
                                            :title="$t('schedule.openMatchReport')">📊</button>
                                        <span class="code-value clickable" @click.stop="copyToClipboard(match.code, $t('schedule.code'), $event)"
                                            :title="$t('schedule.copyCode') + ': ' + match.code">{{ match.code }}</span>
                                    </span>
                                    <span v-else-if="match.code" class="code-value clickable"
                                        @click.stop="copyToClipboard(match.code, $t('schedule.code'), $event)"
                                        :title="$t('schedule.copyCode') + ': ' + match.code">{{ match.code }}</span>
                                    <span v-else class="no-data">-</span>
                                </td>
                                <td class="pin-cell">
                                    <span v-if="match.homePin" class="pin-value clickable"
                                        @click.stop="copyToClipboard(match.homePin, $t('schedule.homePin'), $event)"
                                        :title="$t('schedule.copyHomePin') + ': ' + match.homePin">{{ match.homePin }}</span>
                                    <span v-else class="no-data">-</span>
                                </td>
                                <td class="pin-cell">
                                    <span v-if="match.guestPin" class="pin-value clickable"
                                        @click.stop="copyToClipboard(match.guestPin, $t('schedule.guestPin'), $event)"
                                        :title="$t('schedule.copyGuestPin') + ': ' + match.guestPin">{{ match.guestPin }}</span>
                                    <span v-else class="no-data">-</span>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                <div v-else>
                    <p>{{ $t('schedule.noGames') }}</p>
                </div>
            </template>
            <template #table-panel>
                <div class="table-section">
                    <div class="table-header">
                        <h3>{{ $t('schedule.leagueTable') }}</h3>
                    </div>
                    <div v-if="leagueTable.length > 0">
                        <table id="league-table">
                            <thead>
                                <tr>
                                    <th>{{ $t('schedule.position') }}</th>
                                    <th>{{ $t('schedule.team') }}</th>
                                    <th>{{ $t('schedule.matches') }}</th>
                                    <th>{{ $t('schedule.sets') }}</th>
                                    <th>{{ $t('schedule.points') }}</th>
                                    <th>{{ $t('schedule.balls') }}</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="(team, index) in leagueTable" :key="team.teamId" :class="{ 'our-team': isOurTeam(team.teamName) }">
                                    <td>{{ index + 1 }}</td>
                                    <td>{{ team.teamName }}</td>
                                    <td>{{ team.matchPoints }}</td>
                                    <td>{{ team.setsWon }}:{{ team.setsLost }}</td>
                                    <td>{{ team.tablePoints }}</td>
                                    <td>{{ team.pointRatio }}</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                    <div v-else>
                        <p>{{ $t('schedule.noTableData') }}</p>
                    </div>
                </div>
            </template>
        </ScheduleLayoutShell>

        <!-- Import Modal -->
        <CsvImportDialog v-model="showImportModal" @import="handleCsvImport" @close="closeImportModal" />
    </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)" />
    
    <!-- Mitglieder-Galerie Dialog -->
    <BaseDialog
        v-model="showGalleryDialog"
        :title="$t('schedule.galleryTitle')"
        size="large"
        :close-on-overlay="true"
        @close="closeGalleryDialog"
    >
        <div class="gallery-dialog-content">
            <div class="gallery-controls">
                <label for="gallery-size">{{ $t('schedule.imageSize') }}:</label>
                <select id="gallery-size" v-model="gallerySize" @change="loadGalleryMembers" :disabled="galleryLoading">
                    <option :value="100">100x100 px</option>
                    <option :value="150">150x150 px</option>
                    <option :value="200">200x200 px</option>
                </select>
            </div>
            <div v-if="galleryLoading" class="gallery-loading">{{ $t('schedule.galleryLoading') }}</div>
            <div v-else-if="galleryMembers.length > 0" class="gallery-members-grid">
                <div 
                    v-for="member in galleryMembers" 
                    :key="member.memberId"
                    class="gallery-member-item"
                    :class="{ 'is-ready': isMemberReady(member.memberId) }"
                    @click="toggleMemberReady(member)"
                >
                    <img 
                        :src="getMemberImageUrl(member.memberId)" 
                        :alt="member.fullName"
                        class="gallery-member-image"
                    />
                    <div class="gallery-member-name">{{ member.fullName }}</div>
                </div>
            </div>
            <div v-else class="gallery-error">
                {{ galleryError || $t('schedule.noMembersWithImages') }}
            </div>
        </div>
    </BaseDialog>

    <!-- Player Selection Dialog -->
    <BaseDialog 
        v-model="playerSelectionDialog.isOpen" 
        :title="`${$t('schedule.playerSelection')} - ${playerSelectionDialog.match?.homeTeam?.name || ''} ${$t('schedule.vs')} ${playerSelectionDialog.match?.guestTeam?.name || ''}`"
        @close="closePlayerSelectionDialog"
        :max-width="800"
    >
        <div v-if="playerSelectionDialog.loading" class="loading-state">
            {{ $t('schedule.loadingMembers') }}
        </div>
        
        <div v-else class="player-selection-content">
            <div class="match-info">
                <p><strong>{{ $t('schedule.date') }}:</strong> {{ formatDate(playerSelectionDialog.match?.date) }}</p>
                <p><strong>{{ $t('schedule.time') }}:</strong> {{ playerSelectionDialog.match?.time ? playerSelectionDialog.match.time.toString().slice(0, 5) + ' ' + $t('common.time') : 'N/A' }}</p>
            </div>
            
            <div class="player-list">
                <table class="player-selection-table">
                    <thead>
                        <tr>
                            <th>{{ $t('schedule.player') }}</th>
                            <th>{{ $t('schedule.ready') }}</th>
                            <th>{{ $t('schedule.planned') }}</th>
                            <th>{{ $t('schedule.played') }}</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="member in playerSelectionDialog.members" :key="member.id">
                            <td class="player-name">
                                {{ member.firstName }} {{ member.lastName }}
                            </td>
                            <td class="checkbox-cell">
                                <input 
                                    type="checkbox" 
                                    :checked="member.isReady"
                                    @change="togglePlayerReady(member)"
                                />
                            </td>
                            <td class="checkbox-cell">
                                <input 
                                    type="checkbox" 
                                    :checked="member.isPlanned"
                                    @change="togglePlayerPlanned(member)"
                                />
                            </td>
                            <td class="checkbox-cell">
                                <input 
                                    type="checkbox" 
                                    :checked="member.hasPlayed"
                                    @change="togglePlayerPlayed(member)"
                                />
                            </td>
                        </tr>
                    </tbody>
                </table>
                
                <div v-if="playerSelectionDialog.members.length === 0" class="no-members">
                    {{ $t('schedule.noActiveMembers') }}
                </div>
            </div>
            
            <div class="dialog-actions">
                <button @click="savePlayerSelection" class="btn-save">{{ $t('schedule.save') }}</button>
                <button @click="closePlayerSelectionDialog" class="btn-cancel">{{ $t('schedule.cancel') }}</button>
            </div>
        </div>
    </BaseDialog>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';
import apiClient from '../apiClient.js';
import PDFGenerator from '../components/PDFGenerator.js';
import { getSafeErrorMessage } from '../utils/errorMessages.js';
import SeasonSelector from '../components/SeasonSelector.vue';

import InfoDialog from '../components/InfoDialog.vue';
import ConfirmDialog from '../components/ConfirmDialog.vue';
import BaseDialog from '../components/BaseDialog.vue';
import CsvImportDialog from '../components/CsvImportDialog.vue';
import ScheduleLayoutShell from '../components/schedule/ScheduleLayoutShell.vue';
import {
    connectSocket,
    disconnectSocket,
    onScheduleMatchUpdated,
    offScheduleMatchUpdated,
    onMatchReportSubmitted,
    offMatchReportSubmitted
} from '../services/socketService.js';
export default {
    name: 'ScheduleView',
    components: {
        SeasonSelector,
        InfoDialog,
        ConfirmDialog,
        BaseDialog,
        CsvImportDialog,
        ScheduleLayoutShell
    },
    computed: {
        ...mapGetters(['isAuthenticated', 'currentClub', 'clubs', 'currentClubName']),
        filteredScheduleTeams() {
            const query = this.teamSearchQuery.trim().toLowerCase();
            if (!query) {
                return this.teams;
            }
            return this.teams.filter((team) => {
                const teamName = team.name?.toLowerCase() || '';
                const leagueName = team.league?.name?.toLowerCase() || '';
                return teamName.includes(query) || leagueName.includes(query);
            });
        },
        completedMatchesCount() {
            return this.matches.filter(match => match.isCompleted).length;
        },
        pendingMatchesCount() {
            return this.matches.length - this.completedMatchesCount;
        },
        nextScheduledMatchLabel() {
            const today = new Date();
            today.setHours(0, 0, 0, 0);
            const nextMatch = this.matches
                .filter(match => match.date)
                .map(match => ({ ...match, _date: new Date(match.date) }))
                .filter(match => !isNaN(match._date.getTime()) && match._date >= today)
                .sort((a, b) => a._date - b._date)[0];
            return nextMatch ? this.formatDate(nextMatch.date) : '';
        },
        workspaceDescription() {
            if (!this.selectedLeague) return '';
            return this.activeTab === 'table'
                ? this.$t('schedule.workspaceTableDescription', { count: this.leagueTable.length })
                : this.$t('schedule.workspaceScheduleDescription', {
                    matches: this.matches.length,
                    completed: this.completedMatchesCount,
                    pending: this.pendingMatchesCount
                });
        },
        leagueTeamOptions() {
            const ownTeamName = this.selectedTeam?.name;
            return Array.from(new Set(this.allLeagueMatches.flatMap(match => [
                match.homeTeam?.name,
                match.guestTeam?.name
            ].filter(Boolean))))
                .filter(teamName => teamName !== ownTeamName)
                .sort((a, b) => a.localeCompare(b));
        },
    },
    watch: {
        currentClub: {
            immediate: true,
            handler(newVal) {
                offScheduleMatchUpdated(this.handleScheduleMatchUpdated);
                offMatchReportSubmitted(this.handleMatchReportSubmitted);
                disconnectSocket();
                if (newVal) {
                    connectSocket(newVal);
                    onScheduleMatchUpdated(this.handleScheduleMatchUpdated);
                    onMatchReportSubmitted(this.handleMatchReportSubmitted);
                }
            }
        },
    },
    data() {
        return {
            // Dialog States
            infoDialog: {
                isOpen: false,
                title: '',
                message: '',
                details: '',
                type: 'info'
            },
            confirmDialog: {
                isOpen: false,
                title: '',
                message: '',
                details: '',
                type: 'info',
                resolveCallback: null
            },
            showImportModal: false,
            selectedFile: null,
            teams: [],
            matches: [],
            selectedLeague: '',
            selectedTeam: null,
            hoveredMatch: null,
            selectedSeasonId: null,
            currentSeason: null,
            activeTab: 'schedule',
            leagueTable: [],
            fetchingTable: false,
            fetchingTeamData: false,
            teamSearchQuery: '',
            ownLeagueMatches: [],
            allLeagueMatches: [],
            leagueMatchScope: 'own',
            selectedComparisonTeamName: '',
            
            // Player Selection Dialog
            playerSelectionDialog: {
                isOpen: false,
                match: null,
                members: [],
                loading: false
            },
            // Gallery Dialog
            showGalleryDialog: false,
            galleryLoading: false,
            galleryMembers: [],
            galleryError: '',
            gallerySize: 200,
        };
    },
    methods: {
        getResultClass(match) {
            if (!match.isCompleted) {
                return '';
            }

            const home = Number(match.homeMatchPoints);
            const guest = Number(match.guestMatchPoints);

            // Beteiligung unseres Vereins prüfen
            const isOurTeamHome = this.isOurTeam(match.homeTeam?.name);
            const isOurTeamGuest = this.isOurTeam(match.guestTeam?.name);
            const isOurMatch = isOurTeamHome || isOurTeamGuest;

            // Unentschieden: Nur gelb markieren, wenn unser Team beteiligt ist
            if (!isNaN(home) && !isNaN(guest) && home === guest) {
                return isOurMatch ? 'completed draw' : 'completed';
            }

            if (isOurTeamHome) {
                return home > guest ? 'completed won' : 'completed lost';
            } else if (isOurTeamGuest) {
                return guest > home ? 'completed won' : 'completed lost';
            }

            return 'completed';
        },

        isOurTeam(teamName) {
            if (!teamName || !this.currentClubName) {
                return false;
            }
            // Check if team name starts with our club name
            return teamName.startsWith(this.currentClubName);
        },

        // 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 openPlayerSelectionDialog(match) {
            this.playerSelectionDialog.match = match;
            this.playerSelectionDialog.isOpen = true;
            this.playerSelectionDialog.loading = true;
            
            try {
                const normalizePlayersList = (value) => {
                    if (Array.isArray(value)) return value;
                    if (typeof value === 'string') {
                        try {
                            const parsed = JSON.parse(value);
                            return Array.isArray(parsed) ? parsed : [];
                        } catch (e) {
                            return [];
                        }
                    }
                    return [];
                };
                const readyIds = normalizePlayersList(match.playersReady);
                const plannedIds = normalizePlayersList(match.playersPlanned);
                const playedIds = normalizePlayersList(match.playersPlayed);

                // Fetch members for the current club
                const response = await apiClient.get(`/clubmembers/get/${this.currentClub}/true`);
                
                const allMembers = response.data;
                
                // Filter members by age class if league has age class info
                // For now, show all active members
                const activeMembers = allMembers.filter(m => m.active);
                
                this.playerSelectionDialog.members = activeMembers.map(m => ({
                    ...m,
                    isReady: readyIds.includes(m.id) || false,
                    isPlanned: plannedIds.includes(m.id) || false,
                    hasPlayed: playedIds.includes(m.id) || false
                }));
                    
            } catch (error) {
                console.error('Error loading members:', error);
                console.error('Error details:', error.response?.data);
                await this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingMembers'), getSafeErrorMessage(error), 'error');
            } finally {
                this.playerSelectionDialog.loading = false;
            }
        },
        
        closePlayerSelectionDialog() {
            this.playerSelectionDialog.isOpen = false;
            this.playerSelectionDialog.match = null;
            this.playerSelectionDialog.members = [];
        },
        
        togglePlayerReady(member) {
            member.isReady = !member.isReady;
        },
        
        togglePlayerPlanned(member) {
            member.isPlanned = !member.isPlanned;
        },
        
        togglePlayerPlayed(member) {
            member.hasPlayed = !member.hasPlayed;
        },
        
        async savePlayerSelection(closeDialog = true) {
            const match = this.playerSelectionDialog.match;
            if (!match) return;
            
            const playersReady = this.playerSelectionDialog.members
                .filter(m => m.isReady)
                .map(m => m.id);
            const playersPlanned = this.playerSelectionDialog.members
                .filter(m => m.isPlanned)
                .map(m => m.id);
            const playersPlayed = this.playerSelectionDialog.members
                .filter(m => m.hasPlayed)
                .map(m => m.id);
            
            console.log('[savePlayerSelection] Saving players:', { playersReady, playersPlanned, playersPlayed, matchId: match.id });
            
            try {
                const response = await apiClient.patch(`/matches/${match.id}/players`, {
                    clubId: this.currentClub,
                    playersReady,
                    playersPlanned,
                    playersPlayed
                });
                if (response.status >= 400) {
                    throw new Error(response?.data?.error || 'Failed to update match players');
                }
                console.log('[savePlayerSelection] API response:', response);
                
                // Update local match data
                match.playersReady = playersReady;
                match.playersPlanned = playersPlanned;
                match.playersPlayed = playersPlayed;
                
                // Update all members in the list to reflect the current state
                this.playerSelectionDialog.members.forEach(m => {
                    m.isReady = playersReady.includes(m.id);
                    m.isPlanned = playersPlanned.includes(m.id);
                    m.hasPlayed = playersPlayed.includes(m.id);
                });
                
                if (closeDialog) {
                    await this.showInfo(this.$t('messages.success'), this.$t('schedule.playerSelectionSaved'), '', 'success');
                    this.closePlayerSelectionDialog();
                }
            } catch (error) {
                console.error('Error saving player selection:', error);
                await this.showInfo(this.$t('messages.error'), this.$t('schedule.errorSavingPlayerSelection'), '', 'error');
            }
        },

        // Gallery Methods
        async openGalleryDialog() {
            if (!this.playerSelectionDialog.match) {
                await this.showInfo(this.$t('messages.info'), this.$t('schedule.pleaseSelectGame'), '', 'info');
                return;
            }
            this.showGalleryDialog = true;
            await this.loadGalleryMembers();
        },

        async loadGalleryMembers() {
            if (!this.currentClub || this.galleryLoading) {
                return;
            }
            this.galleryLoading = true;
            this.galleryError = '';
            try {
                const response = await apiClient.get(`/clubmembers/gallery/${this.currentClub}?format=json&size=${this.gallerySize}`);
                this.galleryMembers = response.data.members || [];
            } catch (error) {
                console.error('Fehler beim Laden der Galerie:', error);
                this.galleryError = error?.response?.data?.error || this.$t('schedule.errorLoadingGallery');
                this.galleryMembers = [];
            } finally {
                this.galleryLoading = false;
            }
        },

        closeGalleryDialog() {
            this.showGalleryDialog = false;
            this.galleryMembers = [];
        },

        getMemberImageUrl(memberId) {
            const token = this.$store.getters.token;
            const backendBaseUrl = import.meta.env.VITE_BACKEND || 'http://localhost:3005';
            // Get primary image (latest will be handled by backend)
            return `${backendBaseUrl}/api/clubmembers/image/${this.currentClub}/${memberId}?authcode=${token}`;
        },

        isMemberReady(memberId) {
            const match = this.playerSelectionDialog.match;
            if (!match || !match.playersReady) {
                return false;
            }
            return match.playersReady.includes(memberId);
        },

        async toggleMemberReady(member) {
            console.log('[toggleMemberReady] Called with member:', member);
            const match = this.playerSelectionDialog.match;
            if (!match) {
                console.error('[toggleMemberReady] No match selected');
                return;
            }
            console.log('[toggleMemberReady] Match:', match.id);

            // Find member in playerSelectionDialog.members
            let memberInList = this.playerSelectionDialog.members.find(m => m.id === member.memberId);
            if (!memberInList) {
                // Member not in list yet, add it
                try {
                    const response = await apiClient.get(`/clubmembers/get/${this.currentClub}/true`);
                    const allMembers = response.data;
                    const foundMember = allMembers.find(m => m.id === member.memberId);
                    if (foundMember) {
                        // Check if member is already marked as ready
                        const isCurrentlyReady = match.playersReady?.includes(member.memberId) || false;
                        memberInList = {
                            ...foundMember,
                            isReady: isCurrentlyReady,
                            isPlanned: match.playersPlanned?.includes(member.memberId) || false,
                            hasPlayed: match.playersPlayed?.includes(member.memberId) || false
                        };
                        this.playerSelectionDialog.members.push(memberInList);
                    } else {
                        console.error('Member not found:', member.memberId);
                        return;
                    }
                } catch (error) {
                    console.error('Error loading member:', error);
                    return;
                }
            }

            // Toggle ready status
            const wasReady = memberInList.isReady;
            memberInList.isReady = !wasReady;

            // Update match.playersReady immediately
            if (!match.playersReady) {
                match.playersReady = [];
            }
            const index = match.playersReady.indexOf(member.memberId);
            if (wasReady && index > -1) {
                match.playersReady.splice(index, 1);
            } else if (!wasReady && index === -1) {
                match.playersReady.push(member.memberId);
            }

            // Auto-save (don't close dialog if it's open)
            console.log('[toggleMemberReady] Calling savePlayerSelection');
            await this.savePlayerSelection(false);
            console.log('[toggleMemberReady] savePlayerSelection completed');
        },

        ...mapActions(['openDialog']),
        openImportModal() {
            this.showImportModal = true;
        },
        closeImportModal() {
            this.showImportModal = false;
            this.selectedFile = null;
        },
        handleCsvImport(file) {
            this.selectedFile = file;
            this.importCSV();
        },
        async importCSV() {
            if (!this.selectedFile) return;

            const formData = new FormData();
            formData.append('file', this.selectedFile);
            formData.append('clubId', this.currentClub);

            try {
                await apiClient.post('/matches/import', formData, {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    }
                });
                this.showInfo(this.$t('messages.success'), this.$t('schedule.scheduleImportSuccess'), '', 'success');
                this.closeImportModal();
                this.loadTeams();
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorImportingCSV'), '', 'error');
            }
        },
        // Sortierfunktion für Ligen
        sortLeagues(leagues) {
            if (!Array.isArray(leagues)) {
                return [];
            }
            // Ligen-Priorität
            const leagueOrder = [
                '1. Bundesliga',
                '2. Bundesliga',
                '3. Bundesliga',
                'Regionalliga',
                'Oberliga',
                'Verbandsliga (Hessen)',
                'Bezirksoberliga',
                'Bezirksliga',
                'Bezirksklasse',
                'Kreisliga',
                '1. Kreisklasse',
                '2. Kreisklasse',
                '3. Kreisklasse',
            ];

            // Hilfsfunktionen
            function getLeagueIndex(name) {
                for (let i = 0; i < leagueOrder.length; i++) {
                    if (name.includes(leagueOrder[i])) return i;
                }
                return leagueOrder.length;
            }
            function parseYouth(name) {
                // Gibt {type: 'J'|'M'|'Jugend'|null, age: Zahl|null} zurück
                const m = name.match(/([JM])(\d{1,2})/i);
                if (m) return { type: m[1].toUpperCase(), age: parseInt(m[2]) };
                if (/jugend/i.test(name)) return { type: 'Jugend', age: null };
                return { type: null, age: null };
            }

            // Sortierlogik
            return leagues.slice().sort((a, b) => {
                const ya = parseYouth(a.name);
                const yb = parseYouth(b.name);
                // Erwachsene zuerst
                if (!ya.type && yb.type) return -1;
                if (ya.type && !yb.type) return 1;
                if (!ya.type && !yb.type) {
                    // Beide Erwachsene: nach Liga
                    return getLeagueIndex(a.name) - getLeagueIndex(b.name);
                }
                // Beide Jugend: erst nach Alter aufsteigend (älteste unten), dann J vor M vor "Jugend", dann Liga
                // "Jugend" ohne Zahl ist die jüngste Jugendklasse
                if (ya.age !== yb.age) {
                    if (ya.age === null) return -1;
                    if (yb.age === null) return 1;
                    return ya.age - yb.age;
                }
                // Reihenfolge: J < M < Jugend
                const typeOrder = { 'J': 0, 'M': 1, 'Jugend': 2 };
                if (ya.type !== yb.type) return (typeOrder[ya.type] || 2) - (typeOrder[yb.type] || 2);
                return getLeagueIndex(a.name) - getLeagueIndex(b.name);
            });
        },

        async loadTeams() {
            try {
                const clubId = this.currentClub;
                const seasonParam = this.selectedSeasonId ? `?seasonid=${this.selectedSeasonId}` : '';
                const response = await apiClient.get(`/club-teams/club/${clubId}${seasonParam}`);
                const teams = response.data.filter(team => !!team.league);

                const uniqueLeaguesMap = new Map();
                teams.forEach(team => {
                    if (team.league && !uniqueLeaguesMap.has(team.league.id)) {
                        uniqueLeaguesMap.set(team.league.id, team.league);
                    }
                });
                const sortedLeagues = this.sortLeagues(Array.from(uniqueLeaguesMap.values()));
                const leagueOrder = sortedLeagues.map(l => l.id);

                this.teams = teams.sort((a, b) => {
                    const idxA = leagueOrder.indexOf(a.league.id);
                    const idxB = leagueOrder.indexOf(b.league.id);
                    if (idxA !== idxB) return idxA - idxB;
                    return a.name.localeCompare(b.name);
                });

                if (!this.selectedLeague && this.teams.length > 0) {
                    await this.loadMatchesForSpecificTeam(this.teams[0], { resetScope: true });
                }
            } catch (error) {
                console.error('ScheduleView: Error loading teams:', error);
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingTeams'), '', 'error');
            }
        },
        onSeasonChange(season) {
            this.currentSeason = season;
            this.loadTeams();
            // Leere die aktuellen Matches, da sie für eine andere Saison sind
            this.matches = [];
            this.selectedLeague = '';
            this.selectedTeam = null;
        },
        async loadMatchesForTeam(team) {
            await this.loadMatchesForSpecificTeam(team, { resetScope: true });
        },
        async loadMatchesForSpecificTeam(team, { resetScope = false } = {}) {
            if (!team || !team.league) {
                this.showInfo(this.$t('messages.warning'), this.$t('schedule.noLeagueForTeam'), '', 'warning');
                return;
            }
            this.selectedTeam = team;
            this.selectedLeague = `${team.name}${team.league?.name ? ` (${team.league.name})` : ''}`;
            this.activeTab = 'schedule';
            if (resetScope) {
                this.leagueMatchScope = 'own';
                this.selectedComparisonTeamName = '';
            }
            try {
                const ownResponse = await apiClient.get(`/matches/leagues/${this.currentClub}/matches/${team.league.id}`);
                this.ownLeagueMatches = ownResponse.data;
                await this.loadLeagueMatches(team.league.id);
                this.applyLeagueMatchScope();
                // Lade auch die Tabellendaten für diese Liga
                await this.loadLeagueTable(team.league.id);
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingMatches'), '', 'error');
                this.matches = [];
                this.ownLeagueMatches = [];
                this.allLeagueMatches = [];
            }
        },
        async loadLeagueMatches(leagueId) {
            const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches/${leagueId}?scope=all`);
            this.allLeagueMatches = response.data;
        },
        applyLeagueMatchScope() {
            if (!this.selectedTeam) {
                return;
            }
            const ownTeamName = this.selectedTeam.name;
            if (this.leagueMatchScope === 'all') {
                this.matches = this.allLeagueMatches;
                return;
            }
            if (this.leagueMatchScope === 'other') {
                if (!this.selectedComparisonTeamName && this.leagueTeamOptions.length > 0) {
                    this.selectedComparisonTeamName = this.leagueTeamOptions[0];
                }
                this.matches = this.selectedComparisonTeamName
                    ? this.allLeagueMatches.filter(match =>
                        match.homeTeam?.name === this.selectedComparisonTeamName ||
                        match.guestTeam?.name === this.selectedComparisonTeamName
                    )
                    : [];
                return;
            }
            this.matches = this.ownLeagueMatches.length > 0
                ? this.ownLeagueMatches
                : this.allLeagueMatches.filter(match =>
                    match.homeTeam?.name === ownTeamName || match.guestTeam?.name === ownTeamName
                );
        },
        setLeagueMatchScope(scope) {
            this.leagueMatchScope = scope;
            if (scope !== 'other') {
                this.selectedComparisonTeamName = '';
            }
            this.applyLeagueMatchScope();
        },
        async loadAllMatches() {
            this.selectedLeague = this.$t('schedule.overallSchedule');
            this.selectedTeam = null;
            this.ownLeagueMatches = [];
            this.allLeagueMatches = [];
            this.leagueMatchScope = 'own';
            this.selectedComparisonTeamName = '';
            try {
                const seasonParam = this.selectedSeasonId ? `?seasonid=${this.selectedSeasonId}` : '';
                const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches${seasonParam}`);
                this.matches = response.data;
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingOverallSchedule'), '', 'error');
                this.matches = [];
            }
        },
        async loadAdultMatches() {
            this.selectedLeague = this.$t('schedule.adultSchedule');
            this.selectedTeam = null;
            this.ownLeagueMatches = [];
            this.allLeagueMatches = [];
            this.leagueMatchScope = 'own';
            this.selectedComparisonTeamName = '';
            try {
                const seasonParam = this.selectedSeasonId ? `?seasonid=${this.selectedSeasonId}` : '';
                const response = await apiClient.get(`/matches/leagues/${this.currentClub}/matches${seasonParam}`);
                // Filtere nur Erwachsenenligen (keine Jugendligen)
                const allMatches = response.data;
                this.matches = allMatches.filter(match => {
                    const leagueName = match.leagueDetails?.name || '';
                    // Prüfe, ob es eine Jugendliga ist (J, M, Jugend im Namen)
                    const isYouth = /[JM]\d|jugend/i.test(leagueName);
                    return !isYouth;
                });
            } catch (error) {
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingAdultSchedule'), '', 'error');
                this.matches = [];
            }
        },
        formatDate(date) {
            if (!date) return 'N/A';
            const d = new Date(date);
            if (isNaN(d.getTime())) return 'N/A';
            const weekdays = ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'];
            const wd = weekdays[d.getDay()];
            const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
            const day = d.toLocaleDateString('de-DE', options);
            return `${wd} ${day}`;
        },
        isClubHighlighted(teamName) {
            if (!teamName) return false;
            const clubName = this.currentClubName;
            return Boolean(clubName && teamName.includes(clubName));
        },
        getCurrentClubName() {
            const clubIdNum = Number(this.currentClub);
            const club = this.clubs.find(c => c.id === clubIdNum);
            return club ? club.name : '';
        },
        async generatePDF() {
            const element = this.$refs.scheduleShell?.$el || this.$refs.scheduleContainer;
            const highlightName = this.getCurrentClubName();
            if (element) {
                const pdfGen = new PDFGenerator(20, 10, this.$t);
                pdfGen.addTitle(`${this.$t('schedule.gamesFor')} ${highlightName} ${this.$t('common.in')} ${this.selectedLeague}`);
                
                // Bestimme die auszuschließenden Spalten
                // Spaltenstruktur: Datum, Uhrzeit, Heimmannschaft, Gastmannschaft, Ergebnis, [Altersklasse], Code, Heim-PIN, Gast-PIN
                const hasAgeClass = this.selectedLeague === this.$t('schedule.overallSchedule') || this.selectedLeague === this.$t('schedule.adultSchedule');
                let excludeColumns;
                if (hasAgeClass) {
                    // Mit Altersklasse: Ergebnis=4, Code=6, Heim-PIN=7, Gast-PIN=8
                    excludeColumns = [4, 6, 7, 8];
                } else {
                    // Ohne Altersklasse: Ergebnis=4, Code=5, Heim-PIN=6, Gast-PIN=7
                    excludeColumns = [4, 5, 6, 7];
                }
                
                pdfGen.addTable('schedule-table', highlightName, excludeColumns);
                pdfGen.addNewPage();
                const uniqueLocations = this.getUniqueLocations();
                uniqueLocations.forEach((addressLines, clubName) => {
                    if (!clubName.includes(highlightName)) {
                        pdfGen.addAddress(clubName, addressLines);
                    }
                });

                pdfGen.save(this.$t('schedule.schedulePDF'));
            } else {
                await this.showInfo(this.$t('messages.info'), this.$t('schedule.noMatchesForPDF'), '', 'info');
            }
        },
        getUniqueLocations() {
            const uniqueLocations = new Map();
            this.matches.forEach(match => {
                if (!match.location || !match.homeTeam) return;
                const location = match.location;
                const clubName = match.homeTeam.name;
                const addressLines = [
                    location.name || 'N/A',
                    location.address || 'N/A',
                    `${location.zip || ''} ${location.city || ''}`.trim()
                ];
                const addressKey = addressLines.join('; ');
                if (!uniqueLocations.has(addressKey)) {
                    uniqueLocations.set(clubName, addressLines);
                }
            });

            return uniqueLocations;
        },
        getRowClass(matchDate) {
            if (!matchDate) return '';

            const today = new Date();
            const match = new Date(matchDate);

            // Setze die Zeit auf Mitternacht für genaue Datumsvergleiche
            today.setHours(0, 0, 0, 0);
            match.setHours(0, 0, 0, 0);

            // Berechne die Differenz in Tagen
            const diffTime = match.getTime() - today.getTime();
            const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

            if (diffDays === 0) {
                return 'match-today'; // Heute - gelb
            } else if (diffDays > 0 && diffDays <= 7) {
                return 'match-next-week'; // Nächste Woche - hellblau
            }

            return ''; // Keine besondere Farbe
        },
        async copyToClipboard(text, type, event) {
            try {
                await navigator.clipboard.writeText(text);
                // Zeige eine kurze Bestätigung
                this.showCopyFeedback(event.target, text);
            } catch (err) {
                console.error('Fehler beim Kopieren:', err);
                // Fallback für ältere Browser
                const textArea = document.createElement('textarea');
                textArea.value = text;
                document.body.appendChild(textArea);
                textArea.select();
                document.execCommand('copy');
                document.body.removeChild(textArea);
                
                // Auch für Fallback eine Bestätigung zeigen
                this.showCopyFeedback(event.target, text);
            }
        },
        
        showCopyFeedback(element, originalText) {
            // Speichere die ursprünglichen Styles
            const originalStyles = {
                textContent: element.textContent,
                color: element.style.color,
                backgroundColor: element.style.backgroundColor,
                borderColor: element.style.borderColor,
                fontWeight: element.style.fontWeight
            };
            
            // Ändere das Element zu einem grünen Häkchen
            element.textContent = '✓';
            element.style.color = '#4CAF50';
            element.style.backgroundColor = '#e8f5e8';
            element.style.borderColor = '#4CAF50';
            element.style.fontWeight = 'bold';
            element.style.fontSize = '1.2em';
            
            // Nach 1.5 Sekunden zurücksetzen
            setTimeout(() => {
                element.textContent = originalStyles.textContent;
                element.style.color = originalStyles.color;
                element.style.backgroundColor = originalStyles.backgroundColor;
                element.style.borderColor = originalStyles.borderColor;
                element.style.fontWeight = originalStyles.fontWeight;
                element.style.fontSize = '';
            }, 1500);
        },

        openMatchReport(match) {
            if (!match || !match.code) {
                return;
            }
            const title = `${match.homeTeam?.name || 'N/A'} vs ${match.guestTeam?.name || 'N/A'} - ${this.selectedLeague}`;
            this.openDialog({
                title,
                component: 'MatchReportApiDialog',
                props: {
                    match
                }
            });
        },
        
        async loadLeagueTable(leagueId) {
            try {
                const response = await apiClient.get(`/matches/leagues/${this.currentClub}/table/${leagueId}`);
                this.leagueTable = response.data;
            } catch (error) {
                console.error('ScheduleView: Error loading league table:', error);
                this.leagueTable = [];
            }
        },
        
        async fetchTableFromMyTischtennis() {
            if (!this.selectedTeam || !this.selectedTeam.league || this.selectedLeague === this.$t('schedule.overallSchedule') || this.selectedLeague === this.$t('schedule.adultSchedule')) {
                this.showInfo(this.$t('messages.info'), this.$t('schedule.selectSpecificLeague'), '', 'info');
                return;
            }
            
            this.fetchingTable = true;
            try {
                const leagueId = this.selectedTeam.league.id;
                const response = await apiClient.post(`/matches/leagues/${this.currentClub}/table/${leagueId}/fetch`);
                this.leagueTable = response.data.data;
                this.showInfo(this.$t('messages.success'), this.$t('schedule.tableDataLoaded'), '', 'success');
            } catch (error) {
                console.error('ScheduleView: Error fetching table from MyTischtennis:', error);
                this.showInfo(this.$t('messages.error'), this.$t('schedule.errorLoadingTable'), getSafeErrorMessage(error), 'error');
            } finally {
                this.fetchingTable = false;
            }
        },
        async fetchTeamDataManually() {
            if (!this.selectedTeam?.id) {
                return;
            }

            this.fetchingTeamData = true;
            try {
                const response = await apiClient.post('/scheduler/match_results', {
                    clubTeamId: this.selectedTeam.id
                });
                const result = response?.data;

                if (!result?.success) {
                    throw new Error(result?.error || result?.message || this.$t('schedule.fetchDataFailed'));
                }

                await this.loadMatchesForSpecificTeam(this.selectedTeam);
                if (this.selectedTeam?.league?.id) {
                    await this.loadLeagueTable(this.selectedTeam.league.id);
                }

                const fetchedCount =
                    result?.result?.totalFetched ??
                    result?.result?.fetchedCount ??
                    result?.result?.data?.fetchedCount ??
                    0;

                await this.showInfo(
                    this.$t('messages.success'),
                    this.$t('schedule.teamDataFetched'),
                    this.$t('schedule.teamDataFetchedDetails', {
                        team: this.selectedTeam.name,
                        count: fetchedCount
                    }),
                    'success'
                );
            } catch (error) {
                await this.showInfo(
                    this.$t('messages.error'),
                    getSafeErrorMessage(error, this.$t('schedule.fetchDataFailed')),
                    '',
                    'error'
                );
            } finally {
                this.fetchingTeamData = false;
            }
        },

        refreshScheduleData() {
            if (!this.selectedLeague) return;
            if (this.selectedTeam) {
                this.loadMatchesForSpecificTeam(this.selectedTeam);
            } else if (this.selectedLeague === this.$t('schedule.overallSchedule')) {
                this.loadAllMatches();
            } else if (this.selectedLeague === this.$t('schedule.adultSchedule')) {
                this.loadAdultMatches();
            }
        },

        handleScheduleMatchUpdated(payload) {
            if (payload?.match && payload.matchId != null) {
                const idx = this.matches.findIndex(m => m.id === payload.matchId);
                if (idx !== -1) {
                    this.matches.splice(idx, 1, payload.match);
                    return;
                }
            }
            this.refreshScheduleData();
        },

        handleMatchReportSubmitted(payload) {
            if (payload?.matchData && (payload.matchCode != null || payload.matchData?.gameCode || payload.matchData?.code)) {
                const code = String(payload.matchCode ?? payload.matchData?.gameCode ?? payload.matchData?.code ?? '');
                const idx = this.matches.findIndex(m => m.code === code);
                if (idx !== -1) {
                    const m = { ...this.matches[idx] };
                    const d = payload.matchData;
                    if (d.homeMatches != null) m.homeMatchPoints = d.homeMatches;
                    if (d.guestMatches != null) m.guestMatchPoints = d.guestMatches;
                    if (typeof d.isCompleted === 'boolean') m.isCompleted = d.isCompleted;
                    if (d.startDate) m.startDate = d.startDate;
                    if (d.endDate) m.endDate = d.endDate;
                    this.matches.splice(idx, 1, m);
                    return;
                }
            }
            this.refreshScheduleData();
        },
    },
    async created() {
        // Teams werden geladen, sobald eine Saison ausgewählt ist
        // Die SeasonSelector-Komponente wählt automatisch die aktuelle Saison aus
        // und ruft anschließend onSeasonChange auf, was loadTeams() ausführt
        this.loadTeams();
    },
    beforeUnmount() {
        offScheduleMatchUpdated(this.handleScheduleMatchUpdated);
        offMatchReportSubmitted(this.handleMatchReportSubmitted);
        disconnectSocket();
    },
};
</script>

<style scoped>
.output {
    display: flex;
}

.output ul {
    flex: 0;
    margin-right: 20px;
}

.flex-item {
    flex: 1;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 20px;
}

table,
th,
td {
    border: 1px solid #ddd;
    padding: 8px;
}

th {
    background-color: #f2f2f2;
    text-align: left;
}

tr:hover {
    background-color: #f5f5f5;
}

th,
td {
    white-space: nowrap;
}

.highlighted-club {
    font-weight: 600;
    color: #2b7cff;
}

.result-cell {
    text-align: center;
    font-weight: 600;
}

.result-score {
    font-size: 1.1em;
}

.result-pending {
    color: var(--text-muted);
    font-style: italic;
}

.result-cell.completed.won {
    background-color: #f0f9f0;
}

.result-cell.completed.won .result-score {
    color: #28a745;
}

.result-cell.completed.lost {
    background-color: #fff5f5;
}

.result-cell.completed.lost .result-score {
    color: #dc3545;
}

/* Unentschieden: gelb hinterlegen (wie .row-test in MembersView) */
.result-cell.completed.draw {
    background-color: #fff3cd;
}

.result-cell.completed.draw .result-score {
    color: #856404;
}

.hover-info {
    margin-top: 10px;
    background-color: #eef;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    max-width: 300px;
    position: fixed;
    top: 16em;
    left: 14em;
}

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

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

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

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

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

li {
    white-space: nowrap;
    color: #45a049;
    cursor: pointer;
}

.special-link {
    font-weight: bold;
    color: #2c5aa0 !important;
    padding: 5px 0;
    border-bottom: 1px solid #ddd;
    margin-bottom: 5px;
}

.special-link:hover {
    background-color: #f0f8ff;
    padding-left: 5px;
    transition: all 0.3s ease;
}

.no-leagues {
    color: #666;
    font-style: italic;
    padding: 0.5rem;
}

.divider {
    height: 1px;
    background-color: #ddd;
    margin: 10px 0;
    cursor: default !important;
    color: transparent !important;
}

/* Code und PIN Styles */
.code-cell,
.pin-cell {
    text-align: center;
    font-family: 'Courier New', monospace;
    font-weight: bold;
    min-width: 80px;
}

.match-report-cell {
    cursor: pointer;
}

.code-value {
    background: #e3f2fd;
    color: #1976d2;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.9rem;
    display: inline-block;
    border: 1px solid #bbdefb;
}

.code-value.clickable {
    cursor: pointer;
    transition: all 0.2s ease;
}

.code-value.clickable:hover {
    background: #bbdefb;
    transform: scale(1.05);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.nuscore-link {
    text-decoration: none;
    margin-right: 8px;
    font-size: 1.2rem;
    transition: transform 0.2s ease;
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    color: inherit;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 999px;
    background-color: #e3f2fd;
    border: 1px solid #bbdefb;
}

.nuscore-link:hover {
    transform: scale(1.2);
}

@media (pointer: coarse), (max-width: 900px) {
    .nuscore-link {
        width: 2.75rem;
        height: 2.75rem;
        font-size: 1.4rem;
    }
}

.pin-value {
    background: #fff3e0;
    color: #f57c00;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 0.9rem;
    display: inline-block;
    border: 1px solid #ffcc02;
}

.pin-value.clickable {
    cursor: pointer;
    transition: all 0.2s ease;
}

.pin-value.clickable:hover {
    background: #ffcc02;
    transform: scale(1.05);
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.no-data {
    color: #999;
    font-style: italic;
}

.match-today {
    background-color: #fff3cd !important;
    /* Gelb für heute (wie .row-test in MembersView) */
}

.match-next-week {
    background-color: #ffffcc !important;
    /* Hellgelb für nächste Woche (wie .row-test-form in MembersView) */
}

.match-today:hover {
    background-color: #ffeaa7 !important;
    /* Dunkleres Gelb beim Hover */
}

.match-next-week:hover {
    background-color: #fff9cc !important;
    /* Dunkleres Gelb beim Hover */
}

/* Tab Navigation */
.tab-navigation {
    display: flex;
    gap: 0;
    border-bottom: 2px solid #e0e0e0;
    margin-bottom: 20px;
}

.tab-button {
    background: none;
    border: none;
    padding: 12px 24px;
    font-size: 16px;
    font-weight: 500;
    color: #666;
    cursor: pointer;
    border-bottom: 3px solid transparent;
    transition: all 0.3s ease;
    margin-bottom: -2px;
}

.tab-button:hover {
    color: #333;
    background-color: #f8f9fa;
}

.tab-button.active {
    color: #28a745;
    border-bottom-color: #28a745;
}

/* Tab Content */
.tab-content {
    display: block !important; /* Überschreibe globales display: none */
    width: 100%;
}

.tab-panel {
    width: 100%;
}

/* Table Section */
.table-section {
    padding: 0;
}

.table-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 20px;
}

.table-header h3 {
    margin: 0;
}

.fetch-table-btn {
    background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
    color: var(--text-on-primary);
    border: 1px solid transparent;
    padding: 8px 16px;
    border-radius: 10px;
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    transition: transform 0.2s ease, opacity 0.2s ease;
}

.fetch-table-btn:hover:not(:disabled) {
    transform: translateY(-1px);
    opacity: 0.95;
}

.fetch-table-btn:disabled {
    background-color: #6c757d;
    cursor: not-allowed;
}

#league-table {
    width: 100%;
    border-collapse: collapse;
}

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

#league-table th {
    background-color: #f8f9fa;
    font-weight: 600;
}

#league-table tr:hover {
    background-color: #f5f5f5;
}

#league-table tr.our-team {
    background-color: #e8f5e8;
    font-weight: 600;
}

#league-table tr.our-team:hover {
    background-color: #d4edda;
}

/* Player Selection Dialog */
.player-selection-content {
    padding: 10px 0;
}

.match-info {
    margin-bottom: 20px;
    padding: 10px;
    background-color: #f8f9fa;
    border-radius: 4px;
}

.match-info p {
    margin: 5px 0;
}

.loading-state {
    padding: 40px;
    text-align: center;
    color: #6c757d;
}

.player-selection-table {
    width: 100%;
    border-collapse: collapse;
    margin: 20px 0;
}

.player-selection-table th,
.player-selection-table td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid #dee2e6;
}

.player-selection-table th {
    background-color: #f8f9fa;
    font-weight: 600;
    color: #495057;
}

.player-selection-table tbody tr:hover {
    background-color: #f8f9fa;
}

.player-name {
    font-weight: 500;
}

/* Gallery Styles */
.gallery-dialog-content {
    display: flex;
    flex-direction: column;
    padding: 0;
    min-height: 60vh;
    max-height: 70vh;
    overflow: auto;
}

.gallery-controls {
    width: 100%;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color, #ddd);
    display: flex;
    align-items: center;
    gap: 12px;
    background: #f9f9f9;
    flex-shrink: 0;
}

.gallery-controls label {
    font-weight: 500;
    color: var(--text-color, #333);
}

.gallery-controls select {
    padding: 6px 12px;
    border: 1px solid var(--border-color, #ddd);
    border-radius: 4px;
    font-size: 14px;
    background: white;
    cursor: pointer;
}

.gallery-controls select:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.gallery-members-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 16px;
    padding: 16px;
}

.gallery-member-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    cursor: pointer;
    padding: 8px;
    border: 2px solid transparent;
    border-radius: 8px;
    transition: all 0.2s ease;
}

.gallery-member-item:hover {
    background-color: #f0f0f0;
    border-color: #007bff;
}

.gallery-member-item.is-ready {
    border-color: #28a745;
    background-color: #d4edda;
}

.gallery-member-image {
    width: 100%;
    height: auto;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: 4px;
    margin-bottom: 8px;
    pointer-events: none; /* Prevent image from blocking clicks on parent */
}

.gallery-member-name {
    font-size: 12px;
    text-align: center;
    color: var(--text-color, #333);
    font-weight: 500;
}

.gallery-loading,
.gallery-error {
    padding: 20px;
    text-align: center;
    font-size: 1rem;
    color: var(--text-color, #333);
}

.checkbox-cell {
    text-align: center;
    width: 100px;
}

.checkbox-cell input[type="checkbox"] {
    width: 18px;
    height: 18px;
    cursor: pointer;
}

.no-members {
    padding: 40px;
    text-align: center;
    color: #6c757d;
    font-style: italic;
}

.dialog-actions {
    margin-top: 20px;
    padding-top: 20px;
    border-top: 1px solid #dee2e6;
    display: flex;
    gap: 10px;
    justify-content: flex-end;
}

.btn-save,
.btn-cancel {
    padding: 8px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    transition: background-color 0.2s;
}

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

.btn-save:hover {
    transform: translateY(-1px);
}

.btn-cancel {
    background: var(--surface-color);
    color: var(--text-color);
    border-color: var(--border-color);
}

.btn-cancel:hover {
    background-color: #5a6268;
}

.schedule-view {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.schedule-page-header {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    align-items: flex-start;
    flex-wrap: wrap;
}

.schedule-page-title h2 {
    margin: 0 0 4px;
}

.schedule-page-title p {
    margin: 0;
    color: var(--text-muted, #6c757d);
}

.schedule-page-actions {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
}

.schedule-summary-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.schedule-summary-item {
    min-width: 120px;
    padding: 10px 12px;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 10px;
    background: #fff;
}

.schedule-summary-label {
    display: block;
    font-size: 12px;
    color: var(--text-muted, #6c757d);
    margin-bottom: 4px;
}

.schedule-layout {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

.schedule-sidebar {
    min-width: 0;
}

.schedule-sidebar-card,
.schedule-workspace-header,
.schedule-empty-state {
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 12px;
    background: #fff;
}

.schedule-sidebar-card {
    padding: 14px;
}

.schedule-sidebar-header,
.schedule-workspace-header {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    align-items: flex-start;
}

.schedule-sidebar-header h3,
.schedule-workspace-header h3 {
    margin: 0;
}

.schedule-selection-count,
.workspace-eyebrow {
    font-size: 12px;
    color: var(--text-muted, #6c757d);
}

.workspace-eyebrow {
    display: block;
    margin-bottom: 4px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.schedule-workspace-header {
    padding: 14px 16px;
    margin-bottom: 14px;
}

.schedule-workspace-header p {
    margin: 6px 0 0;
    color: var(--text-muted, #6c757d);
}

.schedule-workspace-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}

.schedule-team-search {
    width: 100%;
    margin-top: 12px;
    margin-bottom: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border-color, #ced4da);
    border-radius: 8px;
}

.schedule-quick-links {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 12px;
}

.schedule-quick-link {
    width: 100%;
    text-align: left;
    padding: 10px 12px;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    background: #fff;
    cursor: pointer;
}

.schedule-quick-link.active,
.schedule-team-list li.active {
    border-color: var(--primary-color, #2b7cff);
    color: var(--primary-color, #2b7cff);
    background: rgba(43, 124, 255, 0.08);
    font-weight: 600;
}

.schedule-team-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.schedule-team-list li {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 10px 12px;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 8px;
    cursor: pointer;
}

.schedule-team-name {
    font-weight: 600;
}

.league-match-scope-card {
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 14px;
    background: linear-gradient(180deg, rgba(47, 122, 95, 0.08), rgba(47, 122, 95, 0.03));
    padding: 14px;
    margin-bottom: 12px;
}

.league-match-scope-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 10px;
}

.league-match-scope-header span {
    color: var(--text-muted, #6c757d);
    font-size: 14px;
}

.league-match-scope-controls {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
}

.team-filter-chip {
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 999px;
    background: var(--surface-color, #fff);
    color: var(--text-color, #333);
    padding: 8px 12px;
    cursor: pointer;
    font-weight: 600;
}

.team-filter-chip.active {
    border-color: var(--primary-soft, #5f9b82);
    color: var(--primary-strong, #1f5f49);
    background: rgba(47, 122, 95, 0.12);
}

.league-match-scope-select {
    min-width: 220px;
    padding: 8px 10px;
    border: 1px solid var(--border-color, #dee2e6);
    border-radius: 10px;
    background: var(--surface-color, #fff);
    color: var(--text-color, #333);
}

.league-match-scope-select:focus {
    outline: none;
    border-color: var(--primary-color, #2f7a5f);
    box-shadow: 0 0 0 3px rgba(47, 122, 95, 0.14);
}

.tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    margin-left: 6px;
    border-radius: 999px;
    background: rgba(47, 122, 95, 0.12);
    color: var(--primary-strong, #1f5f49);
    font-size: 12px;
}

.schedule-empty-state {
    padding: 28px;
    text-align: center;
}

.schedule-empty-state h3 {
    margin-top: 0;
    margin-bottom: 8px;
}

.schedule-empty-state p {
    margin: 0;
    color: var(--text-muted, #6c757d);
}

.output ul li.active {
    font-weight: 600;
    color: var(--primary-color, #2b7cff);
}

.team-league {
    color: var(--text-muted, #6c757d);
}

@media (max-width: 960px) {
    .schedule-layout {
        grid-template-columns: 1fr;
    }
}
</style>
