import { verifyToken } from '../utils/auth.js' import { readMembers } from '../utils/members.js' import { readUsers, migrateUserRoles } from '../utils/auth.js' export default defineEventHandler(async (event) => { try { const token = getCookie(event, 'auth_token') if (!token) { throw createError({ statusCode: 401, message: 'Nicht authentifiziert.' }) } const decoded = verifyToken(token) if (!decoded) { throw createError({ statusCode: 401, message: 'Ungültiges Token.' }) } // Get manual members and registered users const manualMembers = await readMembers() const registeredUsers = await readUsers() // Merge members: combine manual + registered, detect duplicates const mergedMembers = [] // Create lookup maps for O(1) matching instead of O(n) findIndex const emailToIndexMap = new Map() // email -> index in mergedMembers const nameToIndexMap = new Map() // name -> index in mergedMembers // First, add all manual members and build lookup maps for (let i = 0; i < manualMembers.length; i++) { const member = manualMembers[i] const normalizedEmail = member.email?.toLowerCase().trim() || '' const fullName = `${member.firstName || ''} ${member.lastName || ''}`.trim() const normalizedName = fullName.toLowerCase() const memberIndex = mergedMembers.length mergedMembers.push({ ...member, name: fullName, // Computed for display source: 'manual', editable: true, hasLogin: false }) // Build lookup maps (only for manual members) if (normalizedEmail) { // Only add if not already present (prefer first occurrence) if (!emailToIndexMap.has(normalizedEmail)) { emailToIndexMap.set(normalizedEmail, memberIndex) } } if (normalizedName) { // Only add if not already present (prefer first occurrence) if (!nameToIndexMap.has(normalizedName)) { nameToIndexMap.set(normalizedName, memberIndex) } } } // Then add registered users (only active ones) for (const user of registeredUsers) { if (!user.active) continue const normalizedEmail = user.email?.toLowerCase().trim() || '' const normalizedName = user.name?.toLowerCase().trim() || '' // Check if this user matches an existing manual member using O(1) lookup let matchedManualIndex = -1 // Try to match by email first (O(1) lookup) if (normalizedEmail && emailToIndexMap.has(normalizedEmail)) { matchedManualIndex = emailToIndexMap.get(normalizedEmail) // Verify it's still a manual member (safety check) if (mergedMembers[matchedManualIndex]?.source !== 'manual') { matchedManualIndex = -1 } } // If no email match, try name (O(1) lookup) if (matchedManualIndex === -1 && normalizedName && nameToIndexMap.has(normalizedName)) { matchedManualIndex = nameToIndexMap.get(normalizedName) // Verify it's still a manual member and email doesn't conflict (safety check) const candidate = mergedMembers[matchedManualIndex] if (candidate?.source === 'manual') { // Additional safety: if candidate has email, make sure it doesn't conflict const candidateEmail = candidate.email?.toLowerCase().trim() || '' if (!candidateEmail || candidateEmail === normalizedEmail) { // Safe to match by name } else { // Email mismatch - don't match by name alone matchedManualIndex = -1 } } else { matchedManualIndex = -1 } } if (matchedManualIndex !== -1) { // Merge with existing manual member const migratedUser = migrateUserRoles({ ...user }) const roles = Array.isArray(migratedUser.roles) ? migratedUser.roles : (migratedUser.role ? [migratedUser.role] : ['mitglied']) mergedMembers[matchedManualIndex] = { ...mergedMembers[matchedManualIndex], hasLogin: true, loginEmail: user.email, loginRoles: roles, loginRole: roles[0] || 'mitglied', // Rückwärtskompatibilität lastLogin: user.lastLogin, isMannschaftsspieler: user.isMannschaftsspieler === true || mergedMembers[matchedManualIndex].isMannschaftsspieler === true } } else { // Add as new member (from login system) const migratedUser = migrateUserRoles({ ...user }) const roles = Array.isArray(migratedUser.roles) ? migratedUser.roles : (migratedUser.role ? [migratedUser.role] : ['mitglied']) mergedMembers.push({ id: user.id, name: user.name, email: user.email, phone: user.phone || '', address: '', notes: `Rolle(n): ${roles.join(', ')}`, source: 'login', editable: false, hasLogin: true, loginEmail: user.email, loginRoles: roles, loginRole: roles[0] || 'mitglied', // Rückwärtskompatibilität lastLogin: user.lastLogin, isMannschaftsspieler: user.isMannschaftsspieler === true }) } } // Sort by name mergedMembers.sort((a, b) => a.name.localeCompare(b.name)) return { success: true, members: mergedMembers } } catch (error) { console.error('Fehler beim Abrufen der Mitgliederliste:', error) throw error } })