import { test } from '@japa/runner'
import net from 'net'
import { IHttpRequest, HttpEngineOptions, CoreEngine, HostRuleKind, DummyLogger } from '../../../../src/index.js'

const logger = new DummyLogger()

test.group('_connect()', (group) => {
  let engine: CoreEngine
  let request: IHttpRequest
  const host = 'localhost'
  const opts: HttpEngineOptions = {
    timeout: 50000,
    followRedirects: false,
    hosts: [
      {
        kind: HostRuleKind,
        from: 'domain.com',
        to: 'test.com',
        key: '1',
      },
    ],
    logger,
  }

  group.each.setup((ctx) => {
    request = {
      url: `http://localhost:${ctx.context.httpConfig.httpPort}/v1/get/`,
      method: 'GET',
      headers: 'Host: test.com\nContent-Length: 0',
      payload: 'abc',
    }
    engine = new CoreEngine(request, opts)
  })

  test('returns HTTP server client', async ({ assert, httpConfig }) => {
    const client = await engine._connect(httpConfig.httpPort, host)
    assert.typeOf(client, 'object')
    client.destroy()
  })

  test('Sets stats property', async ({ assert, httpConfig }) => {
    const client = await engine._connect(httpConfig.httpPort, host)
    client.destroy()
    assert.typeOf(engine.stats.connectionTime, 'number', 'connectionTime stat is set')
    assert.typeOf(engine.stats.lookupTime, 'number', 'lookupTime stat is set')
  })
})

test.group('_connectTls()', (group) => {
  let engine: CoreEngine
  let request: IHttpRequest
  const host = 'localhost'
  const opts: HttpEngineOptions = {
    timeout: 50000,
    followRedirects: false,
    hosts: [
      {
        kind: HostRuleKind,
        from: 'domain.com',
        to: 'test.com',
        key: '1',
      },
    ],
    logger,
  }

  group.each.setup((ctx) => {
    request = {
      url: `http://localhost:${ctx.context.httpConfig.httpPort}/v1/get/`,
      method: 'GET',
      headers: 'Host: test.com\nContent-Length: 0',
      payload: 'abc',
    }
    engine = new CoreEngine(request, opts)
  })

  test('returns HTTP server client', async ({ assert, httpConfig }) => {
    const client = await engine._connectTls(httpConfig.httpsPort, host)
    assert.typeOf(client, 'object')
    client.destroy()
  })

  test('sets stats property', async ({ assert, httpConfig }) => {
    const client = await engine._connectTls(httpConfig.httpsPort, host)
    client.destroy()
    assert.typeOf(engine.stats.connectionTime, 'number', 'connectionTime stat is set')
    assert.typeOf(engine.stats.lookupTime, 'number', 'lookupTime stat is set')
    assert.typeOf(engine.stats.secureStartTime, 'number', 'secureStartTime stat is set')
    assert.typeOf(engine.stats.secureConnectedTime, 'number', 'secureConnectedTime stat is set')
  })
})

test.group('connect()', (group) => {
  let engine: CoreEngine
  let request: IHttpRequest
  let opts: HttpEngineOptions
  let createdClient: net.Socket | undefined

  group.each.setup((ctx) => {
    request = {
      url: `http://localhost:${ctx.context.httpConfig.httpPort}/v1/headers`,
      method: 'GET',
      headers: 'x-test: true',
    }
    opts = {
      timeout: 50000,
      followRedirects: false,
      hosts: [
        {
          kind: HostRuleKind,
          from: 'domain.com',
          to: 'test.com',
          key: '1',
        },
      ],
      logger,
    }
    engine = new CoreEngine(request, opts)
  })

  group.each.teardown(() => {
    if (createdClient) {
      createdClient.end()
      createdClient.destroy()
      createdClient = undefined
    }
  })

  test('returns HTTP server client', async ({ assert }) => {
    const client = await engine.connect()
    assert.typeOf(client, 'object')
    createdClient = client
  })

  test('sets the socket property', async ({ assert }) => {
    const client = await engine.connect()
    assert.isTrue(engine.socket === client)
    createdClient = client
  })
})
