// @ts-nocheck
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { createEvent, mockSuccessReadBody } from './setup'

vi.mock('../server/utils/auth.js', () => ({
  verifyToken: vi.fn(),
  getUserById: vi.fn(),
  getUserFromToken: vi.fn(),
  readUsers: vi.fn(),
  readMembers: vi.fn(),
  writeUsers: vi.fn(),
  readSessions: vi.fn(),
  writeSessions: vi.fn(),
  migrateUserRoles: vi.fn((user) => {
    if (!user) return user
    if (Array.isArray(user.roles)) return user
    if (user.role) {
      user.roles = [user.role]
      delete user.role
    } else {
      user.roles = ['mitglied']
    }
    return user
  }),
  hasAnyRole: vi.fn((user, ...roles) => {
    if (!user) return false
    const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
    return roles.some(r => userRoles.includes(r))
  }),
  hasRole: vi.fn((user, role) => {
    if (!user) return false
    const userRoles = Array.isArray(user.roles) ? user.roles : (user.role ? [user.role] : [])
    return userRoles.includes(role)
  })
}))

vi.mock('../server/utils/members.js', () => ({
  readMembers: vi.fn(),
  writeMembers: vi.fn(),
  saveMember: vi.fn(),
  deleteMember: vi.fn(),
  normalizeDate: vi.fn((value) => value)
}))

const authUtils = await import('../server/utils/auth.js')
const memberUtils = await import('../server/utils/members.js')

import membersGetHandler from '../server/api/members.get.js'
import membersPostHandler from '../server/api/members.post.js'
import membersDeleteHandler from '../server/api/members.delete.js'
import membersBulkHandler from '../server/api/members/bulk.post.js'

describe('Members API Endpoints', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  describe('GET /api/members', () => {
    it('verlangt Authentifizierung', async () => {
      const event = createEvent()
      await expect(membersGetHandler(event)).rejects.toMatchObject({ statusCode: 401 })
    })

    it('gibt zusammengeführte Mitglieder zurück', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      memberUtils.readMembers.mockResolvedValue([
        { id: 'm1', firstName: 'Anna', lastName: 'Muster', email: 'anna@club.de', hasHallKey: true }
      ])
      authUtils.readUsers.mockResolvedValue([
        { id: 'u1', name: 'Ben Nutzer', email: 'ben@club.de', role: 'mitglied', active: true }
      ])
      authUtils.getUserFromToken.mockResolvedValue({ id: '1', role: 'mitglied' })

      const response = await membersGetHandler(event)

      expect(response.success).toBe(true)
      expect(response.members).toHaveLength(2)
      expect(response.members[0]).toHaveProperty('hasHallKey', true)
    })

    it('zeigt Legacy-Mitglieder ohne active-Flag weiterhin an', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      memberUtils.readMembers.mockResolvedValue([
        { id: 'm1', firstName: 'Anna', lastName: 'Muster', geburtsdatum: '2000-01-01' },
        { id: 'm2', firstName: 'Offen', lastName: 'Antrag', geburtsdatum: '2001-01-01', status: 'pending' }
      ])
      authUtils.readUsers.mockResolvedValue([])
      authUtils.getUserFromToken.mockResolvedValue({ id: '1', role: 'mitglied' })

      const response = await membersGetHandler(event)

      expect(response.success).toBe(true)
      expect(response.members).toHaveLength(1)
      expect(response.members[0].name).toBe('Anna Muster')
    })
  })

  describe('POST /api/members', () => {
    const baseBody = {
      firstName: 'Lisa',
      lastName: 'Beispiel',
      geburtsdatum: '2000-01-01',
      email: 'lisa@example.com',
      hasHallKey: true
    }

    it('verweigert Zugriff ohne Token', async () => {
      const event = createEvent()
      mockSuccessReadBody(baseBody)
      await expect(membersPostHandler(event)).rejects.toMatchObject({ statusCode: 401 })
    })

    it('verlangt Admin- oder Vorstand-Rolle', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody(baseBody)
      authUtils.getUserFromToken.mockResolvedValue({ id: '2', role: 'mitglied' })

      await expect(membersPostHandler(event)).rejects.toMatchObject({ statusCode: 403 })
    })

    it('gibt 409 bei Duplikaten zurück', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody(baseBody)
      authUtils.getUserFromToken.mockResolvedValue({ id: '2', role: 'admin' })
      memberUtils.saveMember.mockRejectedValue(new Error('existiert bereits'))

      await expect(membersPostHandler(event)).rejects.toMatchObject({ statusCode: 409 })
    })

    it('speichert Mitglied erfolgreich', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody(baseBody)
      authUtils.getUserFromToken.mockResolvedValue({ id: '2', role: 'admin' })
      memberUtils.saveMember.mockResolvedValue(true)

      const response = await membersPostHandler(event)
      expect(response.success).toBe(true)
      expect(memberUtils.saveMember).toHaveBeenCalledWith(expect.objectContaining({
        hasHallKey: true
      }))
    })

    it('erlaubt vorstand beim Speichern', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody(baseBody)
      authUtils.getUserFromToken.mockResolvedValue({ id: '3', role: 'vorstand' })
      memberUtils.saveMember.mockResolvedValue(true)

      const response = await membersPostHandler(event)
      expect(response.success).toBe(true)
    })

    it('erlaubt Updates von Altdaten ohne Geburtsdatum', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody({
        id: 'legacy-1',
        firstName: 'Lisa',
        lastName: 'Beispiel',
        email: 'lisa@example.com'
      })
      authUtils.getUserFromToken.mockResolvedValue({ id: '3', role: 'vorstand' })
      memberUtils.saveMember.mockResolvedValue(true)

      const response = await membersPostHandler(event)
      expect(response.success).toBe(true)
      expect(memberUtils.saveMember).toHaveBeenCalledWith(expect.objectContaining({
        id: 'legacy-1',
        geburtsdatum: ''
      }))
    })
  })

  describe('DELETE /api/members', () => {
    it('validiert die ID', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody({})
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      authUtils.getUserById.mockResolvedValue({ id: '1', role: 'admin' })

      await expect(membersDeleteHandler(event)).rejects.toMatchObject({ statusCode: 400 })
    })

    it('löscht Mitglied erfolgreich', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody({ id: 'm1' })
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      authUtils.getUserById.mockResolvedValue({ id: '1', role: 'vorstand' })
      memberUtils.deleteMember.mockResolvedValue(true)

      const response = await membersDeleteHandler(event)
      expect(response.success).toBe(true)
      expect(memberUtils.deleteMember).toHaveBeenCalledWith('m1')
    })
  })

  describe('POST /api/members/bulk', () => {
    const importBody = {
      members: [
        { firstName: 'Paul', lastName: 'Team', geburtsdatum: '2001-02-03' }
      ]
    }

    it('validiert members-Array', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody({ members: [] })
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      authUtils.getUserById.mockResolvedValue({ id: '1', role: 'admin' })

      await expect(membersBulkHandler(event)).rejects.toMatchObject({ statusCode: 400 })
    })

    it('importiert Mitglieder und schreibt Datei', async () => {
      const event = createEvent({ cookies: { auth_token: 'token' } })
      mockSuccessReadBody(importBody)
      authUtils.verifyToken.mockReturnValue({ id: '1' })
      authUtils.getUserById.mockResolvedValue({ id: '1', role: 'admin' })
      memberUtils.readMembers.mockResolvedValue([])
      memberUtils.writeMembers.mockResolvedValue(true)

      const response = await membersBulkHandler(event)

      expect(response.success).toBe(true)
      expect(response.summary.imported).toBe(1)
      expect(memberUtils.writeMembers).toHaveBeenCalled()
    })
  })
})
