import {
  acceptance,
  exists,
  query,
  visible,
} from "discourse/tests/helpers/qunit-helpers";
import { test } from "qunit";
import { click, currentURL, fillIn, findAll, visit } from "@ember/test-helpers";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import {
  getAdminTestingWizard,
  getCreatedWizard,
  getCustomFields,
  getSuppliers,
  getUniqueWizard,
  getUnsubscribedAdminWizards,
  getWizard,
} from "../helpers/admin-wizard";

acceptance("Admin | Custom Wizard Unsubscribed", function (needs) {
  needs.user();
  needs.settings({
    custom_wizard_enabled: true,
    available_locales: JSON.stringify([{ name: "English", value: "en" }]),
  });

  needs.pretender((server, helper) => {
    server.get("/admin/wizards/wizard", () => {
      return helper.response(getWizard);
    });
    server.get("/admin/wizards/custom-fields", () => {
      return helper.response(getCustomFields);
    });
    server.get("/admin/wizards/subscription", () => {
      return helper.response(getUnsubscribedAdminWizards);
    });
    server.get("/admin/wizards/api", () => {
      return helper.response({ success: "OK" });
    });
    server.get("/admin/customize/user_fields", () => {
      return helper.response({ user_fields: [] });
    });
    server.get("/admin/wizards/wizard/this_is_testing_wizard", () => {
      return helper.response(getAdminTestingWizard);
    });
    server.put("/admin/wizards/wizard/new_wizard_for_testing", () => {
      return helper.response({
        success: "OK",
        wizard_id: "new_wizard_for_testing",
      });
    });
    server.get("/admin/wizards/wizard/new_wizard_for_testing", () => {
      return helper.response(getCreatedWizard);
    });
    server.get("/admin/wizards/wizard/unique_wizard", () => {
      return helper.response(getUniqueWizard);
    });
    server.get("/admin/plugins/subscription-client/suppliers", () => {
      return helper.response(getSuppliers);
    });
  });

  async function appendText(selector, text) {
    let element = document.querySelector(selector);
    if (element) {
      let currentValue = element.value;
      let newValue = currentValue + text;
      await fillIn(selector, newValue);
    }
  }

  test("Displaying all tabs except API", async (assert) => {
    await visit("/admin/wizards");
    const list = find(".admin-controls li");
    const count = list.length;
    assert.equal(count, 5, "There should be 5 admin tabs");
  });

  test("shows unauthorized and unsubscribed", async (assert) => {
    await visit("/admin/wizards");
    assert.ok(
      exists(".supplier-authorize .btn-primary"),
      "the authorize button is shown."
    );
    assert.strictEqual(
      query("button.wizard-subscription-badge span").innerText.trim(),
      "Subscribe"
    );
  });

  test("creating a new wizard", async (assert) => {
    await visit("/admin/wizards/wizard");
    await click(".admin-wizard-controls button");
    assert.ok(
      query(".message-content").innerText.includes(
        "You're creating a new wizard"
      ),
      "it displays wizard creation message"
    );
    const wizardTitle = "New wizard for testing";
    await fillIn(".wizard-header input", wizardTitle);
    assert.equal(
      $(".wizard-header input").val(),
      wizardTitle,
      "The title input is inserted"
    );
    const wizardLink = find("div.wizard-url a");
    assert.equal(wizardLink.length, 1, "Wizard link was created");
    await click(".btn-after-time");
    assert.ok(
      exists(".d-date-time-input .d-time-input span.name"),
      "a time selector is shown"
    );
    let timeText = query(
      ".d-date-time-input .d-time-input span.name"
    ).innerText;
    const regex = /\d\d\:\d\d/;
    assert.ok(regex.test(timeText));
    assert.equal(
      $.trim($("a[title='Subscribe to use these features']").text()),
      "Not Subscribed",
      "Show messsage and link of user not subscribed"
    );
    assert.equal(
      find(".wizard-subscription-container").length,
      1,
      "Wizard subscription features are not accesible"
    );
    await click(".step .link-list button");
    const stepOneText = "step_1 (step_1)";
    const stepOneBtn = find(`.step button:contains(${stepOneText})`);
    assert.equal(stepOneBtn.length, 1, "Creating a step");
    const stepTitle = "step title";
    await fillIn(".wizard-custom-step input[name='title']", stepTitle);
    const stepButtonText = $.trim(
      $(".step div[data-id='step_1'] button").text()
    );
    assert.ok(
      stepButtonText.includes(stepTitle),
      "The step button changes according to title"
    );
    assert.equal(
      find(".wizard-subscription-container").length,
      2,
      "Steps subscription features are not accesible"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      "Input in step description composer"
    );
    await click(".wizard-custom-step .wizard-editor-gutter button:first-child");
    assert.strictEqual(
      query(
        ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper p"
      ).textContent.trim(),
      "Input in step description composer"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      "\n\n**Bold text**"
    );
    let boldText = await query(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper strong"
    ).innerHTML.trim();
    assert.strictEqual(
      boldText,
      "Bold text",
      "The bold text in the preview wrapper should be 'Bold Text'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      "\n\n*emphasized text*"
    );
    let empText = await query(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper em"
    ).innerHTML.trim();
    assert.strictEqual(
      empText,
      "emphasized text",
      "The emphasized text in the preview wrapper should be 'emphasized text'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      "\n\n> Blockqoute text"
    );
    let blockquoteText = await query(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper blockquote p"
    ).innerHTML.trim();
    assert.strictEqual(
      blockquoteText,
      "Blockqoute text",
      "The emphasized text in the preview wrapper should be 'Blockqoute text'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      `\n\n\`\`\`
                              \code text
                              \n\`\`\``
    );
    let codeText = await query(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper code"
    ).innerHTML.trim();
    assert.strictEqual(
      codeText,
      "code text",
      "The emphasized text in the preview wrapper should be 'code text'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      `\n\n* List item\n* List item`
    );
    let listItems = findAll(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper ul li"
    );
    assert.strictEqual(
      listItems.length,
      2,
      "There should be two list items in the unordered list in the preview wrapper"
    );
    assert.strictEqual(
      listItems[0].textContent.trim(),
      "List item",
      "The first list item should be 'List item'"
    );
    assert.strictEqual(
      listItems[1].textContent.trim(),
      "List item",
      "The second list item should be 'List item'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      `\n\n1. List item\n1. List item`
    );
    let orderedListItems = findAll(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper ol li"
    );
    assert.strictEqual(
      orderedListItems.length,
      2,
      "There should be two list items in the ordered list in the preview wrapper"
    );
    assert.strictEqual(
      orderedListItems[0].textContent.trim(),
      "List item",
      "The first list item should be 'List item'"
    );
    assert.strictEqual(
      orderedListItems[1].textContent.trim(),
      "List item",
      "The second list item should be 'List item'"
    );
    await appendText(
      ".wizard-custom-step .wizard-text-editor textarea",
      `\n\n`
    );
    await click(
      ".wizard-custom-step .wizard-text-editor .d-editor button.link"
    );
    assert.ok(
      exists(".d-modal.insert-hyperlink-modal"),
      "hyperlink modal visible"
    );

    await fillIn(".d-modal__body.insert-link .inputs .link-url", "google.com");
    await fillIn(".d-modal__body.insert-link .inputs .link-text", "Google");
    await click(".d-modal__footer button.btn-primary");
    let urlText = await query(
      ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper a"
    ).innerHTML.trim();
    assert.strictEqual(
      urlText,
      "Google",
      "The link text in the preview wrapper should be 'Google'"
    );
    await click(
      ".wizard-custom-step .wizard-text-editor .d-editor button.local-dates"
    );

    assert.ok(
      exists(".d-modal.discourse-local-dates-create-modal"),
      "Insert date-time modal visible"
    );

    assert.ok(
      !exists(
        ".discourse-local-dates-create-modal .d-modal__body .advanced-options"
      ),
      "Advanced mode not visible"
    );
    await click(".d-modal__footer button.advanced-mode-btn");
    assert.ok(
      exists(
        ".discourse-local-dates-create-modal .d-modal__body .advanced-options"
      ),
      "Advanced mode is visible"
    );
    await click(".d-modal__footer button.btn-primary");
    assert.ok(
      exists(
        ".wizard-custom-step .wizard-text-editor .d-editor-preview-wrapper span.discourse-local-date"
      ),
      "Date inserted"
    );

    await click(".field .link-list button");
    assert.ok(
      !visible(".wizard-custom-field button.undo-changes"),
      "clear button is not rendered"
    );
    const fieldOneText = "step_1_field_1 (step_1_field_1)";
    const fieldOneBtn = find(`.field button:contains(${fieldOneText})`);
    assert.equal(fieldOneBtn.length, 1, "Creating a field");
    const fieldTitle = "field title";
    await fillIn(".wizard-custom-field input[name='label']", fieldTitle);
    assert.ok(
      visible(".wizard-custom-field button.undo-changes"),
      "clear button is rendered after filling content"
    );
    let fieldButtonText = $.trim(
      $(".field div[data-id='step_1_field_1'] button").text()
    );
    assert.ok(
      fieldButtonText.includes(fieldTitle),
      "The step button changes according to title"
    );
    await fillIn(
      ".wizard-custom-field textarea[name='description']",
      "First step field description"
    );
    await click(`.wizard-custom-field button.undo-changes`);
    fieldButtonText = $(".field div[data-id='step_1_field_1'] button")
      .text()
      .trim();
    assert.ok(
      fieldButtonText.includes("step_1_field_1 (step_1_field_1)"),
      "The field button changes to default title after clear button is clicked"
    );
    await fillIn(".wizard-custom-field input[name='label']", fieldTitle);
    await fillIn(
      ".wizard-custom-field textarea[name='description']",
      "First step field description"
    );
    const fieldTypeDropdown = selectKit(
      ".wizard-custom-field .setting-value .select-kit"
    );
    await fieldTypeDropdown.expand();
    await fieldTypeDropdown.selectRowByValue("text");
    assert.ok(
      query(".wizard-custom-field .message-content").innerText.includes(
        "You're editing a field"
      ),
      "Text tipe for field correctly selected"
    );
    assert.equal(
      find(".wizard-subscription-container").length,
      3,
      "Field subscription features are not accesible"
    );
    await click(".action .link-list button");
    const actionOneText = "action_1 (action_1)";
    const actionOneBtn = find(`.action button:contains(${actionOneText})`);
    assert.equal(actionOneBtn.length, 1, "Creating an action");
    assert.ok(
      query(
        ".wizard-custom-action .wizard-message .message-content"
      ).innerText.includes("Select an action type"),
      "it displays wizard select action message"
    );
    const actionTypeDropdown = selectKit(
      ".wizard-custom-action .setting-value .select-kit"
    );
    await actionTypeDropdown.expand();
    const listEnabled = findAll(
      ".wizard-custom-action .setting .setting-value ul li:not(.disabled)"
    );
    const listDisabled = findAll(
      ".wizard-custom-action .setting .setting-value ul li.disabled"
    );
    assert.ok(
      listDisabled.length === 7,
      "disabled items displayed correctly in action dropdown"
    );
    assert.ok(
      listEnabled.length === 4,
      "Enabled items displayed correctly in action dropdown"
    );
    await actionTypeDropdown.selectRowByValue("create_topic");
    assert.ok(
      query(".wizard-custom-action .message-content").innerText.includes(
        "You're editing an action"
      ),
      "Create type action correctly selected"
    );
    let listTopicSettings = findAll(
      ".admin-wizard-container .wizard-custom-action .setting"
    );
    assert.ok(
      listTopicSettings.length === 10,
      "Display all settings of create topic"
    );
    await actionTypeDropdown.expand();
    await actionTypeDropdown.selectRowByValue("open_composer");
    listTopicSettings = findAll(
      ".admin-wizard-container .wizard-custom-action .setting"
    );
    assert.ok(
      listTopicSettings.length === 8,
      "Display all settings of open composer"
    );
    await actionTypeDropdown.expand();
    await actionTypeDropdown.selectRowByValue("update_profile");
    listTopicSettings = findAll(
      ".admin-wizard-container .wizard-custom-action .setting"
    );
    assert.ok(
      listTopicSettings.length === 4,
      "Display all settings of update profile"
    );
    await actionTypeDropdown.expand();
    await actionTypeDropdown.selectRowByValue("route_to");
    listTopicSettings = findAll(
      ".admin-wizard-container .wizard-custom-action .setting"
    );
    assert.ok(
      listTopicSettings.length === 4,
      "Display all settings of route to"
    );
    await actionTypeDropdown.expand();
    await click('[data-name="Select a type"]');
    listTopicSettings = findAll(
      ".admin-wizard-container .wizard-custom-action .setting"
    );
    assert.ok(
      listTopicSettings.length === 2,
      "the settings options is empty when no action is selected"
    );
    await actionTypeDropdown.expand();
    await actionTypeDropdown.selectRowByValue("create_topic");
    const fieldsContentIf = [4, 8];
    for (let i = 0; i < fieldsContentIf.length; i++) {
      await click(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) button`
      );
      let selectKitInsideThirdSetting = await selectKit(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .select-kit`
      );
      await selectKitInsideThirdSetting.expand();
      await selectKitInsideThirdSetting.selectRowByIndex(1);
      await fillIn(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .key input`,
        "Action title"
      );
      await fillIn(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .value input`,
        "Some value"
      );
      await fillIn(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .output input`,
        "Result text"
      );
      const actualTitle = query(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .key input`
      ).value;
      const actualValue = query(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .value input`
      ).value;
      const actualResultText = query(
        `.admin-wizard-container .wizard-custom-action .setting:nth-of-type(${fieldsContentIf[i]}) .output input`
      ).value;

      assert.strictEqual(actualTitle, "Action title", "Title is correct");
      assert.strictEqual(actualValue, "Some value", "Value is correct");
      assert.strictEqual(actualResultText, "Result text", "Text is correct");
    }
    assert.ok(
      !visible('.admin-wizard-buttons button:contains("Delete Wizard")'),
      "delete wizard button not displayed"
    );
    await click(".admin-wizard-buttons button");
    assert.equal(
      currentURL(),
      "/admin/wizards/wizard/new_wizard_for_testing",
      "Wizard saved successfully"
    );
    assert.ok(
      visible('.admin-wizard-buttons button:contains("Delete Wizard")'),
      "delete wizard button visible"
    );
  });
  test("viewing content for a selected wizard", async (assert) => {
    await visit("/admin/wizards/wizard");
    assert.ok(
      query(".message-content").innerText.includes(
        "Select a wizard, or create a new one"
      ),
      "it displays wizard message"
    );
    const wizards = selectKit(".select-kit");
    await wizards.expand();

    await wizards.selectRowByValue("unique_wizard");
    assert.ok(
      query(".message-content").innerText.includes("You're editing a wizard"),
      "it displays wizard message for a selected wizard"
    );
    assert.equal(
      query(".admin-wizard-container .wizard-header input").value,
      getUniqueWizard.name,
      "The wizard name is correctly displayed"
    );
    // Save wizard Submissions
    assert.equal(
      query(".wizard-settings .setting:nth-of-type(1) input").checked,
      getUniqueWizard.save_submissions,
      "The save submissions flag is correctly set"
    );

    // Multiple Submissions
    assert.equal(
      query(".wizard-settings .setting:nth-of-type(2) input").checked,
      getUniqueWizard.multiple_submissions,
      "The multiple submissions flag is correctly set"
    );

    // After Signup
    assert.equal(
      query(".wizard-settings .setting:nth-of-type(3) input").checked,
      getUniqueWizard.after_signup,
      "The after signup flag is correctly set"
    );

    // Prompt Completion
    assert.equal(
      query(".wizard-settings .setting:nth-of-type(4) input").checked,
      getUniqueWizard.prompt_completion,
      "The prompt completion flag is correctly set"
    );
    // step content
    for (let i = 0; i < getUniqueWizard.steps.length; i++) {
      // click on the step that is needed
      await click(
        `.wizard-links.step .link-list div:nth-of-type(${
          i + 1
        }) button.btn-text`
      );
      assert.equal(
        query(".wizard-custom-step  input[name='title']").value,
        getUniqueWizard.steps[i].title,
        "Step title is correct"
      );
      assert.equal(
        query(".wizard-custom-step .wizard-text-editor textarea").value,
        getUniqueWizard.steps[i].description,
        "Step description is correct"
      );
      // field content
      for (let j = 0; j < getUniqueWizard.steps[i].fields.length; j++) {
        await click(
          `.wizard-links.field .link-list div:nth-of-type(${
            j + 1
          }) button.btn-text`
        );
        assert.equal(
          query(".wizard-custom-field.visible .setting:nth-of-type(1) input")
            .value,
          getUniqueWizard.steps[i].fields[j].label,
          "Field title is correct"
        );
        assert.equal(
          query(".wizard-custom-field.visible .setting:nth-of-type(3) textarea")
            .value,
          getUniqueWizard.steps[i].fields[j].description,
          "Field description is correct"
        );
        let selectTypeElement = document.querySelector(
          `.admin-wizard-container .wizard-custom-field.visible .setting:nth-of-type(5) .select-kit`
        );
        let summaryElement = selectTypeElement.querySelector("summary");
        assert.equal(
          summaryElement.getAttribute("data-value"),
          getUniqueWizard.steps[i].fields[j].type,
          "The correct data-value is selected"
        );
      }
    }
  });
});