import { test } from '@japa/runner'
import sinon from 'sinon'
import { Certificates } from '../../../../src/mocking/lib/Certificates.js'
import { Certificate, IPemCertificate } from '../../../../src/models/ClientCertificate.js'
import type { HttpCertificate } from '../../../../src/index.js'

test.group('certificate()', (group) => {
  let certs: Certificates

  group.each.setup(() => {
    certs = new Certificates()
  })

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

  test('has the {property} property of a type {type}')
    .with([
      { property: 'type', type: 'string' },
      { property: 'cert', type: 'object' },
      { property: 'key', type: 'string' },
      { property: 'name', type: 'string' },
      { property: 'created', type: 'number' },
    ])
    .run(({ assert }, { property, type }) => {
      const result = certs.certificate()
      assert.typeOf(result[property as keyof HttpCertificate], type)
    })

  test('uses passed type', ({ assert }) => {
    const result = certs.certificate({
      type: 'p12',
    })
    assert.equal(result.type, 'p12')
  })

  test('adds certKey on the pem certificate', ({ assert }) => {
    const result = certs.certificate({
      type: 'pem',
    }) as IPemCertificate
    assert.typeOf(result.certKey, 'object')
    assert.typeOf(result.certKey.data, 'string')
    assert.isNotEmpty(result.certKey.data)
  })

  test('creates binary data on a certificate', ({ assert }) => {
    const result = certs.certificate({
      binary: true,
    })
    const cert = new Certificate(result)
    assert.typeOf(cert.cert.data, 'Uint8Array')
  })

  test('adds passphrase to a certificate by default', ({ assert }) => {
    const result = certs.certificate({})
    assert.typeOf(result.cert.passphrase, 'string')
  })

  test('ignores passphrase on a certificate', ({ assert }) => {
    const result = certs.certificate({
      noPassphrase: true,
    })
    assert.isUndefined(result.cert.passphrase)
  })
})

test.group('certificates()', (group) => {
  let certs: Certificates

  group.each.setup(() => {
    certs = new Certificates()
  })

  test('Returns an array', ({ assert }) => {
    const result = certs.certificates()
    assert.typeOf(result, 'array')
  })

  test('List has default number of items', ({ assert }) => {
    const result = certs.certificates()
    assert.lengthOf(result, 15)
  })

  test('Returns requested number of items', ({ assert }) => {
    const result = certs.certificates(5)
    assert.lengthOf(result, 5)
  })

  test('calls clientCertificate()', ({ assert }) => {
    const spy = sinon.spy(certs, 'certificate')
    certs.certificates(5)
    assert.equal(spy.callCount, 5)
  })
})
