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

suite('Accounts', { tags: ['accounts', 'crud'] }, (t) => {
  t.test('creates an account', { tags: ['create'] }, async () => {
    const res = await t.api.post('/v1/accounts', { name: 'Test Account' })
    t.assert.status(res, 201)
    t.assert.equal(res.data.name, 'Test Account')
    t.assert.ok(res.data.id)
    t.assert.ok(res.data.accountNumber, 'should auto-generate account number')
    t.assert.equal(res.data.accountNumber.length, 6)
  })

  t.test('creates account with address and normalizes state', { tags: ['create'] }, async () => {
    const res = await t.api.post('/v1/accounts', {
      name: 'Texas Family',
      address: { street: '123 Main', city: 'Austin', state: 'texas', zip: '78701' },
    })
    t.assert.status(res, 201)
    t.assert.equal(res.data.address.state, 'TX')
  })

  t.test('lists accounts with pagination', { tags: ['read'] }, async () => {
    await t.api.post('/v1/accounts', { name: 'List Test A' })
    await t.api.post('/v1/accounts', { name: 'List Test B' })

    const res = await t.api.get('/v1/accounts', { limit: 100 })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.length >= 2)
    t.assert.ok(res.data.pagination.total >= 2)
  })

  t.test('searches accounts by name', { tags: ['search'] }, async () => {
    await t.api.post('/v1/accounts', { name: 'Searchable Unicorn' })

    const res = await t.api.get('/v1/accounts', { q: 'Unicorn' })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.some((a: { name: string }) => a.name === 'Searchable Unicorn'))
  })

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

    const res = await t.api.get('/v1/accounts', { q: 'FindableKid' })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.some((a: { id: string }) => a.id === acct.data.id))
  })

  t.test('gets account by id', { tags: ['read'] }, async () => {
    const created = await t.api.post('/v1/accounts', { name: 'Get By ID' })
    const res = await t.api.get(`/v1/accounts/${created.data.id}`)
    t.assert.status(res, 200)
    t.assert.equal(res.data.name, 'Get By ID')
  })

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

  t.test('updates an account', { tags: ['update'] }, async () => {
    const created = await t.api.post('/v1/accounts', { name: 'Before Update' })
    const res = await t.api.patch(`/v1/accounts/${created.data.id}`, { name: 'After Update' })
    t.assert.status(res, 200)
    t.assert.equal(res.data.name, 'After Update')
  })

  t.test('soft-deletes an account', { tags: ['delete'] }, async () => {
    const created = await t.api.post('/v1/accounts', { name: 'To Delete' })
    const res = await t.api.del(`/v1/accounts/${created.data.id}`)
    t.assert.status(res, 200)
    t.assert.equal(res.data.isActive, false)
  })

  t.test('sets primary member on first member create', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Primary Test' })
    const member = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'First',
      lastName: 'Member',
    })

    const refreshed = await t.api.get(`/v1/accounts/${acct.data.id}`)
    t.assert.equal(refreshed.data.primaryMemberId, member.data.id)
  })

  t.test('does not overwrite primary on second member', { tags: ['create'] }, async () => {
    const acct = await t.api.post('/v1/accounts', { name: 'Primary Keep' })
    const first = await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'First',
      lastName: 'One',
    })
    await t.api.post(`/v1/accounts/${acct.data.id}/members`, {
      firstName: 'Second',
      lastName: 'One',
    })

    const refreshed = await t.api.get(`/v1/accounts/${acct.data.id}`)
    t.assert.equal(refreshed.data.primaryMemberId, first.data.id)
  })

  t.test('searches by email', { tags: ['search'] }, async () => {
    await t.api.post('/v1/accounts', { name: 'Email Search', email: 'findme-unique@test.com' })

    const res = await t.api.get('/v1/accounts', { q: 'findme-unique@test' })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.some((a: { email: string }) => a.email === 'findme-unique@test.com'))
  })

  t.test('searches by phone', { tags: ['search'] }, async () => {
    await t.api.post('/v1/accounts', { name: 'Phone Search', phone: '555-UNIQUE-9876' })

    const res = await t.api.get('/v1/accounts', { q: '555-UNIQUE-9876' })
    t.assert.status(res, 200)
    t.assert.ok(res.data.data.some((a: { phone: string }) => a.phone === '555-UNIQUE-9876'))
  })

  t.test('paginates with page and limit', { tags: ['read', 'pagination'] }, async () => {
    for (let i = 0; i < 5; i++) {
      await t.api.post('/v1/accounts', { name: `Paginate ${i}` })
    }

    const page1 = await t.api.get('/v1/accounts', { page: 1, limit: 2 })
    t.assert.status(page1, 200)
    t.assert.equal(page1.data.data.length, 2)
    t.assert.greaterThan(page1.data.pagination.totalPages, 1)

    const page2 = await t.api.get('/v1/accounts', { page: 2, limit: 2 })
    t.assert.status(page2, 200)
    t.assert.equal(page2.data.data.length, 2)
    t.assert.notEqual(page1.data.data[0].id, page2.data.data[0].id)
  })

  t.test('sorts by name descending', { tags: ['read', 'sort'] }, async () => {
    await t.api.post('/v1/accounts', { name: 'AAA Sort First' })
    await t.api.post('/v1/accounts', { name: 'ZZZ Sort Last' })

    const res = await t.api.get('/v1/accounts', { sort: 'name', order: 'desc', limit: 100 })
    t.assert.status(res, 200)
    const names = res.data.data.map((a: { name: string }) => a.name)
    const zIdx = names.findIndex((n: string) => n.includes('ZZZ'))
    const aIdx = names.findIndex((n: string) => n.includes('AAA'))
    t.assert.ok(zIdx < aIdx, 'ZZZ should come before AAA in desc order')
  })

  t.test('creates account with billing mode split', { tags: ['create'] }, async () => {
    const res = await t.api.post('/v1/accounts', { name: 'Split Billing', billingMode: 'split' })
    t.assert.status(res, 201)
    t.assert.equal(res.data.billingMode, 'split')
  })

  t.test('updates billing mode', { tags: ['update'] }, async () => {
    const created = await t.api.post('/v1/accounts', { name: 'Change Billing' })
    const res = await t.api.patch(`/v1/accounts/${created.data.id}`, { billingMode: 'split' })
    t.assert.status(res, 200)
    t.assert.equal(res.data.billingMode, 'split')
  })
})
