import {
  click,
  currentURL,
  fillIn,
  settled,
  // pauseTest,
  visit,
} from "@ember/test-helpers"
import {
  authenticateSession,
  invalidateSession,
} from "ember-simple-auth/test-support"
import { setupApplicationTest } from "ember-qunit"
import setupMirage from "ember-cli-mirage/test-support/setup-mirage"
import { module, test } from "qunit"
import sharedScenario from "../../mirage/scenarios/shared"

let runner = {
  testRole: "Course",
  model: "course",
  forNewRecord: {
    fillIn: [
      {
        sel: `[data-test-kb-form-kb-input-id='createFormCoursename']`,
        val: "Acceptance Test Course",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='createFormCoursetrainer']`,
        val: "Bob Boots",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='createFormCourseduration']`,
        val: "5",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='createFormCourseexpires']`,
        val: "24",
      },
    ],
    click: [],
  },
  forEditRecord: {
    fillIn: [
      {
        sel: `[data-test-kb-form-kb-input-id='editFormCoursename']`,
        val: "Acceptance Test Passed",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='editFormCoursetrainer']`,
        val: "Harriet Hat",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='editFormCourseduration']`,
        val: "3",
      },
      {
        sel: `[data-test-kb-form-kb-input-id='editFormCourseexpires']`,
        val: "12",
      },
    ],
    click: [],
  },
  forManyToMany: [
    {
      testRole: "CourseSkills",
      route: "skills",
      model: "skill",
      childDefault: { skill_type: "SK", course: [1] },
      parentDefault: { skill: [1, 2, 3] },
      forNewRecord: {
        fillIn: [
          {
            sel: `[data-test-kb-form-kb-input-id='createFormCourseSkillname']`,
            val: "Acceptance Test Skill",
          },
        ],
        click: [
          "[data-test-kb-form-kb-input-id='createFormCourseSkilldepartmentsHR']",
          "[data-test-kb-form-kb-input-id='createFormCourseSkillproceduresCHEMICAL']",
        ],
      },
    },
    {
      testRole: "CourseSkills",
      route: "competencies",
      model: "skill",
      childDefault: { skill_type: "CM", course: [1] },
      parentDefault: { skill: [1, 2, 3] },
      forNewRecord: {
        fillIn: [
          {
            sel: `[data-test-kb-form-kb-input-id='createFormCourseSkillname']`,
            val: "Acceptance Test Competency",
          },
        ],
        click: [
          "[data-test-kb-form-kb-input-id='createFormCourseSkilldepartmentsOPS']",
          "[data-test-kb-form-kb-input-id='createFormCourseSkillproceduresFUELS']",
        ],
      },
    },
  ],
}

module(`Acceptance | ${runner.model}`, function (hooks) {
  setupApplicationTest(hooks)
  setupMirage(hooks)

  hooks.beforeEach(function () {
    authenticateSession({ token: "faketoken" })
  })

  test(`/${runner.model}: redirects unauthenticated`, async function (assert) {
    sharedScenario(this.server)
    await invalidateSession()
    await settled()
    await visit(`/${runner.model}`)
    assert.equal(currentURL(), "/login", `routed /login`)
  })

  test(`/${runner.model}: lists`, async function (assert) {
    sharedScenario(this.server)
    this.server.createList(runner.model, 3)
    await settled()
    await visit(`/${runner.model}`)
    assert.equal(currentURL(), `/${runner.model}`, `routed /${runner.model}`)
    assert
      .dom(`[data-test-kb-${runner.model}-list-id='listCourses']`)
      .exists({ count: 1 })
    assert
      .dom(`[data-test-kb-${runner.model}-list-row-id]`)
      .exists({ count: 3 })
    assert
      .dom(
        `
        [data-test-kb-${runner.model}-list-row-id-id='1']
      `
      )
      .exists({ count: 1 })
    assert
      .dom(`[data-test-kb-${runner.model}-list-row-id-id='2']`)
      .exists({ count: 1 })
    assert
      .dom(`[data-test-kb-${runner.model}-list-row-id-id='3']`)
      .exists({ count: 1 })
  })

  test(`/${runner.model}/create`, async function (assert) {
    sharedScenario(this.server)
    // Visit the create route.
    await visit(`/${runner.model}/create`)
    await settled()
    // Fill in all the required fields.
    assert.equal(
      currentURL(),
      `/${runner.model}/create`,
      `routed /${runner.model}/create`
    )
    for (let fill of runner.forNewRecord.fillIn) {
      await fillIn(fill.sel, fill.val)
    }
    for (let sel of runner.forNewRecord.click) {
      await click(sel)
    }
    // Submit the form.
    await click("[data-test-kb-form-submit-id]")
    await settled()
    // Check redirect to the model detail route; all content rendered.
    assert.equal(
      currentURL(),
      `/${runner.model}/1`,
      `routed /${runner.model}/1`
    )
    for (let fill of runner.forNewRecord.fillIn) {
      assert
        .dom(`[data-test-kb-${runner.model}-detail-id]`)
        .includesText(fill.val)
    }
  })

  test(`/${runner.model}/edit`, async function (assert) {
    sharedScenario(this.server)
    this.server.create(runner.model, runner.forNewRecord)
    await settled()
    // Visit the edit route.
    await visit(`/${runner.model}/1/edit`)
    await settled()
    // Test presence of values in form.
    assert.equal(
      currentURL(),
      `/${runner.model}/1/edit`,
      `route /${runner.model}/1/edit`
    )
    for (let fill of runner.forEditRecord.fillIn) {
      await fillIn(fill.sel, fill.val)
    }
    for (let sel of runner.forEditRecord.click) {
      await click(sel)
    }
    // Submit the form.
    await click("[data-test-kb-form-submit-id]")
    await settled()
    // Check redirect to the model detail route; all content rendered.
    assert.equal(
      currentURL(),
      `/${runner.model}/1`,
      `routed /${runner.model}/1`
    )
    for (let fill of runner.forEditRecord.fillIn) {
      assert
        .dom(`[data-test-kb-${runner.model}-detail-id]`)
        .includesText(fill.val)
    }
  })

  test(`/${runner.model}/delete`, async function (assert) {
    sharedScenario(this.server)
    this.server.create(runner.model)
    await settled()
    await visit(`/${runner.model}`)
    assert
      .dom(`[data-test-kb-${runner.model}-list-row-id]`)
      .exists({ count: 1 })
    // Visit the delete route.
    await visit(`/${runner.model}/1/delete`)
    await settled()
    // Submit the form.
    await click("[data-test-kb-model-delete-button-id]")
    await settled()
    // Check record is removed.
    await visit(`/${runner.model}`)
    assert.dom(`[data-test-kb-${runner.model}-list-row-id]`).doesNotExist()
    assert
      .dom(`[data-test-kb-wireframe-main-model-not-found-id]`)
      .includesText(`No ${runner.model}s found.`)
  })

  runner.forManyToMany.forEach(manySide => {
    // Runs the same tests for each many route.
    test(`/${runner.model}/id/${manySide.route}: list and remove many2many`, async function (assert) {
      sharedScenario(this.server)
      // Create parent and child records with a many2many relationship.
      this.server.createList(manySide.model, 3, manySide.childDefault)
      this.server.create(runner.model, manySide.parentDefault)
      await settled()
      // Visit the "Children" route.
      await visit(`/${runner.model}/1/${manySide.route}`)
      assert.equal(
        currentURL(),
        `/${runner.model}/1/${manySide.route}`,
        `routed /${runner.model}/1/${manySide.route}`
      )
      // Check that the children are visible.
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='remove${manySide.testRole}']`
        )
        .exists({ count: 3 })
      // Check that we can remove a child.
      await click(
        `[data-test-kb-confirm-action-id='remove${manySide.testRole}']`
      )
      await settled()
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='remove${manySide.testRole}']`
        )
        .exists({ count: 2 })
    })

    test(`/${runner.model}/id/${manySide.route}/edit: add many2many`, async function (assert) {
      sharedScenario(this.server)
      // Remove the manySide sides of the defaults.
      delete manySide.childDefault[runner.model]
      delete manySide.parentDefault[manySide.model]
      this.server.createList(manySide.model, 3, manySide.childDefault)
      this.server.create(runner.model, manySide.parentDefault)
      await settled()
      // Visit the "Click to Add Children" route.
      await visit(`/${runner.model}/1/${manySide.route}/edit`)
      assert.equal(
        currentURL(),
        `/${runner.model}/1/${manySide.route}/edit`,
        `routed /${runner.model}/1/${manySide.route}/edit`
      )
      // Check that the 3 records are available in the "Click to Add" list.
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='add${manySide.testRole}']`
        )
        .exists({ count: 3 })
      // Check we can add it to the "List Children" table.
      await click(`[data-test-kb-confirm-action-id='add${manySide.testRole}']`)
      await settled()
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='add${manySide.testRole}']`
        )
        .exists({ count: 2 })
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='remove${manySide.testRole}']`
        )
        .exists({ count: 1 })
      // Check we can remove it again.
      await click(
        `[data-test-kb-confirm-action-id='remove${manySide.testRole}']`
      )
      await settled()
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='add${manySide.testRole}']`
        )
        .exists({ count: 3 })
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='remove${manySide.testRole}']`
        )
        .exists({ count: 0 })
    })

    test(`/${runner.model}/id/${manySide.model}/new many2many`, async function (assert) {
      sharedScenario(this.server)
      this.server.create(runner.model, runner.forNewRecord)
      await settled()
      await visit(`/${runner.model}/1/${manySide.route}/new`)
      assert.equal(
        currentURL(),
        `/${runner.model}/1/${manySide.route}/new`,
        `routed /${runner.model}/1/${manySide.route}/new`
      )
      for (let fill of manySide.forNewRecord.fillIn) {
        await fillIn(fill.sel, fill.val)
      }
      for (let sel of manySide.forNewRecord.click) {
        await click(sel)
      }
      // Submit the form.
      await click("[data-test-kb-form-submit-id]")
      await settled()
      // Check redirect to the model detail route; all content rendered.
      assert.equal(
        currentURL(),
        `/${runner.model}/1/${manySide.route}`,
        `routed /${runner.model}/1/${manySide.route}`
      )
      assert
        .dom(
          `[data-test-kb-${manySide.model}-list-row-id='remove${manySide.testRole}']`
        )
        .exists({ count: 1 })
    })
  })
})
