import { test } from '@japa/runner'
import { ProjectItem } from '../../../src/models/ProjectItem.js'
import { HttpProject } from '../../../src/models/HttpProject.js'
import { Kind as ProjectRequestKind } from '../../../src/models/ProjectRequest.js'
import { ProjectFolderKind } from '../../../src/models/kinds.js'

test.group('ProjectItem.projectRequest()', () => {
  test('creates the item', ({ assert }) => {
    const project = HttpProject.fromName('test')
    const item = ProjectItem.projectRequest(project, 'r1')
    assert.equal(item.kind, ProjectRequestKind)
    assert.equal(item.key, 'r1')
  })
})

test.group('ProjectItem.projectFolder()', () => {
  test('creates the item', ({ assert }) => {
    const project = HttpProject.fromName('test')
    const item = ProjectItem.projectFolder(project, 'f1')
    assert.equal(item.kind, ProjectFolderKind)
    assert.equal(item.key, 'f1')
  })
})

test.group('ProjectItem.isProjectItem()', () => {
  test('returns true for a folder item', ({ assert }) => {
    const project = HttpProject.fromName('test')
    const item = ProjectItem.projectFolder(project, 'f1')
    assert.isTrue(ProjectItem.isProjectItem(item))
  })

  test('returns true for a request item', ({ assert }) => {
    const project = HttpProject.fromName('test')
    const item = ProjectItem.projectRequest(project, 'r1')
    assert.isTrue(ProjectItem.isProjectItem(item))
  })

  test('returns false when not an item', ({ assert }) => {
    assert.isFalse(ProjectItem.isProjectItem({} as ProjectItem))
  })
})

test.group('ProjectItem > constructor()', (group) => {
  let project: HttpProject
  group.each.setup(() => {
    project = HttpProject.fromName('test')
  })

  test('creates a default item for "http-request" type', ({ assert }) => {
    const item = new ProjectItem(project, 'http-request')
    assert.equal(item.kind, ProjectRequestKind)
    assert.equal(item.key, '')
  })

  test('creates a default item for "folder" type', ({ assert }) => {
    const item = new ProjectItem(project, 'folder')
    assert.equal(item.kind, ProjectFolderKind)
    assert.equal(item.key, '')
  })

  test('creates an instance from a schema', ({ assert }) => {
    const schema = ProjectItem.projectRequest(project, 'r1').toJSON()
    const item = new ProjectItem(project, schema)
    assert.equal(item.kind, ProjectRequestKind)
    assert.equal(item.key, 'r1')
  })

  test('creates an instance from a serialized schema', ({ assert }) => {
    const schema = JSON.stringify(ProjectItem.projectRequest(project, 'r1'))
    const item = new ProjectItem(project, schema)
    assert.equal(item.kind, ProjectRequestKind)
    assert.equal(item.key, 'r1')
  })

  test('throws when input is not defined', ({ assert }) => {
    assert.throws(() => {
      // @ts-expect-error Used in testing
      new ProjectItem(project, undefined)
    })
  })
})

test.group('ProjectItem > toJSON()', (group) => {
  let project: HttpProject
  group.each.setup(() => {
    project = HttpProject.fromName('test')
  })

  test('sets the kind', ({ assert }) => {
    const item = ProjectItem.projectRequest(project, 'r1').toJSON()
    assert.equal(item.kind, ProjectRequestKind)
  })

  test('sets the key', ({ assert }) => {
    const item = ProjectItem.projectRequest(project, 'r1').toJSON()
    assert.equal(item.key, 'r1')
  })
})

test.group('ProjectItem > getItem()', (group) => {
  let project: HttpProject
  group.each.setup(() => {
    project = HttpProject.fromName('test')
  })

  test('returns a definition of a request', ({ assert }) => {
    const created = project.addRequest('https://api.com')
    const definition = project.items[0].getItem()
    assert.deepEqual(definition, created)
  })

  test('returns a definition of a folder', ({ assert }) => {
    const created = project.addFolder('a folder')
    const definition = project.items[0].getItem()
    assert.deepEqual(definition, created)
  })
})

test.group('ProjectItem > getParent()', (group) => {
  let project: HttpProject
  group.each.setup(() => {
    project = HttpProject.fromName('test')
  })

  test('returns the project for a root level items', ({ assert }) => {
    project.addRequest('https://api.com')
    const definition = project.items[0].getParent()
    assert.isTrue(definition === project)
  })

  test('returns a parent folder', ({ assert }) => {
    const f1 = project.addFolder('f1')
    f1.addFolder('f2') // This creates an item in f1.items
    const definition = f1.items[0].getParent()
    assert.isTrue(definition === f1)
  })
})
