import { test } from '@japa/runner'
import { ISafePayload, Headers } from '../../../../src/index.js'
import * as PayloadSupport from '../../../../src/runtime/http-engine/PayloadSupport.js'

test.group('normalizeString()', () => {
  test('returns the same string', ({ assert }) => {
    const result = PayloadSupport.normalizeString('test')
    assert.strictEqual(result, 'test')
  })

  test('adds CRLF for a single \\n character', ({ assert }) => {
    const result = PayloadSupport.normalizeString('te\nst')
    assert.strictEqual(result, 'te\r\nst')
  })

  test('adds CRLF for a single \\r character', ({ assert }) => {
    const result = PayloadSupport.normalizeString('te\rst')
    assert.strictEqual(result, 'te\r\nst')
  })

  test('ignores existing \\r\\n characters', ({ assert }) => {
    const result = PayloadSupport.normalizeString('te\r\nst')
    assert.strictEqual(result, 'te\r\nst')
  })
})

test.group('payloadToBuffer()', (group) => {
  const filePayload: ISafePayload = {
    type: 'file',
    data: [42, 42, 42],
    meta: { mime: 'text/plain', name: 'foo.txt' },
  }

  const blobPayload: ISafePayload = {
    type: 'blob',
    data: [42, 42, 42],
    meta: { mime: 'text/plain' },
  }

  const bufferPayload: ISafePayload = {
    type: 'buffer',
    data: [42, 42, 42],
  }

  const arrayBufferPayload: ISafePayload = {
    type: 'arraybuffer',
    data: [42, 42, 42],
  }

  const formDataPayload: ISafePayload = {
    type: 'formdata',
    data: [
      {
        name: 'txt',
        value: 'text-value',
        enabled: true,
      },
    ],
  }

  let headers: Headers
  group.each.setup(() => {
    headers = new Headers()
  })

  test('returns undefined when no payload', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers)
    assert.isUndefined(result)
    assert.notOk(headers.get('content-type'), 'does not add content-type')
  })

  test('returns Buffer from a string', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, 'test')
    assert.ok(result, 'has the result')
    assert.equal((result as Buffer).toString('utf-8'), 'test', 'has the contents')
    assert.notOk(headers.get('content-type'), 'does not add content-type')
  })

  test('returns Buffer from a File', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, filePayload)
    assert.ok(result, 'has the result')
    assert.equal((result as Buffer).toString('utf-8'), '***', 'has the contents')
  })

  test('adds the File content type', ({ assert }) => {
    PayloadSupport.payloadToBuffer(headers, filePayload)
    const mime = headers.get('content-type')
    assert.equal(mime, 'text/plain')
  })

  test('returns Buffer from a Blob', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, blobPayload)
    assert.ok(result, 'has the result')
    assert.equal((result as Buffer).toString('utf-8'), '***', 'has the contents')
  })

  test('adds the Blob content type', ({ assert }) => {
    PayloadSupport.payloadToBuffer(headers, blobPayload)
    const mime = headers.get('content-type')
    assert.equal(mime, 'text/plain')
  })

  test('returns Buffer from a Buffer', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, bufferPayload)
    assert.ok(result, 'has the result')
    assert.equal((result as Buffer).toString('utf-8'), '***', 'has the contents')
    assert.notOk(headers.get('content-type'), 'does not add content-type')
  })

  test('returns Buffer from an ArrayBuffer', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, arrayBufferPayload)
    assert.ok(result, 'has the result')
    assert.equal((result as Buffer).toString('utf-8'), '***', 'has the contents')
    assert.notOk(headers.get('content-type'), 'does not add content-type')
  })

  test('returns Buffer from a FormData', ({ assert }) => {
    const result = PayloadSupport.payloadToBuffer(headers, formDataPayload)
    assert.ok(result, 'has the result')
  })

  test('adds the FormData content type', ({ assert }) => {
    PayloadSupport.payloadToBuffer(headers, formDataPayload)
    const mime = headers.get('content-type')
    assert.include(mime, 'multipart/form-data; boundary=')
  })
})
