import { verifyToken, getUserFromToken, hasRole } 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.'
      })
    }

  const currentUser = await getUserFromToken(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 manual members. Legacy records without explicit status flags
    // are treated as accepted members; only explicit non-accepted records are skipped.
    for (let i = 0; i < manualMembers.length; i++) {
      const member = manualMembers[i]
      const normalizedStatus = member.status ? String(member.status).toLowerCase() : ''
      const hasExplicitAcceptanceFlag = member.active !== undefined || member.accepted !== undefined || normalizedStatus !== ''
      const isAccepted = hasExplicitAcceptanceFlag
        ? (
            member.active === true ||
            member.accepted === true ||
            normalizedStatus === 'accepted'
          )
        : true
      if (!isAccepted) {
        // Skip applications that are not yet accepted
        continue
      }
      const normalizedEmail = member.email?.toLowerCase().trim() || ''
      const fullName = `${member.firstName || ''} ${member.lastName || ''}`.trim()
      const normalizedName = fullName.toLowerCase()

      const memberIndex = mergedMembers.length
      // Ensure visibility flags are booleans for manual entries
      const vis = member.visibility || {}
      member.visibility = {
        // Default: visible to all logged-in members unless explicitly hidden
        showEmail: vis.showEmail === undefined ? true : Boolean(vis.showEmail),
        showPhone: vis.showPhone === undefined ? true : Boolean(vis.showPhone),
        // Address remains private by default
        showAddress: vis.showAddress === undefined ? false : Boolean(vis.showAddress)
      }

      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() || ''

      // Hilfsfunktion: Extrahiere Vorname/Nachname aus user.name
      function extractNames(name) {
        if (!name || typeof name !== 'string') return { firstName: '', lastName: '' }
        const parts = name.trim().split(/\s+/)
        if (parts.length === 1) return { firstName: parts[0], lastName: '' }
        return { firstName: parts[0], lastName: parts.slice(1).join(' ') }
      }

      // 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'])
        // Extrahiere Namen nur, wenn Felder leer sind
        const { firstName, lastName } = extractNames(user.name)
        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,
          geburtsdatum: mergedMembers[matchedManualIndex].geburtsdatum || user.geburtsdatum || '',
          firstName: mergedMembers[matchedManualIndex].firstName || firstName,
          lastName: mergedMembers[matchedManualIndex].lastName || lastName,
          editable: true
        }
        // If the registered user has visibility preferences, apply them (coerce to booleans)
        if (user.visibility && typeof user.visibility === 'object') {
          const vis = mergedMembers[matchedManualIndex].visibility || {}
          mergedMembers[matchedManualIndex].visibility = {
            showEmail: user.visibility.showEmail === undefined ? Boolean(vis.showEmail) : Boolean(user.visibility.showEmail),
            showPhone: user.visibility.showPhone === undefined ? Boolean(vis.showPhone) : Boolean(user.visibility.showPhone),
            showAddress: user.visibility.showAddress === undefined ? Boolean(vis.showAddress) : Boolean(user.visibility.showAddress)
          }
        }
      } 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'])
        // Registered-only user: default to privacy-preserving visibility (hidden) unless user explicitly set visibility elsewhere
        // Use stored visibility from user if present, otherwise default to false
        const userVis = user.visibility || {}
        const { firstName, lastName } = extractNames(user.name)
        mergedMembers.push({
          id: user.id,
          name: user.name,
          firstName,
          lastName,
          geburtsdatum: user.geburtsdatum || '',
          email: user.email,
          phone: user.phone || '',
          address: '',
          visibility: {
              showEmail: userVis.showEmail === undefined ? true : Boolean(userVis.showEmail),
              showPhone: userVis.showPhone === undefined ? true : Boolean(userVis.showPhone),
              showAddress: userVis.showAddress === undefined ? false : Boolean(userVis.showAddress)
            },
          notes: `Rolle(n): ${roles.join(', ')}`,
          source: 'login',
          editable: true,
          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))
    // Die Mitgliederliste ist nur für authentifizierte Nutzer sichtbar (siehe oben).
    // Respektiere individuelle Sichtbarkeitspräferenzen (user.visibility)
  const currentUserToken = token
  const isViewerAuthenticated = !!currentUser
  // Only 'vorstand' may override member visibility
  const isPrivilegedViewer = currentUser ? hasRole(currentUser, 'vorstand') : false

  // Filtere den Admin-Account heraus
  const filteredMembers = mergedMembers.filter(m => m.email?.toLowerCase() !== 'admin@harheimertc.de')
  const sanitizedMembers = filteredMembers.map(member => {
      // Default: show email/phone/address to other logged-in members unless member.visibility explicitly hides them
      const visibility = member.visibility || {}

      const showEmail = visibility.showEmail === undefined ? true : Boolean(visibility.showEmail)
      const showPhone = visibility.showPhone === undefined ? true : Boolean(visibility.showPhone)
      const showAddress = visibility.showAddress === undefined ? false : Boolean(visibility.showAddress)

  // Determine if contact info existed but was hidden to the viewer
  const hadEmail = !!member.email
  const hadPhone = !!member.phone
  const hadAddress = !!member.address
  const hadBirthday = !!member.geburtsdatum
  const emailVisible = (isPrivilegedViewer || (isViewerAuthenticated && showEmail))
  const phoneVisible = (isPrivilegedViewer || (isViewerAuthenticated && showPhone))
  const addressVisible = (isPrivilegedViewer || (isViewerAuthenticated && showAddress))
  const birthdayVisible = (isPrivilegedViewer || (isViewerAuthenticated && (member.visibility && member.visibility.showBirthday !== undefined ? Boolean(member.visibility.showBirthday) : true)))
  const contactHidden = (!emailVisible && hadEmail) || (!phoneVisible && hadPhone) || (!addressVisible && hadAddress)

  return {
    id: member.id,
    name: member.name,
    firstName: member.firstName || '',
    lastName: member.lastName || '',
    source: member.source,
    editable: member.editable,
    hasLogin: member.hasLogin,
    loginRoles: member.loginRoles,
    loginRole: member.loginRole,
    lastLogin: member.lastLogin,
    isMannschaftsspieler: member.isMannschaftsspieler,
    hasHallKey: member.hasHallKey === true || member.hasHallenschluessel === true,
    notes: member.notes || '',
    // Sichtbarkeits-Flags explizit mitgeben
    showEmail: visibility.showEmail === undefined ? true : Boolean(visibility.showEmail),
    showPhone: visibility.showPhone === undefined ? true : Boolean(visibility.showPhone),
    showAddress: visibility.showAddress === undefined ? false : Boolean(visibility.showAddress),
    showBirthday: visibility.showBirthday === undefined ? true : Boolean(visibility.showBirthday),
    // Privileged viewers (vorstand) always see contact fields
    email: emailVisible ? member.email : undefined,
    phone: phoneVisible ? member.phone : undefined,
    address: addressVisible ? member.address : undefined,
    // Birthday: expose only day + month and only if allowed; do not expose year or age
    birthday: (birthdayVisible && hadBirthday) ? (function(){
      try {
        const d = new Date(member.geburtsdatum)
        if (isNaN(d.getTime())) return undefined
        const day = `${d.getDate()}`.padStart(2, '0')
        const month = `${d.getMonth()+1}`.padStart(2, '0')
        return `${day}.${month}`
      } catch (_e) {
        return undefined
      }
    })() : undefined,
  geburtsdatum: member.geburtsdatum || undefined // Originalfeld für das Edit-Formular
  }
})

    return {
      success: true,
      members: sanitizedMembers
    }
  } catch (error) {
    console.error('Fehler beim Abrufen der Mitgliederliste:', error)
    throw error
  }
})

