/* eslint-disable @typescript-eslint/no-explicit-any */
import { test } from '@japa/runner'
import {
  ExportArcHistoryRequest,
  ExportArcWebsocketUrl,
  ExportArcUrlHistory,
  ExportArcVariable,
  ExportArcAuthData,
  ExportArcHostRule,
  ARCVariable,
  ARCProject,
  ARCSavedRequest,
  LegacyExportProcessor,
  LegacyMock,
} from '../../../src/legacy.js'

const generator = new LegacyMock()

function mockRev(data: any[]): any[] {
  return data.map((item) => {
    item._rev = generator.types.string()
    return item
  })
}

test.group('prepareRequestsList()', (group) => {
  let data: ARCSavedRequest[]
  let instance: LegacyExportProcessor
  group.each.setup(async () => {
    instance = new LegacyExportProcessor(false)
    const projects = generator.http.listProjects(20)
    const insert = generator.http.savedData(20, 20, { projects }).requests
    data = mockRev(insert)
  })

  test('returns an array', ({ assert }) => {
    const result = instance.prepareRequestsList(data)
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    const result = instance.prepareRequestsList(data)
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('key is set', ({ assert }) => {
    const result = instance.prepareRequestsList(data)
    for (let i = 0, len = result.length; i < len; i++) {
      assert.typeOf(result[i].key, 'string')
    }
  })

  test('removes the legacyProject', ({ assert }) => {
    // @ts-expect-error Used in testing
    data[0].legacyProject = 'abc'
    delete data[0].projects
    const result = instance.prepareRequestsList(data)
    // @ts-expect-error Used in testing
    assert.isUndefined(result[0].legacyProject)
  })

  test('creates projects from a legacyProject', ({ assert }) => {
    // @ts-expect-error Used in testing
    data[0].legacyProject = 'abc'
    delete data[0].projects
    const result = instance.prepareRequestsList(data)
    assert.typeOf(result[0].projects, 'array')
    assert.equal(result[0].projects![0], 'abc')
  })

  test('adds to projects from the legacyProject', ({ assert }) => {
    data[0].projects = ['test']
    // @ts-expect-error Used in testing
    data[0].legacyProject = 'abc'
    const result = instance.prepareRequestsList(data)
    // @ts-expect-error Used in testing
    assert.isUndefined(result[0].legacyProject)
    assert.lengthOf(result[0].projects!, 2)
  })

  test('kind property is set', ({ assert }) => {
    const result = instance.prepareRequestsList(data)
    assert.equal(result[0].kind, 'ARC#HttpRequest')
  })
})

test.group('prepareProjectsList()', (group) => {
  let data: ARCProject[]
  let instance: LegacyExportProcessor

  group.each.setup(() => {
    instance = new LegacyExportProcessor(false)
    data = generator.http.listProjects(5)
    data = mockRev(data)
  })

  test('Result is an array', ({ assert }) => {
    const result = instance.prepareProjectsList(data)
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    const result = instance.prepareProjectsList(data)
    for (let i = 0, len = result.length; i < len; i++) {
      // @ts-expect-error Used in testing
      assert.notOk(result[i]._id, '_id is set')
      // @ts-expect-error Used in testing
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('key is set', ({ assert }) => {
    const ids = data.map((item) => item._id)
    const result = instance.prepareProjectsList(data)
    for (let i = 0, len = result.length; i < len; i++) {
      assert.equal(result[i].key, ids[i], 'Key is not set')
    }
  })

  test('kind property is set', ({ assert }) => {
    const result = instance.prepareProjectsList(data)
    assert.equal(result[0].kind, 'ARC#ProjectData')
  })
})

test.group('prepareHistoryDataList()', (group) => {
  let result: ExportArcHistoryRequest[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.http.listHistory()
    data = mockRev(data)
    result = instance.prepareHistoryDataList(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#HttpRequest')
  })
})

test.group('prepareWsUrlHistoryData()', (group) => {
  let result: ExportArcWebsocketUrl[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.urls.urls()
    data = mockRev(data)
    result = instance.prepareWsUrlHistoryData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#WebsocketHistoryData')
  })
})

test.group('prepareUrlHistoryData()', (group) => {
  let result: ExportArcUrlHistory[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.urls.urls()
    data = mockRev(data)
    result = instance.prepareUrlHistoryData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#UrlHistoryData')
  })
})

test.group('prepareVariablesData()', (group) => {
  let result: ExportArcVariable[]
  let removed: ARCVariable
  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.variables.listVariables()
    data = mockRev(data)
    // @ts-expect-error Used in testing
    data[1].environment = false
    removed = data[1]
    result = instance.prepareVariablesData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#Variable')
  })

  test('ignores items that have no environment', ({ assert }) => {
    const item = result.find((v) => v.key === removed._id)
    assert.notOk(item)
  })
})

test.group('prepareAuthData()', (group) => {
  let result: ExportArcAuthData[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.authorization.basicList()
    data = mockRev(data)
    result = instance.prepareAuthData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#AuthData')
  })
})

test.group('prepareCookieData()', (group) => {
  let result: any[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.cookies.cookies()
    data = mockRev(data)
    result = instance.prepareCookieData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#Cookie')
  })
})

test.group('prepareCookieData() with electron cookies', (group) => {
  let result: any[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(true)
    let data = generator.cookies.cookies()
    data = mockRev(data)
    result = instance.prepareCookieData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('does not set key', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.isUndefined(result[i].key)
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#Cookie')
  })
})

test.group('prepareHostRulesData()', (group) => {
  let result: ExportArcHostRule[]

  group.each.setup(async () => {
    const instance = new LegacyExportProcessor(false)
    let data = generator.hostRules.rules()
    data = mockRev(data)
    result = instance.prepareHostRulesData(data)
  })

  test('Result is an array', ({ assert }) => {
    assert.typeOf(result, 'array')
  })

  test('_rev and _id is removed', ({ assert }) => {
    for (let i = 0, len = result.length; i < len; i++) {
      assert.notOk(result[i]._id, '_id is set')
      assert.notOk(result[i]._rev, '_rev is set')
    }
  })

  test('kind property is set', ({ assert }) => {
    assert.equal(result[0].kind, 'ARC#HostRule')
  })
})

test.group('createExportObject()', (group) => {
  let instance: LegacyExportProcessor

  group.each.setup(() => {
    instance = new LegacyExportProcessor(true)
  })

  test('returns an object', ({ assert }) => {
    const result = instance.createExportObject([], { appVersion: '123', provider: 'xyz' })
    assert.typeOf(result, 'object')
  })

  test('has export time', ({ assert }) => {
    const result = instance.createExportObject([], { appVersion: '123', provider: 'xyz' })
    assert.typeOf(result.createdAt, 'string')
  })

  test('has application version', ({ assert }) => {
    const result = instance.createExportObject([], {
      appVersion: '1.2.3',
      provider: 'xyz',
    })
    assert.equal(result.version, '1.2.3')
  })

  test('has export kind', ({ assert }) => {
    const result = instance.createExportObject([], {
      appVersion: '123',
      kind: 'ARC#test',
      provider: 'xyz',
    })
    assert.equal(result.kind, 'ARC#test')
  })

  test('has loadToWorkspace property', ({ assert }) => {
    const result = instance.createExportObject([], {
      appVersion: '123',
      skipImport: true,
      provider: 'xyz',
    })
    assert.isTrue(result.loadToWorkspace)
  })
})

test.group('prepareItem() - cookies', (group) => {
  let data: any[]
  let instance: LegacyExportProcessor
  group.each.setup(async () => {
    instance = new LegacyExportProcessor(false)
    const cookies = generator.cookies.cookies()
    data = mockRev(cookies)
  })

  test('prepares cookie data', ({ assert }) => {
    const result = instance.prepareItem('cookies', data)!
    assert.equal(result[0].kind, 'ARC#Cookie')
  })
})

test.group('prepareItem() - clientcertificates', (group) => {
  let data: any[]
  let instance: LegacyExportProcessor
  group.each.setup(async () => {
    instance = new LegacyExportProcessor(false)
    let certs = generator.certificates.clientCertificates(2)
    certs = mockRev(certs)
    data = []
    certs.forEach((obj) => {
      const item = obj
      const certificate = /** @type Certificate */ item.cert
      const keyCertificate = /** @type Certificate */ item.key
      const dataDoc = {
        cert: generator.certificates.toStore(certificate),
      }
      delete (item as any).cert
      if (item.key) {
        // @ts-expect-error Used in testing
        dataDoc.key = generator.certificates.toStore(keyCertificate)
        delete item.key
      }
      // @ts-expect-error Used in testing
      item._id = `index-id-${Date.now()}`
      // @ts-expect-error Used in testing
      dataDoc._id = `data-id-${Date.now()}`
      // @ts-expect-error Used in testing
      item.dataKey = `data-${Date.now()}`
      data.push({ item, data: dataDoc })
    })
  })

  test('prepares client certificates data', ({ assert }) => {
    const result = instance.prepareItem('clientcertificates', data)!
    assert.equal(result[0].kind, 'ARC#ClientCertificate')
  })
})

test.group('prepareItem() - default', (group) => {
  let instance: LegacyExportProcessor
  group.each.setup(async () => {
    instance = new LegacyExportProcessor(false)
  })

  test('returns undefined', ({ assert }) => {
    // @ts-expect-error Used in testing
    const result = instance.prepareItem('unknown', [])
    assert.isUndefined(result)
  })
})
