import { test } from '@japa/runner'
import sinon from 'sinon'
import { RestApi } from '../../../../src/mocking/legacy/RestApi.js'
import type { ARCRestApiIndex } from '../../../../src/legacy.js'

test.group('generateApiIndex()', (group) => {
  let apis: RestApi

  group.each.setup(() => {
    apis = new RestApi()
  })

  test('returns an object', ({ assert }) => {
    const result = apis.apiIndex()
    assert.typeOf(result, 'object')
  })

  test('has the {property} property of a type {type}')
    .with([
      { property: '_id', type: 'string' },
      { property: 'order', type: 'number' },
      { property: 'title', type: 'string' },
      { property: 'type', type: 'string' },
      { property: 'latest', type: 'string' },
      { property: 'versions', type: 'array' },
    ])
    .run(({ assert }, { property, type }) => {
      const result = apis.apiIndex()
      assert.typeOf(result[property as keyof ARCRestApiIndex], type)
    })

  test('generate versionsSize versions', ({ assert }) => {
    const result = apis.apiIndex({
      versionSize: 10,
    })
    assert.lengthOf(result.versions, 10)
  })
})

test.group('generateApiIndexList()', (group) => {
  let apis: RestApi

  group.each.setup(() => {
    apis = new RestApi()
  })

  test('returns an array', ({ assert }) => {
    const result = apis.apiIndexList()
    assert.typeOf(result, 'array')
  })

  test('has size items', ({ assert }) => {
    const result = apis.apiIndexList(10)
    assert.lengthOf(result, 10)
  })

  test('calls generateApiIndex() for each item', ({ assert }) => {
    const spy = sinon.spy(apis, 'apiIndex')
    apis.apiIndexList(2)
    assert.equal(spy.callCount, 2)
  })
})

test.group('apiData()', (group) => {
  let apis: RestApi

  group.each.setup(() => {
    apis = new RestApi()
  })

  test('returns an array', ({ assert }) => {
    const index = apis.apiIndex()
    const result = apis.apiData(index)
    assert.typeOf(result, 'array')
  })
  ;[
    ['_id', 'string'],
    ['data', 'string'],
    ['version', 'string'],
    ['indexId', 'string'],
  ].forEach(([property, type]) => {
    test(`has the ${property} property of a type ${type}`, ({ assert }) => {
      const index = apis.apiIndex()
      const result = apis.apiData(index)[0]
      // @ts-expect-error Used in testing
      assert.typeOf(result[property], type)
    })
  })

  test('generates an item for each version', ({ assert }) => {
    const index = apis.apiIndex({
      versionSize: 6,
    })
    const result = apis.apiData(index)
    assert.lengthOf(result, 6)
  })
})

test.group('apiDataList()', (group) => {
  let apis: RestApi

  group.each.setup(() => {
    apis = new RestApi()
  })

  test('returns an array', ({ assert }) => {
    const index = apis.apiIndex()
    const result = apis.apiDataList([index])
    assert.typeOf(result, 'array')
  })
  ;[
    ['_id', 'string'],
    ['data', 'string'],
    ['version', 'string'],
    ['indexId', 'string'],
  ].forEach(([property, type]) => {
    test(`has the ${property} property of a type ${type}`, ({ assert }) => {
      const index = apis.apiIndex()
      const result = apis.apiDataList([index])[0]
      // @ts-expect-error Used in testing
      assert.typeOf(result[property], type)
    })
  })

  test('generates an item for each version', ({ assert }) => {
    const index = apis.apiIndex({
      versionSize: 6,
    })
    const result = apis.apiDataList([index])
    assert.lengthOf(result, 6)
  })
})
