import { suite } from '../lib/context.js'

suite('Members', { tags: ['members', 'crud'] }, (t) => {
  t.test('creates a member with auto-generated number', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Member Create Test' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Alice',
      lastName: 'Test',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.firstName, 'Alice')
    t.assert.ok(res.data.memberNumber, 'should auto-generate member number')
    t.assert.equal(res.data.memberNumber.length, 6)
  })

  t.test('inherits email from account when not provided', { tags: ['inheritance'] }, async () => {
    const acct = await t.api.post('/v1/accounts', {
      name: 'Inherit Email',
      email: 'family@test.com',
      phone: '555-1234',
    })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Child',
      lastName: 'Inherit',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.email, 'family@test.com')
    t.assert.equal(res.data.phone, '555-1234')
  })

  t.test('uses member email when explicitly provided', { tags: ['inheritance'] }, async () => {
    const acct = await t.api.post('/v1/accounts', {
      name: 'Override Email',
      email: 'family@test.com',
    })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Adult',
      lastName: 'Own',
      email: 'own@test.com',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.email, 'own@test.com')
  })

  t.test('inherits address from account when not provided', { tags: ['inheritance'] }, async () => {
    const acct = await t.api.post('/v1/accounts', {
      name: 'Inherit Address',
      address: { street: '123 Main St', city: 'Austin', state: 'TX', zip: '78701' },
    })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Kid',
      lastName: 'Home',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.address.city, 'Austin')
    t.assert.equal(res.data.address.state, 'TX')
  })

  t.test('accepts explicit isMinor flag without DOB', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Minor Test' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Kid',
      lastName: 'NoDate',
      isMinor: true,
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.isMinor, true)
  })

  t.test('creates member without email or DOB', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Minimal Member' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Just',
      lastName: 'Name',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.firstName, 'Just')
  })

  t.test('lists all members across accounts', { tags: ['read'] }, async () => {
    const acct1 = await t.api.post('/v1/accounts', { name: 'List A' })
    const acct2 = await t.api.post('/v1/accounts', { name: 'List B' })
    await t.api.post(`/v1/accounts/${acct1.data.id}/members`, { firstName: 'A1', lastName: 'One' })
    await t.api.post(`/v1/accounts/${acct2.data.id}/members`, { firstName: 'B1', lastName: 'Two' })

    const res = await t.api.get('/v1/members', { limit: 100 })
    t.assert.status(res, 200)
    t.assert.greaterThan(res.data.data.length, 1)
    t.assert.ok(res.data.data[0].accountName, 'should include account name')
  })

  t.test('searches members by name', { tags: ['search'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Search Member Acct' })
    await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'UniqueSearchName',
      lastName: 'Person',
    })

    const res = await t.api.get('/v1/members', { q: 'UniqueSearchName' })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.some((m: { firstName: string }) => m.firstName === 'UniqueSearchName'))
  })

  t.test('moves member to existing account', { tags: ['move'] }, async () => {
    const acct1 = await t.api.post('/v1/accounts', { name: 'Source Acct' })
    const acct2 = await t.api.post('/v1/accounts', { name: 'Target Acct' })
    const member = await t.api.post(`/v1/accounts/${acct1.data.id}/members`, {
      firstName: 'Mover',
      lastName: 'Person',
    })

    const res = await t.api.post(`/v1/members/${member.data.id}/move`, {
      accountId: acct2.data.id,
    })
    t.assert.status(res, 200)
    t.assert.equal(res.data.accountId, acct2.data.id)
  })

  t.test('moves member to new account when no accountId given', { tags: ['move'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Move Source' })
    const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Solo',
      lastName: 'Flyer',
    })

    const res = await t.api.post(`/v1/members/${member.data.id}/move`, {})
    t.assert.status(res, 200)
    t.assert.notEqual(res.data.accountId, acct.data.id)
  })

  t.test('normalizes state on member address via account inheritance', { tags: ['inheritance'] }, async () => {
    const acct = await t.api.post('/v1/accounts', {
      name: 'State Inherit',
      address: { state: 'California' },
    })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Cal',
      lastName: 'Kid',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.address.state, 'CA')
  })

  t.test('updates a member', { tags: ['update'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Update Test' })
    const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Before',
      lastName: 'Update',
    })

    const res = await t.api.patch(`/v1/members/${member.data.id}`, { firstName: 'After' })
    t.assert.status(res, 200)
    t.assert.equal(res.data.firstName, 'After')
  })

  t.test('deletes a member', { tags: ['delete'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Delete Test' })
    const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Gone',
      lastName: 'Soon',
    })

    const res = await t.api.del(`/v1/members/${member.data.id}`)
    t.assert.status(res, 200)
  })

  t.test('lists members for a specific account', { tags: ['read'] }, async () => {
    const acct1 = await t.api.post('/v1/accounts', { name: 'Scoped List A' })
    const acct2 = await t.api.post('/v1/accounts', { name: 'Scoped List B' })
    await t.api.post(`/v1/accounts/${acct1.data.id}/members`, { firstName: 'In', lastName: 'Scope' })
    await t.api.post(`/v1/accounts/${acct2.data.id}/members`, { firstName: 'Out', lastName: 'Scope' })

    const res = await t.api.get(`/v1/accounts/${acct1.data.id}/members`)
    t.assert.status(res, 200)
    t.assert.equal(res.data.data.length, 1)
    t.assert.equal(res.data.data[0].firstName, 'In')
  })

  t.test('derives isMinor from child DOB', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Minor DOB Test' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Young',
      lastName: 'Kid',
      dateOfBirth: '2020-01-01',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.isMinor, true)
  })

  t.test('derives isMinor as false from adult DOB', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Adult DOB Test' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Grown',
      lastName: 'Up',
      dateOfBirth: '1985-06-15',
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.isMinor, false)
  })

  t.test('explicit isMinor overrides DOB calculation', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Override Minor' })
    const res = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Override',
      lastName: 'Test',
      dateOfBirth: '1985-06-15',
      isMinor: true,
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.isMinor, true)
  })

  t.test('update recalculates isMinor when DOB changes', { tags: ['update'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Recalc Test' })
    const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Age',
      lastName: 'Change',
      dateOfBirth: '2020-01-01',
    })
    t.assert.equal(member.data.isMinor, true)

    const res = await t.api.patch(`/v1/members/${member.data.id}`, { dateOfBirth: '1980-01-01' })
    t.assert.status(res, 200)
    t.assert.equal(res.data.isMinor, false)
  })

  t.test('returns 404 for missing member', { tags: ['read'] }, async () => {
    const res = await t.api.get('/v1/members/a0000000-0000-0000-0000-999999999999')
    t.assert.status(res, 404)
  })
})
