import { describe, it, expect, vi, beforeEach } from 'vitest'

vi.mock('../../../server/models/counter.js', () => ({
  default: {
    findOneAndUpdate: vi.fn()
  }
}))

vi.mock('../../../server/models/member.js', () => ({
  default: {
    findByIdAndUpdate: vi.fn()
  }
}))

import Counter from '../../../server/models/counter.js'
import Member from '../../../server/models/member.js'
import { assignMemberNumber } from '../../../server/utils/memberNumber.js'

describe('assignMemberNumber', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    Member.findByIdAndUpdate.mockResolvedValue(undefined)
  })

  it('returns 1 for the first member', async () => {
    Counter.findOneAndUpdate.mockResolvedValue({ seq: 1 })

    const result = await assignMemberNumber('member-abc')

    expect(result).toBe(1)
  })

  it('increments atomically using findOneAndUpdate with $inc and upsert', async () => {
    Counter.findOneAndUpdate.mockResolvedValue({ seq: 5 })

    await assignMemberNumber('member-xyz')

    expect(Counter.findOneAndUpdate).toHaveBeenCalledWith(
      { _id: 'memberNumber' },
      { $inc: { seq: 1 } },
      { new: true, upsert: true }
    )
  })

  it('saves the member number to the member record without running validators', async () => {
    Counter.findOneAndUpdate.mockResolvedValue({ seq: 3 })

    await assignMemberNumber('member-abc')

    expect(Member.findByIdAndUpdate).toHaveBeenCalledWith(
      'member-abc',
      { memberNumber: 3 },
      { runValidators: false }
    )
  })

  it('returns the sequence number for the given member', async () => {
    Counter.findOneAndUpdate.mockResolvedValue({ seq: 42 })

    const result = await assignMemberNumber('member-999')

    expect(result).toBe(42)
  })
})
