/* eslint-disable no-restricted-globals */
import { configure, processCLIArgs, run } from '@japa/runner'
import { assert, type Assert } from '@japa/assert'
import { apiClient, type ApiClient } from '@japa/api-client'
import { expectTypeOf } from '@japa/expect-type'
import { browserClient } from '@japa/browser-client'
import { TestContext } from '@japa/runner/core'
import Servers from './server.js'
import { SetupHttpConfig } from './context.js'
import * as reporters from '@japa/runner/reporters'
import { events } from './plugins/events/index.js'
import { sinon } from './plugins/sinon/index.js'

const servers = new Servers()

TestContext.macro('sleep', function (milliseconds: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, milliseconds)
  })
})

TestContext.getter('httpConfig', () => servers.getConfig())

const activated = ['spec']
if (process.env.GITHUB_ACTIONS === 'true') {
  activated.push('github')
}

processCLIArgs(process.argv.splice(2))
configure({
  suites: [
    {
      name: 'unit',
      files: ['tests/unit/**/*.spec.ts'],
      configure(suite): void {
        suite.setup(async () => {
          await servers.start()
          return () => servers.stop()
        })
      },
    },
  ],
  plugins: [
    assert(),
    apiClient('http://localhost:3333'),
    expectTypeOf(),
    browserClient({ runInSuites: ['browser'] }),
    events(),
    sinon(),
  ],
  reporters: {
    activated,
    list: [reporters.spec(), reporters.ndjson(), reporters.dot(), reporters.github()],
  },
})

run()

declare module '@japa/runner' {
  interface TestContext {
    client: ApiClient
    assert: Assert
  }
}

declare module '@japa/runner/core' {
  interface TestContext {
    /**
     * Awaits with the text execution.
     * @param milliseconds The number of milliseconds to wait
     */
    sleep(milliseconds: number): Promise<void>
    /**
     * The configuration of the HTTP servers for unit testing.
     */
    httpConfig: SetupHttpConfig
  }
}
