import { test, expect } from "../../../fixtures/index";
import { ContactPage } from "../../../pom/contact/contact.page";
import { LoginPage } from "../../../pom/login.page";
import { randomDate } from "../../../pom/utils/utlisFunc";
import { randomString, randomText } from "../../../utils/array";
import { verifyScreenshot } from "../../../utils/screenshot";

test.describe("CRUD operations for contact tests", async () => {
    let loginPage: LoginPage;
    let contactPage: ContactPage;

    test.beforeEach(async ({ page, conf }) => {
        loginPage = new LoginPage(page);
        contactPage = new ContactPage(page);
        contactPage.loadBusinessNames(
            conf.data.business_singular,
            conf.data.business_plural
        );

        await test.step("Navigate to login page", async () => {
            await loginPage.open();
            await page.waitForLoadState('networkidle');
        });

        await test.step("Perform login authentication", async () => {
            await loginPage.login(conf.data.username, conf.data.password);
            await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
        });

        if (conf.data.not_redirect) {
            return;
        }

        await test.step("Navigate to contact page", async () => {
            await contactPage.open();
            await page.waitForLoadState('networkidle');
        });
    });

    test("CONTACT_012 - Verify contact creation form validation", {
        tag: ["@CONTACT_012", "@contact", "@validate"],
    }, async ({ conf }) => {
        await test.step("Verify creation fails without required data", async () => {
            await contactPage.clickCreatePage();
            await contactPage.contactLoc.creating.createBtn.click();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();

            await expect(contactPage.contactLoc.creating.modalNotProvided).toBeVisible();
            await contactPage.contactLoc.creating.btnConfirmModalProvided.click();

            await expect(contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.empty_Fname).first()).toBeVisible();
            const countEmptyError = (await contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.empty_Fname).all()).length;
            expect(countEmptyError).toBe(2);
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Verify validation with invalid email", async () => {
            await contactPage.contactLoc.creating.email.fill(conf.data.invalid_data);
            await expect(contactPage.contactLoc.creating.email).toHaveValue(conf.data.invalid_data);

            await contactPage.contactLoc.creating.createBtn.click();
            await expect(contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.invalid_email)).toBeVisible();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Verify validation with data exceeding limits", async () => {
            const invalidData = conf.data.invalid_data;

            await contactPage.contactLoc.creating.firstName.fill(invalidData);
            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(invalidData);

            await contactPage.contactLoc.updating.inputLname.fill(invalidData);
            await expect(contactPage.contactLoc.updating.inputLname).toHaveValue(invalidData);

            await contactPage.contactLoc.updating.inputTag.fill(invalidData);
            await contactPage.contactLoc.updating.dropdownAddTag(invalidData).click();
            await expect(contactPage.contactLoc.updating.tagHadCreateUpdate(invalidData)).toBeVisible();
            await contactPage.dashboardLoc.modal.headerModal("New Contact").click();

            await contactPage.contactLoc.creating.createBtn.click();

            await expect(contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.exceed_Fname)).toBeVisible();
            await expect(contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.exceed_Lname)).toBeVisible();
            await expect(contactPage.dashboardLoc.creating.errorInput(conf.data.error_msg.exceed_tag)).toBeVisible();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });
    });

    test("CONTACT_013 - Verify successful contact creation without creating another", {
        tag: ["@CONTACT_013", "@contact", "@function"],
    }, async ({ conf }) => {
        const emailContact = await contactPage.getRanmdomEmail(conf.data.email);
        const firstName = conf.data.first_name;

        await test.step("Open contact creation modal", async () => {
            await contactPage.clickCreatePage();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Fill contact data and verify create another option is unchecked", async () => {
            await contactPage.contactLoc.creating.firstName.fill(firstName);
            await contactPage.contactLoc.creating.email.fill(emailContact);

            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
            await expect(contactPage.contactLoc.creating.email).toHaveValue(emailContact);
            await expect(contactPage.contactLoc.creating.createAnotherContact).not.toBeChecked();
        });

        await test.step("Create contact and verify success without keeping modal open", async () => {
            await contactPage.contactLoc.creating.createBtn.click();

            await expect(contactPage.contactLoc.creating.messageCreatetSuccess).toBeVisible();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).not.toBeVisible();
            await expect(contactPage.contactLoc.creating.dataFirstNameAdd(firstName)).toBeVisible();
            await expect(contactPage.contactLoc.creating.dataEmailAdd(emailContact)).toBeVisible();
        });
    });

    test("CONTACT_014 - Verify successful contact creation with creating another option", {
        tag: ["@CONTACT_014", "@contact", "@function"],
    }, async ({ conf }) => {
        const emailContact = await contactPage.getRanmdomEmail(conf.data.email);
        const firstName = conf.data.first_name;

        await test.step("Open contact creation modal", async () => {
            await contactPage.clickCreatePage();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Fill contact data and enable create another contact option", async () => {
            // Fill business
            await contactPage.dashboardLoc.modal.inputByID("autocomplete_business_provider_id").fill(conf.data.business_name);
            await expect(contactPage.dashboardLoc.search.filter.popup.optionInput(conf.data.business_name)).toBeVisible();
            await contactPage.dashboardLoc.search.filter.popup.optionInput(conf.data.business_name).click();
            await contactPage.dashboardLoc.modal.inputContainByID("checkbox-use_business_address").check();
            await contactPage.dashboardLoc.common.popUpConfirm.click();

            await contactPage.contactLoc.creating.firstName.fill(firstName);
            await contactPage.contactLoc.creating.email.fill(emailContact);
            await contactPage.contactLoc.creating.createAnotherContact.check();

            await expect(contactPage.dashboardLoc.root).toMatchAriaSnapshot(contactPage.contactSnapshot.createAnotherContact);
            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
            await expect(contactPage.contactLoc.creating.email).toHaveValue(emailContact);
            await expect(contactPage.contactLoc.creating.createAnotherContact).toBeChecked();
        });

        await test.step("Create contact and verify modal remains open for another creation", async () => {
            await contactPage.contactLoc.creating.createBtn.click();
            await expect(contactPage.contactLoc.creating.messageCreatetSuccess).toBeVisible();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
            await expect(contactPage.contactLoc.creating.dataFirstNameAdd(firstName)).toBeVisible();
            await expect(contactPage.contactLoc.creating.dataEmailAdd(emailContact)).toBeVisible();
            await expect(contactPage.dashboardLoc.root).toMatchAriaSnapshot(contactPage.contactSnapshot.createAnotherContact);
        });
    });

    test("CONTACT_015 - Verify contact creation failure with invalid data", {
        tag: ["@CONTACT_015", "@contact", "@function"],
    }, async ({ conf }) => {
        const firstName = conf.data.first_name;
        const invalidEmail = conf.data.email;

        await test.step("Open contact creation modal", async () => {
            await contactPage.clickCreatePage();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Fill form with invalid email data", async () => {
            await contactPage.contactLoc.creating.firstName.fill(firstName);
            await contactPage.contactLoc.creating.email.fill(invalidEmail);
            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
            await expect(contactPage.contactLoc.creating.email).toHaveValue(invalidEmail);
        });

        await test.step("Verify creation fails with invalid email error", async () => {
            await contactPage.contactLoc.creating.createBtn.click();
            await expect(contactPage.contactLoc.creating.messageCraeteInvalidEmail).toBeVisible();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
        });
    });

    test("CONTACT_016 - Verify contact creation failure with existing contact", {
        tag: ["@CONTACT_016", "@contact", "@function"],
    }, async ({ conf }) => {
        const firstName = conf.data.first_name;
        const existingEmail = conf.data.email;

        await test.step("Open contact creation modal", async () => {
            await contactPage.clickCreatePage();
            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
        });

        await test.step("Fill form with existing contact email", async () => {
            await contactPage.contactLoc.creating.firstName.fill(firstName);
            await contactPage.contactLoc.creating.email.fill(existingEmail);

            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
            await expect(contactPage.contactLoc.creating.email).toHaveValue(existingEmail);
        });

        await test.step("Verify creation fails with duplicate email error", async () => {
            await contactPage.contactLoc.creating.createBtn.click();

            await expect(contactPage.dashboardLoc.modal.headerModal("New Contact")).toBeVisible();
            await expect(contactPage.contactLoc.creating.blockMsgDuplicateEmail).toBeVisible();
            await expect(contactPage.contactLoc.textMsgDuplicateEmail).toContainText(existingEmail);
            await expect(contactPage.contactLoc.creating.firstName).toHaveValue(firstName);
        });
    });

    test("CONTACT_018 - Verify successfully contact information update", {
        tag: ["@CONTACT_018", "@contact", "@function"],
    }, async ({ conf, updateContactPage }) => {
        await test.step("Verify close update modal without change data", async () => {
            await updateContactPage.contactLoc.updating.btnCloseModalUpdate.click();
            await expect(updateContactPage.contactLoc.modalForm).not.toBeVisible();

            // Reopen update modal
            await updateContactPage.dashboardLoc.buttonUpdate.click();
            await expect(updateContactPage.contactLoc.modalForm).toBeVisible();
        })

        await test.step("Fill contact update form with new data", async () => {
            await updateContactPage.contactLoc.updating.inputPhoneNumber.fill(conf.data.phone_number);
            await updateContactPage.contactLoc.updating.inputTag.type(conf.data.tag, { delay: 100 });
            await updateContactPage.waitForSecond(1); // wait for dropdown to appear
            await updateContactPage.contactLoc.optionSelectTag(conf.data.tag).click();
            await updateContactPage.contactLoc.updating.inputAddress.fill(conf.data.address);
            await updateContactPage.contactLoc.updating.inputCity.fill(conf.data.city);
        });

        await test.step("Verify close modal with data changed", async () => {
            await updateContactPage.dashboardLoc.modal.headerModal("Contact Detail").click();
            await updateContactPage.waitForSecond(1); // wait for possible changes to register
            await updateContactPage.contactLoc.updating.btnCloseModalUpdate.click();
            await expect(updateContactPage.dashboardLoc.buttonByText("Back").last()).toBeVisible();
            await updateContactPage.dashboardLoc.buttonByText("Back").last().click();
        });

        await test.step("Save changes and verify successful update", async () => {
            await updateContactPage.dashboardLoc.modal.headerModal("Contact Detail").click();
            await updateContactPage.dashboardLoc.buttonUpdateInForm.click({ force: true });
            await expect(updateContactPage.contactLoc.updating.msgUpdateSuccess).toBeVisible();
            await expect(updateContactPage.contactLoc.modalForm).not.toBeVisible();
            await expect(updateContactPage.contactLoc.updating.phoneDetail).toContainText(
                conf.data.phone_number.replace(/(\(\d{3}\)\s*\d{3})-(\d{4})/, "$1 - $2")
            );
            await updateContactPage.waitForSecond(1);
            const tags = await updateContactPage.contactLoc.updating.tagHadCreateDetail.allTextContents();
            expect(tags).toContain(`#${conf.data.tag}`);

            await updateContactPage.dashboardLoc.buttonUpdate.click();
            await expect(updateContactPage.contactLoc.updating.inputAddress).toHaveValue(conf.expect.address);
            await expect(updateContactPage.contactLoc.updating.inputCity).toHaveValue(conf.expect.city);
        });
    });

    test("CONTACT_019 - Verify contact update failure with invalid data", {
        tag: ["@CONTACT_019", "@contact", "@function"],
    }, async ({ conf, updateContactPage }) => {
        await test.step("Fill form with invalid email", async () => {
            await updateContactPage.contactLoc.updating.inputEmail.fill(conf.data.email_invalid);
            await expect(updateContactPage.contactLoc.updating.inputEmail).toHaveValue(conf.data.email_invalid);
        });

        await test.step("Verify update fails with invalid email error", async () => {
            await updateContactPage.dashboardLoc.buttonUpdateInForm.click();

            await expect(updateContactPage.contactLoc.updating.msgErrorInvalidEmail).toBeVisible();
            await expect(updateContactPage.contactLoc.modalForm).toBeVisible();
        });
    });

    test("CONTACT_020 - Verify contact update failure with existing email", {
        tag: ["@CONTACT_020", "@contact", "@function"],
    }, async ({ conf, updateContactPage }) => {
        await test.step("Fill form with existing contact email", async () => {
            await updateContactPage.contactLoc.updating.inputEmail.fill(conf.data.exist_email);
            await expect(updateContactPage.contactLoc.updating.inputEmail).toHaveValue(conf.data.exist_email);
        });

        await test.step("Verify update fails with duplicate email error", async () => {
            await updateContactPage.dashboardLoc.buttonUpdateInForm.click();

            await expect(updateContactPage.contactLoc.modalForm).toBeVisible();
            await expect(updateContactPage.contactLoc.textMsgDuplicateEmail).toBeVisible();
        });
    });

    test("CONTACT_021 - Verify contact update validation for character limits", {
        tag: ["@CONTACT_021", "@contact", "@validate"]
    }, async ({ conf, updateContactPage }) => {
        await test.step("Fill form with data exceeding character limits", async () => {
            await updateContactPage.contactLoc.updating.inputFname.fill(conf.data.first_name_long);
            await updateContactPage.contactLoc.updating.inputLname.fill(conf.data.last_name_long);
            await updateContactPage.contactLoc.updating.inputNote.fill(conf.data.note_long);
            await updateContactPage.contactLoc.updating.inputTag.fill(conf.data.tag_long);
            await updateContactPage.contactLoc.updating.dropdownAddTag(conf.data.tag_long).click();

            await expect(updateContactPage.contactLoc.updating.inputFname).toHaveValue(conf.data.first_name_long);
            await expect(updateContactPage.contactLoc.updating.inputLname).toHaveValue(conf.data.last_name_long);
            await expect(updateContactPage.contactLoc.updating.inputNote).toHaveValue(conf.data.note_long);
            await expect(updateContactPage.contactLoc.updating.tagHadCreateUpdate(conf.data.tag_long)).toBeVisible();
        });

        await test.step("Verify update fails with character limit validation errors", async () => {
            await updateContactPage.dashboardLoc.buttonUpdateInForm.click();

            await expect(updateContactPage.contactLoc.modalForm).toBeVisible();
            await expect(updateContactPage.contactLoc.msgErrorTooLongInput("first name")).toBeVisible();
            await expect(updateContactPage.contactLoc.msgErrorTooLongInput("last name")).toBeVisible();
            await expect(updateContactPage.contactLoc.msgErrorTooLongInput("tags")).toBeVisible();
            await expect(updateContactPage.contactLoc.msgErrorTooLongInput("note")).toBeVisible();
        });
    });

    test("CONTACT_023 - Verify contact business field clear and update functionality", {
        tag: ["@CONTACT_023", "@contact", "@function"]
    }, async ({ conf }) => {
        const contactName = conf.data.contact;
        const businessName = conf.data.business_name;

        await test.step("Verify contact has business information", async () => {
            await contactPage.getDetailCase(contactName);
            await contactPage.dashboardLoc.buttonUpdate.click();
            await expect(contactPage.contactLoc.modalForm.first()).toBeVisible();
            await expect(contactPage.contactLoc.updating.inputByName("business_provider_id")).toHaveValue(businessName);
        });

        await test.step("Clear business field and save changes", async () => {
            await contactPage.contactLoc.updating.inputByName("business_provider_id").clear();
            await expect(contactPage.contactLoc.updating.inputByName("business_provider_id")).not.toHaveValue(businessName);
            await contactPage.dashboardLoc.buttonUpdateInForm.click();
        });

        await test.step("Verify business field is cleared and restore business information", async () => {
            await contactPage.dashboardLoc.buttonUpdate.click();
            await contactPage.waitForSecond(1.5); // wait for loading form
            await expect(contactPage.contactLoc.updating.inputByName("business_provider_id")).toHaveValue("");

            await contactPage.contactLoc.updating.inputByName("business_provider_id").fill(businessName);
            await expect(contactPage.contactLoc.updating.optionBusiness(businessName)).toBeVisible();
            await contactPage.contactLoc.updating.optionBusiness(businessName).click();
            await expect(contactPage.contactLoc.updating.inputByName("business_provider_id")).toHaveValue(businessName);
            await contactPage.dashboardLoc.buttonUpdateInForm.click();
        });
    });

    test("CONTACT_027 - Verify crud Contact Group", {
        tag: ["@CONTACT_027", "@contact", "@function"]
    }, async ({ conf }) => {
        await test.step("Verify contact group had been delete", async () => {
            await contactPage.dashboardLoc.buttonByText("Contact Group").click();
            await contactPage.dashboardLoc.common.spanText("Contact Groups").waitFor({ state: 'visible' });
            await contactPage.search("Test Tag");
            await contactPage.waitForSecond(3)
            const dataTestTag = (await contactPage.dashboardLoc.table.itemInRow("Test Tag").all()).length;
            if (dataTestTag > 0) {
                await contactPage.contactLoc.contactGroup.btnDeleteContactGroup.first().click();
                await contactPage.dashboardLoc.common.popUpConfirm.click();
                await contactPage.dashboardLoc.btnClosePopupNotification.click();
            }
        })

        await test.step("Verify create new contact group", async () => {
            await contactPage.createContactGroupComplete(conf.data.input_create);
            await contactPage.verifyContactGroupInNewTab(
                conf.data.input_create[2].value,
                conf.data.input_create[0].value
            );
        });

        await test.step("Verify update contact group", async () => {
            await contactPage.updateContactGroupComplete(conf.data.input_create);
            await contactPage.verifyContactGroupInNewTab(
                conf.data.input_create[2].value,
                conf.data.input_create[0].value_update
            );
        });

        await test.step("Verify delete contact group", async () => {
            await contactPage.contactLoc.contactGroup.btnDeleteContactGroup.first().click();
            await contactPage.dashboardLoc.common.popUpConfirm.click();
            await contactPage.search(conf.data.input_create[0].value_update);
            await contactPage.verifyContactGroupInNewTab(conf.data.input_create[2].value, null);
        });
    });

    test("CONTACT_028 - Verify when cancel update tag", {
        tag: ["@CONTACT_028", "@contact", "@function"]
    }, async ({ conf }) => {
        await test.step("Verify cancel update tag without change data", async () => {
            await contactPage.dashboardLoc.buttonByText("Contact Group").click();
            await contactPage.dashboardLoc.common.spanText("Contact Groups").waitFor({ state: 'visible' });
            await contactPage.search("Test Close Modal");
            await contactPage.contactLoc.contactGroup.btnEditContactGroup.first().click();
            await expect(contactPage.dashboardLoc.modal.headerModal("Edit Contact Group")).toBeVisible();

            await contactPage.contactLoc.updating.btnCloseModalUpdateContactGroup.click();
            await expect(contactPage.dashboardLoc.modal.headerModal("Edit Contact Group")).not.toBeVisible();
        });

        await test.step("Verify reopen and close modal with change data", async () => {
            // Reopen edit modal
            await contactPage.contactLoc.contactGroup.btnEditContactGroup.first().click();
            await expect(contactPage.dashboardLoc.modal.headerModal("Edit Contact Group")).toBeVisible();

            // Fill data
            await contactPage.dashboardLoc.modal.inputByID("input_note").fill("123");
            await contactPage.contactLoc.updating.btnCloseModalUpdateContactGroup.click();
            await expect(contactPage.dashboardLoc.buttonByText("Back").last()).toBeVisible();
            await contactPage.dashboardLoc.buttonByText("Back").last().click();
        });
    });

    test("CONTACT_030 - Verify bulk edit function to change active/reference", {
        tag: ['@CONTACT_030', '@contact', '@function']
    }, async ({ conf, apiHelper }) => {
        let contactID1: string;
        let contactID2: string;
        const firstName1 = `${randomText(5)}${randomString(5)}`;
        const firstName2 = `${randomText(5)}${randomString(5)}`;
        const lastName = `${randomText(5)}${randomString(8)}`;
        const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
        const fullName1 = `${capitalize(firstName1)} ${capitalize(lastName)}`;
        const fullName2 = `${capitalize(firstName2)} ${capitalize(lastName)}`;

        await test.step("Precondition: Create 2 new contacts", async () => {
            const createContactResponse1 = await apiHelper.createContact({
                first_name: firstName1,
                last_name: lastName
            });
            contactID1 = createContactResponse1.contact_id;

            const createContactResponse2 = await apiHelper.createContact({
                first_name: firstName2,
                last_name: lastName
            });
            contactID2 = createContactResponse2.contact_id;
        });

        await test.step("Verify change 2 contacts to reference", async () => {
            // Search 2 contacts
            await contactPage.reload();
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);
            await contactPage.waitAllRequestCompeleted();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).toBeVisible();

            // Click add to bulk edit
            await contactPage.dashboardLoc.buttonByText("Bulk Edit").click();
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 2 contacts from Page 1")).toBeVisible();

            // Click checkbox select all
            await contactPage.waitForSecond(2);
            await contactPage.dashboardLoc.bulkEdit.checkBoxCheckAll.click();
            await expect(contactPage.dashboardLoc.common.spanTextContainsAll("You have selected 2 contacts")).toBeVisible();

            //Verify UI in step 2
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await expect(contactPage.page.locator('#root')).toMatchAriaSnapshot(`
              - text: "2 of 4 steps Step 1: Choose Contacts Step 2: Apply Bulk Action Step 3: Action Detail Step 4: Confirmation"
              - paragraph:
                - text: "Step 2: Apply Bulk Action"
                - img
              - paragraph: Choose the action you want to apply to the selected contacts.
              - radio "Change Role"
              - text: Change Role Select a role to change to.
              - radio "Change Job Title"
              - text: Change Job Title Select a title to change to.
              - radio "Assign Contact Group"
              - text: Assign Contact Group Add to existing, Replace all, or Remove existing group.
              - radio "Modify Tag"
              - text: Modify Tag Add to existing, Replace all, or Remove existing tag.
              - radio "Read/Unread"
              - text: Read/Unread Mark as Read or Unread.
              - radio "Active/Reference"
              - text: Active/Reference Move to the Active workspace for high visibility or the Reference section for low visibility.
              - button "Back"
              - button "Next" [disabled]
              `);

            // Verify choose Active/Reference action
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Active/Reference").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();

            // Verify choose Reference in step 3
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Reference").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.buttonByText("Confirmation").click();
        });

        await test.step("Verify contacts after bulk edit", async () => {
            await contactPage.open();
            // Verify search in tab Active
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);
            await contactPage.waitAllRequestCompeleted();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).not.toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).not.toBeVisible();

            // Verify search in tab Reference
            await contactPage.dashboardLoc.table.tabInTable("Reference").click();
            await contactPage.search(lastName);
            await contactPage.waitAllRequestCompeleted();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).toBeVisible();
        });

        await test.step("Verify change 2 contacts to active", async () => {
            // Click add to bulk edit
            await contactPage.dashboardLoc.buttonByText("Bulk Edit").click();
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 2 contacts from Page 1")).toBeVisible();

            // Click checkbox select all
            await contactPage.waitForSecond(2);
            await contactPage.dashboardLoc.bulkEdit.checkBoxCheckAll.click();
            await expect(contactPage.dashboardLoc.common.spanTextContainsAll("You have selected 2 contacts")).toBeVisible();

            // Verify choose Active/Reference action
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Active/Reference").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();

            // Verify choose Reference in step 3
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Active").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.buttonByText("Confirmation").click();
        });

        await test.step("Verify contacts after bulk edit", async () => {
            await contactPage.open();
            // Verify search in tab Active
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);
            await contactPage.waitAllRequestCompeleted();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).toBeVisible();

            // Verify search in tab Reference
            await contactPage.dashboardLoc.table.tabInTable("Reference").click();
            await contactPage.search(lastName);
            await contactPage.waitAllRequestCompeleted();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).not.toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).not.toBeVisible();
        });

        await test.step("Teardown - Archive contacts", async () => {
            await apiHelper.archiveContact(contactID1);
            await apiHelper.archiveContact(contactID2);
        });
    });

    test("CONTACT_031 - Verify bulk edit function to change read/unread", {
        tag: ['@CONTACT_031', '@contact', '@function']
    }, async ({ conf, apiHelper }) => {
        let contactID1: string;
        let contactID2: string;
        const firstName1 = `${randomText(5)}${randomString(5)}`;
        const firstName2 = `${randomText(5)}${randomString(5)}`;
        const lastName = `${randomText(5)}${randomString(8)}`;
        const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
        const fullName1 = `${capitalize(firstName1)} ${capitalize(lastName)}`;
        const fullName2 = `${capitalize(firstName2)} ${capitalize(lastName)}`;

        await test.step("Precondition: Create 2 new contacts", async () => {
            const createContactResponse1 = await apiHelper.createContact({
                first_name: firstName1,
                last_name: lastName,
                address_1: "123 Main St"
            });
            contactID1 = createContactResponse1.contact_id;

            const createContactResponse2 = await apiHelper.createContact({
                first_name: firstName2,
                last_name: lastName,
                address_1: "123 Main St"
            });
            contactID2 = createContactResponse2.contact_id;
        });

        await test.step("Verify change 2 contacts to read", async () => {
            // Search 2 contacts
            await contactPage.reload();
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);

            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).toBeVisible();
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 1 to 2 of 2 entries")).toBeVisible();

            await contactPage.resetToDefaultColumn(contactPage.contactProps.customizedColumns, 1);
            await verifyScreenshot('contacts-unread.png', contactPage.dashboardLoc.table.container, [
                contactPage.dashboardLoc.table.itemInRow(fullName1),
                contactPage.dashboardLoc.table.itemInRow(fullName2)
            ], 0.01);

            // Click add to bulk edit
            await contactPage.dashboardLoc.buttonByText("Bulk Edit").click();
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 2 contacts from Page 1")).toBeVisible();

            // Click checkbox select all
            await contactPage.waitForSecond(2);
            await contactPage.dashboardLoc.bulkEdit.checkBoxCheckAll.click();
            await expect(contactPage.dashboardLoc.common.spanTextContainsAll("You have selected 2 contacts")).toBeVisible();

            await contactPage.dashboardLoc.buttonByText("Next").click();

            // Verify choose Read/Unread action
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Read/Unread").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();

            // Verify choose Read in step 3
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Read").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.buttonByText("Confirmation").click();
        });

        await test.step("Verify contacts after bulk edit", async () => {
            await contactPage.open();
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 1 to 2 of 2 entries")).toBeVisible();
            await contactPage.resetToDefaultColumn(contactPage.contactProps.customizedColumns, 1);

            await verifyScreenshot('contacts-read.png', contactPage.dashboardLoc.table.container, [
                contactPage.dashboardLoc.table.itemInRow(fullName1),
                contactPage.dashboardLoc.table.itemInRow(fullName2)
            ], 0.01);
        });

        await test.step("Verify change 2 contacts to unread", async () => {
            // Click add to bulk edit
            await contactPage.dashboardLoc.buttonByText("Bulk Edit").click();
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 2 contacts from Page 1")).toBeVisible();

            // Click checkbox select all
            await contactPage.waitForSecond(2);
            await contactPage.dashboardLoc.bulkEdit.checkBoxCheckAll.click();
            await expect(contactPage.dashboardLoc.common.spanTextContainsAll("You have selected 2 contacts")).toBeVisible();

            // Verify choose Read/Unread action
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Read/Unread").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();

            // Verify choose Read in step 3
            await contactPage.dashboardLoc.bulkEdit.inputBulkEditAction("Unread").check();
            await expect(contactPage.dashboardLoc.buttonByText("Next")).toBeEnabled();
            await contactPage.dashboardLoc.buttonByText("Next").click();
            await contactPage.dashboardLoc.buttonByText("Confirmation").click();
        });

        await test.step("Verify contacts after bulk edit", async () => {
            await contactPage.open();
            // Verify search in tab Active
            await contactPage.dashboardLoc.table.tabInTable("Active").click();
            await contactPage.search(lastName);
            await expect(contactPage.dashboardLoc.common.pTextContainsAll("Showing 1 to 2 of 2 entries")).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName1)).toBeVisible();
            await expect(contactPage.dashboardLoc.table.itemInRow(fullName2)).toBeVisible();
            
            await contactPage.resetToDefaultColumn(contactPage.contactProps.customizedColumns, 1);
            await verifyScreenshot('contacts-unread.png', contactPage.dashboardLoc.table.container, [
                contactPage.dashboardLoc.table.itemInRow(fullName1),
                contactPage.dashboardLoc.table.itemInRow(fullName2)
            ]);
        });

        await test.step("Teardown - Archive contacts", async () => {
            await apiHelper.archiveContact(contactID1);
            await apiHelper.archiveContact(contactID2);
        });
    });
});