import { test, expect } from '../../fixtures/index';
import { RequestPage } from '../../pom/request/request.page';
import { LoginPage } from '../../pom/login.page';
import path from 'path';
import { takeScreenshot, verifyScreenshot } from '../../utils/screenshot';
import { SharedRequestPage } from '../../pom/share-request.page';
import { getTodayInTimeZone } from '../../pom/utils/utlisFunc';
import { extractNumber, getRandomNumberInRange, randomString } from '../../utils/array';
import { Mail } from '../../pom/utils/mail.page';
import { CasePage } from '../../pom/case/case.page';
import { authenticator } from 'otplib'
import fs from 'fs';

test.describe('Feature case for request-listing', () => {
    let loginPage: LoginPage;
    let requestPage: RequestPage;
    let msgOffNoti: string = "";
    let msgOnNoti: string = "";
    let listMailCheck: string[] = [];
    test.beforeEach(async ({ page, conf }) => {
        loginPage = new LoginPage(page);
        requestPage = new RequestPage(page);
        requestPage.loadBusinessNames(conf.data.business_singular, conf.data.business_plural);

        await loginPage.open();
        await loginPage.login(conf.data.username, conf.data.password);
        await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
        await requestPage.open();
    });

    test('REQ_005 - Verify feature sort', {
        tag: ['@REQ_005', '@request', '@feature']
    }, async () => {
        const displayNames = ['Request #', 'Client Name', 'Creator', 'Directed To'];
        const sortedFieldName = ['id', 'customer_name', 'from_contact_name', 'to_contact_name']
        const propertyNames = ['id', 'customer_name', 'from_business', 'to_business'];
        const directions = ['asc', 'asc', 'asc', 'asc'];
        for (let i = 0; i < displayNames.length; i++) {
            await expect(requestPage.dashboardLoc.table.headingColumn(displayNames[i])).toBeVisible();
            await requestPage.dashboardLoc.table.headingColumn(displayNames[i]).click();
            await expect(requestPage.page).toHaveURL(
                new RegExp(`.*sort=${sortedFieldName[i]}&direction=${directions[i]}`)
            );

            let apiDataUrl = `api/v1/requests?return_type=json&is_archived=false&sort=${sortedFieldName[i]}&direction=${directions[i]}`;
            const data = await requestPage.getDataInTable(displayNames[i], propertyNames[i], apiDataUrl);
            console.log(`Sort by: ${displayNames[i]}, direction: ${directions[i]}, property: ${propertyNames[i]}`)
            expect(data.dataApi).toEqual(data.dataUI);
        }
    });

    test('REQ_006 - Verify feature filter', {
        tag: ['@REQ_006', '@request', '@feature']
    }, async ({ conf }) => {
        const filterFields = requestPage.requestProps.filterProperties;
        for (let i = 0; i < filterFields.length; i++) {
            // clear filter
            await requestPage.open();
            await requestPage.waitForSecond(3);

            // prepare locator
            let fieldLocator;
            switch (filterFields[i].type) {
                case 'input':
                    fieldLocator = requestPage.dashboardLoc.search.filter.popup.inputField(filterFields[i].name);
                    break;
                default:
                    throw new Error(`Unsupported filter type: ${filterFields[i].type}`);
            }

            // Fill invalid value
            await requestPage.dashboardLoc.search.filter.btn.click();
            await expect(requestPage.dashboardLoc.search.filter.popup.container).toBeVisible();
            await fieldLocator.fill(conf.data.filter_data[filterFields[i].name].invalid_data);
            await requestPage.dashboardLoc.search.filter.popup.btnApply.click();
            await expect(requestPage.dashboardLoc.table.noResult).toBeVisible();

            // Fill valid value
            await requestPage.dashboardLoc.search.filter.btn.click();
            await expect(requestPage.dashboardLoc.search.filter.popup.container).toBeVisible();
            await fieldLocator.fill(conf.data.filter_data[filterFields[i].name].valid_data);
            await requestPage.dashboardLoc.search.filter.popup.btnApply.click();
            await expect(requestPage.dashboardLoc.table.noResult).not.toBeVisible();
        }
    });

    test('REQ_007 - Verify feature Pin', {
        tag: ['@REQ_007', '@request', '@feature']
    }, async ({ conf }) => {
        await test.step('Search and verify icon Pin visible', async () => {
            //Search
            await requestPage.requestLoc.inputSearch.fill(conf.data.case_number);
            await expect(requestPage.requestLoc.tableHeadingColumn('Pin')).toBeVisible();

            //verify icon Pin visible
            await expect(requestPage.requestLoc.pinIcon(conf.data.case_number)).toBeVisible()
        });
        await test.step('Verify Pin and unpin feature', async () => {
            //Click Pin icon and verify
            await requestPage.requestLoc.pinIcon(conf.data.case_number).click();
            await expect(requestPage.requestLoc.pinnedIcon(conf.data.case_number)).toBeVisible();
            await expect(requestPage.requestLoc.firstCaseNumber(conf.data.case_number)).toBeVisible();

            // Click unpin
            await requestPage.requestLoc.pinnedIcon(conf.data.case_number).click()
            await expect(requestPage.requestLoc.pinIcon(conf.data.case_number)).toBeVisible();

        });
    });

    test('REQ_008 - Verify feature customized columns', {
        tag: ['@REQ_008', '@request', '@ui']
    }, async () => {
        const customThreeDotLocator = requestPage.genLoc("//div[contains(@class, 'card-header')]//span[contains(@class, 'cursor-pointer')]").nth(0);
        // Verify default columns displayed
        await test.step("Verify default columns displayed", async () => {
            const customizedColumns = requestPage.requestProps.customizedColumns;
            for (let i = 0; i < customizedColumns.length; i++) {
                if (customizedColumns[i].default) {
                    await expect(requestPage.dashboardLoc.listing.heading.headingColumn(customizedColumns[i].tableDisplayName)).toBeVisible();
                }
            }
        });

        // Verify customized column show disable items and active items
        await test.step("Verify customized columns popup state", async () => {
            await requestPage.openThreedotMenu(requestPage.requestProps.threeDotDropdownMenus.customizedColumn, customThreeDotLocator);

            // Verify enabled column and disabled column
            const customizedColumns = requestPage.requestProps.customizedColumns;
            for (let i = 0; i < customizedColumns.length; i++) {
                if (customizedColumns[i].default) {
                    await expect(requestPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(customizedColumns[i].name)).toBeDisabled();
                } else {
                    await expect(requestPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(customizedColumns[i].name)).toBeEnabled();
                }
            }
        });

        // Pre-condition: disable all enabled column
        await test.step("Pre-condition: disable all enabled column", async () => {
            const customizedColumns = requestPage.requestProps.customizedColumns;
            for (let i = 0; i < customizedColumns.length; i++) {
                if (!customizedColumns[i].default) {
                    await requestPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(customizedColumns[i].name).setChecked(false);
                }
            }
        });

        // Check each columns and verify it shown
        await test.step("Check each columns and verify it shown", async () => {
            await requestPage.open();
            const customizedColumns = requestPage.requestProps.customizedColumns.filter(column => !column.default);
            for (let i = 0; i < customizedColumns.length; i++) {
                await requestPage.openThreedotMenu(requestPage.requestProps.threeDotDropdownMenus.customizedColumn, customThreeDotLocator);
                await requestPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(customizedColumns[i].name).setChecked(true);
                await requestPage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
                await expect(requestPage.dashboardLoc.listing.heading.headingColumn(customizedColumns[i].tableDisplayName)).toBeVisible();
            }
        });

        // Uncheck each columns and verify it hidden
        await test.step("Uncheck each columns and verify it hidden", async () => {
            await requestPage.open();
            const customizedColumns = requestPage.requestProps.customizedColumns.filter(column => !column.default);
            for (let i = 0; i < customizedColumns.length; i++) {
                await requestPage.openThreedotMenu(requestPage.requestProps.threeDotDropdownMenus.customizedColumn, customThreeDotLocator);
                await requestPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(customizedColumns[i].name).setChecked(false);
                await requestPage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
                await expect(requestPage.dashboardLoc.listing.heading.headingColumn(customizedColumns[i].tableDisplayName)).not.toBeVisible();
            }
        });
    });

    test("REQ_009 - Verify when user fill text in Repond message in detail request", {
        tag: ['@REQ_009', '@request', '@function', '@screenshot']
    }, async ({ conf }) => {
        test.slow();
        const textEditorBody = requestPage.requestLoc.textEditorCreateCaseArea;
        await test.step("Search exist case and detail case appeared, modal appeared", async () => {
            await requestPage.requestLoc.inputSearch.fill(conf.data.case_exist);
            await expect(requestPage.requestLoc.caseAlreadyExist(conf.data.case_exist)).toBeVisible();

            //Verify detail case appeared
            await requestPage.requestLoc.caseAlreadyExist(conf.data.case_exist).click();
            await requestPage.waitForSecond(1);
            await expect(requestPage.requestLoc.caseIDDetail).toContainText(conf.data.case_exist);

            //Verify modal appeared
            await requestPage.requestLoc.buttonRepond.click();
            await requestPage.waitForSecond(1);
            await expect(textEditorBody).toBeVisible();
        })

        await test.step("Verify when typing first message in editor text", async () => {
            await textEditorBody.type(conf.data.first_message, { delay: 20 });
            await expect(textEditorBody).toHaveText(conf.data.first_message, { timeout: 3000 });
        })

        await test.step("Verify when typing second message italic in editor text", async () => {
            await textEditorBody.press('Enter');
            await requestPage.requestLoc.btnItalicEditorCreate.click();
            await textEditorBody.type(conf.data.second_message, { delay: 20 });
            await requestPage.requestLoc.btnItalicEditorCreate.click();

            await expect(textEditorBody).toContainText(conf.data.second_message);
            await expect(textEditorBody.locator("//p[2]/em")).toHaveText(conf.data.second_message);
        })

        await test.step("Verify when typing third message bold in editor text", async () => {
            await textEditorBody.press('Enter');
            await requestPage.requestLoc.btnBoldEditorCreate.click();
            await textEditorBody.type(conf.data.third_message, { delay: 20 });
            await requestPage.requestLoc.btnBoldEditorCreate.click();

            await expect(textEditorBody).toContainText(conf.data.third_message);
            await expect(textEditorBody.locator("//p[3]/strong")).toHaveText(conf.data.third_message);
        })

        await test.step("Verify when typing list type number in editor text", async () => {
            await textEditorBody.press('Enter');
            await requestPage.requestLoc.btnListNumberTypeCreate.click();
            await requestPage.rendListTextEditor(conf.data.child_message);

            await expect(textEditorBody.locator("ol li")).toHaveCount(3);
            for (let i = 1; i <= 3; i++) {
                await expect(textEditorBody.locator(`ol li:nth-child(${i})`)).toHaveText(conf.data.child_message);
            }
        })

        await test.step("Verify when typing list type dot in editor text", async () => {
            await requestPage.requestLoc.btnListDotTypeCreate.click();
            await requestPage.rendListTextEditor(conf.data.child_message);

            await expect(textEditorBody.locator("ul li")).toHaveCount(3);
            for (let i = 1; i <= 3; i++) {
                await expect(textEditorBody.locator(`ul li:nth-child(${i})`)).toHaveText(conf.data.child_message);
            }
        })

        await test.step("Verify when click submit respond", async () => {
            await requestPage.requestLoc.detail.btnSubmitMessage.click();

            await expect(requestPage.requestLoc.messageRepondSucces).toBeVisible({ timeout: 20_000 });
            await expect(textEditorBody).not.toBeVisible();
            await requestPage.waitForSecond(5);
            await expect(requestPage.requestLoc.headerModalNewPost).toBeVisible();

            await requestPage.requestLoc.buttonLeaveIt.click();
        })

        await test.step("Verify the similarities between Text in Editor and Posted", async () => {
            await requestPage.requestLoc.thumbImagePosted.first().click();
            await requestPage.waitForSecond(5)
            await verifyScreenshot("post-details-snapshot.png", requestPage.requestLoc.detailPostedAttachment, [], 0.02)
        })
    })

    test("REQ_010 - Verify when user fill Text Editor in Create new request", {
        tag: ['@REQ_010', '@request', '@function' , '@screenshot']
    }, async ({ conf }) => {

        await test.step("Verify site create new request appear", async () => {
            await requestPage.gotoCreateRequest("step");
            await expect(requestPage.dashboardLoc.buttonByText("Switch to Fast Submission")).toBeVisible();
        })

        await test.step("Verify when choose option in step action, patient, business", async () => {
            //Choose action type
            await expect(requestPage.requestLoc.actionLetterOfProtection).toBeVisible();
            await requestPage.waitForSecond(1);
            await requestPage.requestLoc.actionLetterOfProtection.click({ force: true });
            await requestPage.requestLoc.btnNextStep.click();

            //Choose patient
            await expect(requestPage.requestLoc.listPatientSuggested).toBeVisible();
            await requestPage.requestLoc.listPatientSuggested.click();
            await requestPage.requestLoc.btnNextStep.click();

            //Choose business
            await expect(requestPage.requestLoc.listBusinessSuggested).toBeVisible();
            await requestPage.requestLoc.listBusinessSuggested.click();
            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.textEditorCreateCaseArea).toBeVisible()
        })

        const textEditor = requestPage.requestLoc.textEditorCreateCaseArea;

        await test.step("Verify when typing first message in editor text", async () => {
            //Clear text
            await textEditor.evaluate((el) => (el.innerHTML = ''));

            await textEditor.type(conf.data.first_message, { delay: 20 });
            await expect(textEditor).toHaveText(conf.data.first_message);
        })

        await test.step("Verify when typing second message italic in editor text", async () => {
            await textEditor.press('Enter');
            await requestPage.requestLoc.btnItalicEditorCreate.click();
            await textEditor.type(conf.data.second_message, { delay: 20 });
            await requestPage.requestLoc.btnItalicEditorCreate.click();

            await expect(textEditor).toContainText(conf.data.second_message);
            await expect(textEditor.locator("//p[2]/em")).toHaveText(conf.data.second_message);
        })

        await test.step("Verify when typing third message bold in editor text", async () => {
            await textEditor.press('Enter');
            await requestPage.requestLoc.btnBoldEditorCreate.click();
            await textEditor.type(conf.data.third_message, { delay: 20 });
            await requestPage.requestLoc.btnBoldEditorCreate.click();

            await expect(textEditor).toContainText(conf.data.third_message);
            await expect(textEditor.locator("//p[3]/strong")).toHaveText(conf.data.third_message);
        })

        await test.step("Verify when typing list type number in editor text", async () => {
            await textEditor.press('Enter');
            await requestPage.requestLoc.btnListNumberTypeCreate.click();
            await requestPage.rendListTextEditor(conf.data.child_message);

            await expect(textEditor.locator("ol li")).toHaveCount(3);
            for (let i = 1; i <= 3; i++) {
                await expect(textEditor.locator(`ol li:nth-child(${i})`)).toHaveText(conf.data.child_message);
            }
        })

        await test.step("Verify when typing list type dot in editor text", async () => {
            await requestPage.requestLoc.btnListDotTypeCreate.click();
            await requestPage.rendListTextEditor(conf.data.child_message);

            await expect(textEditor.locator("ul li")).toHaveCount(3);
            for (let i = 1; i <= 3; i++) {
                await expect(textEditor.locator(`ul li:nth-child(${i})`)).toHaveText(conf.data.child_message);
            }
        })

        await test.step("Verify when submit create request", async () => {
            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.btnCreateOnly).toBeVisible();
            await requestPage.requestLoc.btnCreateOnly.click({ force: true });
            await requestPage.waitForSecond(3);

            await expect(requestPage.requestLoc.thumbImagePosted.first()).toBeVisible({ timeout: 25_000 });
        })

        await test.step("Verify the similarities between Text in Editor and Posted", async () => {
            await requestPage.requestLoc.thumbImagePosted.first().click();
            await requestPage.waitForSecond(5);
            await verifyScreenshot("post-details-create-snapshot.png", requestPage.requestLoc.detailPostedAttachment, [], 0.02)
        })
    })

    test("REQ_013 - Verify when create with Step-by-Step", {
        tag: ['@REQ_013', '@request', '@function']
    }, async ({ conf }) => {
        test.setTimeout(170_000);
        let url: string = "";
        let uniqueBusiness: string = "";
        await test.step("Goto create new with Step-by-Step", async () => {
            await requestPage.gotoCreateRequest("step");
            await expect(requestPage.dashboardLoc.buttonByText("Switch to Fast Submission")).toBeVisible();
        })

        await test.step("Choose action type and verify next step", async () => {
            await requestPage.requestLoc.actionLetterOfProtection.click();
            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.create.headerInCreateStep("Patient")).toBeVisible();
        })

        await test.step("Choose client and verify next step", async () => {
            const dataOfOptions = await requestPage.fillDataCreateRequest("Type or select a name", "Name", conf.data.patient);
            expect(dataOfOptions.infoPatient).toContain(dataOfOptions.address);

            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.create.headerInCreateStep("Business")).toBeVisible();
        })

        await test.step("Choose business and verify next step", async () => {
            uniqueBusiness = conf.data.business + randomString(8);
            await requestPage.requestLoc.create.inputByPlaceholder("Type or select a business").first().type(uniqueBusiness, { delay: 100 });
            await expect(requestPage.requestLoc.create.btnAddNewOption(uniqueBusiness)).toBeVisible();
            await requestPage.requestLoc.create.btnAddNewOption(uniqueBusiness).click();

            await expect(requestPage.dashboardLoc.modal.headerModal("New Business")).toBeVisible();
            await expect(requestPage.dashboardLoc.modal.inputByID("autocomplete_name")).toHaveValue(uniqueBusiness);

            await requestPage.dashboardLoc.buttonByText("Create").nth(1).click();
            await expect(requestPage.dashboardLoc.msgCreateSuccess).toBeVisible();
            await expect(requestPage.dashboardLoc.modal.inputByID("autocomplete_business_provider_id")).toHaveValue(uniqueBusiness);
            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.create.headerInCreateStep("Message")).toBeVisible();
        })

        await test.step("Verify add message, share request", async () => {
            await requestPage.requestLoc.btnNextStep.click();
            await expect(requestPage.requestLoc.create.headerInCreateStep("Share")).toBeVisible();
            await requestPage.requestLoc.create.inputByPlaceholder("Type or select an email address").type(conf.data.user_recive, { delay: 100 });
            await expect(requestPage.requestLoc.create.inputByPlaceholder("Type or select an email address")).toHaveValue(conf.data.user_recive);
            await expect(requestPage.requestLoc.create.dropdownMemberShare(conf.data.user_recive)).toBeVisible();
            await requestPage.requestLoc.create.dropdownMemberShare(conf.data.user_recive).click({ force: true });

            await requestPage.requestLoc.create.headerInCreateStep("Share").click();
            await requestPage.requestLoc.create.btnCreateAndShare.click();
            await expect(requestPage.requestLoc.create.caseIDRequest).toBeVisible({ timeout: 35_000 });
            url = requestPage.page.url();
        });

        await test.step("Verify business had suggest in the firsts list", async () => {
            //Verify showing in case detail
            const casePage = new CasePage(requestPage.page);
            await casePage.open();
            await casePage.getDetailCase("495528");
            await casePage.dashboardLoc.listBusinesses.last().click();
            await expect(casePage.dashboardLoc.modal.headerModal("Business")).toBeVisible();
            const businessFirstRecommend = await casePage.caseLoc.detail.firstSuggestBusiness.innerText();
            expect(businessFirstRecommend).toBe(uniqueBusiness);

            // Verify showing when create request
            await requestPage.gotoCreateRequest("multi");
            await requestPage.requestLoc.create.itemStep(3).first().click();
            await expect(requestPage.requestLoc.detail.businessFirstRecommend).toHaveText(uniqueBusiness);
        })

        await test.step("Verify user had recive request", async () => {
            await requestPage.changeUser(conf.data.username_recive, conf.data.password_recive, requestPage.page);

            await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
            await requestPage.checkNotification("New Request", true);
            await expect(requestPage.requestLoc.create.caseIDRequest).toBeVisible();
            const urlRecive = requestPage.page.url();
            expect(urlRecive.replace('/shared', '')).toBe(url);
        })
    })

    test("REQ_014 - Verify when create with Fast Submission with multiple request", {
        tag: ['@REQ_014', '@request', '@function']
    }, async ({ conf }) => {
        await test.step("Goto create new with Fast Submission", async () => {
            await requestPage.gotoCreateRequest("multi");
            await expect(requestPage.dashboardLoc.buttonByText("Switch to Step-by-Step")).toBeVisible();
        })

        await test.step("Verify when click add more request", async () => {
            await requestPage.dashboardLoc.buttonByText("Add more").click();
            const listOfCreationRequests = (await requestPage.requestLoc.create.boxCreateMultiRequests.all()).length;
            expect(listOfCreationRequests).toBe(2);
        })

        await test.step("Fill data to request", async () => {
            //Choose Action type
            await requestPage.requestLoc.create.itemStep(1).first().click();
            await requestPage.requestLoc.actionLetterOfProtection.first().click();

            //Choose Client
            await requestPage.requestLoc.create.itemStep(2).first().click();
            const dataOfOptionsClient = await requestPage.fillDataCreateRequest("Type or select a name", "Name", conf.data.patient);
            expect(dataOfOptionsClient.infoPatient).toContain(dataOfOptionsClient.address);

            //Choose Business
            await requestPage.requestLoc.create.itemStep(3).first().click();
            const dataOfOptionsBusiness = await requestPage.fillDataCreateRequest("Type or select a business", "Business Name", conf.data.business);

            //Fix tạm thời sau cần chỉnh lại dynamic
            const address = "5718 Westheimer Rd., Ste 1000, Houston";
            expect(dataOfOptionsBusiness.infoPatient).toContain(address);

            //Fill email member to share
            await requestPage.requestLoc.create.itemStep(5).first().click();
            await requestPage.requestLoc.create.inputByPlaceholder("Type or select an email address").first().fill(conf.data.user_recive);
            await expect(requestPage.requestLoc.create.inputByPlaceholder("Type or select an email address").first()).toHaveValue(conf.data.user_recive);
            await requestPage.requestLoc.create.dropdownMemberShare(conf.data.user_recive).click();

            // Aplly for all requests
            const applyAllFields = ["patient", "action", "business", "message", "share"];
            await requestPage.dashboardLoc.common.spanText("New Request").click();
            for (let i = 0; i < applyAllFields.length; i++) {
                await requestPage.waitForSecond(1);
                await requestPage.requestLoc.create.inputCheckAll(applyAllFields[i]).click({ force: true });
            }
        })

        await test.step("Verify create multi request", async () => {
            await requestPage.dashboardLoc.buttonByText("Create").first().click();
            await expect(requestPage.requestLoc.create.viewRequest.first()).toBeVisible({ timeout: 35_000 });
            const requestsCreated = await requestPage.requestLoc.create.viewRequest.all();
            expect(requestsCreated.length).toBe(2);
            const listRequest: string[] = [];
            for (let i = 0; i < requestsCreated.length; i++) {
                listRequest.push(await requestsCreated[i].innerText());
            }
            listRequest.reverse();

            //Verify receive notification from shared user
            await requestPage.changeUser(conf.data.username_recive, conf.data.password_recive, requestPage.page);
            await expect(requestPage.dashboardLoc.notification.signalNoti).toBeVisible();
            await requestPage.checkNotification("New Request");
            await expect(requestPage.dashboardLoc.notification.requestID(listRequest[0])).toBeVisible();
            await requestPage.waitForSecond(3);

            const listDesNotifications = await requestPage.dashboardLoc.notification.desNotifications.all();
            for (let i = 0; i < requestsCreated.length; i++) {
                const descriptin = await listDesNotifications[i].textContent();
                expect(descriptin).toContain(listRequest[i]);
                expect(descriptin).toContain(conf.data.patient);
                expect(descriptin).toContain(conf.data.action_type);
            }

            //Verify in data exist in share with me
            let sharedRequestPage = new SharedRequestPage(requestPage.page);
            await sharedRequestPage.open()
            for (let i = 0; i < requestsCreated.length; i++) {
                await sharedRequestPage.search(listRequest[i].replace("#", ""))
                await expect(sharedRequestPage.dashboardLoc.table.itemInRow(listRequest[i].replace("#", ""))).toBeVisible();
            }
        })
    })

    // Tạm thời vì sẽ đang có automation link r
    // test("REQ_017 - Verify business sharing edits in case the business has not accepted the request", {
    //     tag: ['@REQ_017', '@request', '@function']
    // }, async ({ conf, browser }) => {
    //     test.setTimeout(200_000);

    //     await test.step("Get detail request", async () => {
    //         await requestPage.getDetailCase(conf.data.case);
    //     })

    //     await test.step("Edit change share to another business", async () => {
    //         await requestPage.editBusinessAndShare(conf.data.business_change_to, conf.data.user.member_new, conf.data.member_change_to);
    //     })

    //     await test.step("Check that the record no longer exists in the 'Shared with me' list of the deleted user, and that the record exists for the newly shared user", async () => {
    //         await requestPage.verifyShareRequest(browser, conf, 'member_old', true);
    //         await requestPage.verifyShareRequest(browser, conf, 'member_new', false);
    //     })

    //     await test.step("Edit change share to old business", async () => {
    //         await requestPage.editBusinessAndShare(conf.data.business_chane, conf.data.user.member_old, conf.data.member_change);
    //     })

    //     await test.step("Check that the record no longer exists in the 'Shared with me' list of the deleted user, and that the record exists for the newly shared user", async () => {
    //         await requestPage.verifyShareRequest(browser, conf, 'member_new', true);
    //         await requestPage.verifyShareRequest(browser, conf, 'member_old', false);
    //     })
    // })

    test("REQ_018 - Verify business sharing edits in case the business has accepted the request", {
        tag: ['@REQ_018', '@request', '@function']
    }, async ({ conf }) => {
        await requestPage.getDetailCase(conf.data.case);
        await requestPage.requestLoc.detail.btnDropdownEditBusiness.click();
        await requestPage.requestLoc.detail.btnEdit.click();
        await expect(requestPage.dashboardLoc.modal.headerModal("Designated Business Cannot Be Modified")).toBeVisible();
    });

    test("REQ_019 - Verify add tag in request", {
        tag: ['@REQ_019', '@request', '@function']
    }, async ({ conf }) => {
        await test.step("Navigate to request detail", async () => {
            await requestPage.getDetailCase(conf.data.case);
        });

        await test.step("Verify add tags with tag count greater than 9 (invalid)", async () => {
            await requestPage.addMultipleTags(10);
            await requestPage.saveTags();
            await expect(requestPage.dashboardLoc.tag.errorMaxTag).toBeVisible();
        });

        await test.step("Verify when add < 9 tag (valid)", async () => {
            await requestPage.removeOneTag();
            await requestPage.saveTags();
            await expect(requestPage.dashboardLoc.msgSuccess).toBeVisible();
            await requestPage.waitForSecond(1);
            await requestPage.dashboardLoc.btnClosePopupNotification.click();
            await expect(requestPage.dashboardLoc.tag.btnSaveTag).not.toBeVisible();

            const tagCount = await requestPage.getTagCount();
            expect(tagCount).toBe(9);
        });

        await test.step("Clear all tag", async () => {
            await requestPage.clearAllTags();
            await expect(requestPage.dashboardLoc.tag.btnSaveTag).not.toBeVisible();

            const tagCount = await requestPage.getTagCount();
            expect(tagCount).toBe(0);
        });
    });

    test("REQ_020 - Verify assigne request", {
        tag: ['@REQ_020', '@request', '@function']
    }, async ({ conf }) => {
        let url: string = "";
        await test.step("Get detail request", async () => {
            await requestPage.getDetailCase(conf.data.case);
        });

        await test.step("Assignee to member not exist in business", async () => {
            await requestPage.requestLoc.detail.btnAssignee.click();
            await expect(requestPage.dashboardLoc.modal.headerModal("Assignee")).toBeVisible();
            await requestPage.requestLoc.detail.inputSearchAssignee.fill(conf.data.user_not_in_business);
            await requestPage.waitForSecond(2);
            const options = await requestPage.requestLoc.detail.optionsMember.all();
            expect(options.length).toBe(1);
        });

        await test.step("Assignee to member in business", async () => {
            await requestPage.requestLoc.detail.inputSearchAssignee.clear();
            const currentUser = await requestPage.requestLoc.detail.fullnameAssignee.innerText();
            await requestPage.assignToUser(conf.data.user_recive);
            await requestPage.waitForSecond(2);

            // Verify activity
            const textActivity = await requestPage.getNewestRequestHistory();
            url = requestPage.page.url();
            expect(textActivity).toContain(`changed the Assignee ${currentUser} ${conf.data.user_recive} ${await getTodayInTimeZone()}`);
        });

        await test.step("Verify the assigned member receives a notification", async () => {
            await requestPage.changeUser(conf.data.username_recive, conf.data.password, requestPage.page);
            await requestPage.checkNotification("Assignee", true);
            await expect(requestPage.requestLoc.create.caseIDRequest).toBeVisible();
            const urlRecive = requestPage.page.url();
            expect(urlRecive).toBe(url);
        });

        await test.step("Teardown: Assign back to the previous member", async () => {
            await requestPage.requestLoc.detail.btnAssignee.click();
            await requestPage.assignToUser(conf.data.user_send);
            await expect(requestPage.dashboardLoc.notificationUpdateSuccess).toBeVisible({ timeout: 20_000 });
        });
    });


    test("REQ_021 - Verify Snapshot in request had action type Letter of Protection", {
        tag: ["@REQ_021", "@request", "@function", "@screenshot"]
    }, async ({ conf, browser }) => {
        test.setTimeout(200_000);
        const popupNewPost = requestPage.dashboardLoc.modal.headerModal("New Post: Minimize Previous Post?");
        await requestPage.page.addLocatorHandler(popupNewPost, async () => {
            await requestPage.dashboardLoc.buttonByText("Leave it").click();
        })

        await test.step("User A post a new respond", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.respondToRequest(conf.data.message);
            await requestPage.waitForSecond(2) //Wait for activity update

            const textActivity = await requestPage.getNewestRequestHistory();
            expect(textActivity).toContain(`responded to the request ${await getTodayInTimeZone()}`);
            await requestPage.verifyPostSnapshot();
            await requestPage.waitForSecond(5);
            await verifyScreenshot("post-details-snapshot.png", requestPage.requestLoc.detailPostedAttachment, [], 0.02);
            await requestPage.page.close();
        });

        await test.step("User B get noti and send back respond", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_recive, conf.data.password);
            await requestPageB.checkNotification("New Response", true);
            await requestPageB.verifyPostSnapshot();
            await verifyScreenshot("post-details-snapshot.png", requestPageB.requestLoc.detailPostedAttachment, [], 0.02);
            await requestPageB.backToRequestList();
            await requestPageB.respondToRequest(conf.data.message);
            await requestPageB.waitForSecond(2) //Wait for activity update

            const textActivityB = await requestPageB.getNewestRequestHistory();
            expect(textActivityB).toContain(`responded to the request ${await getTodayInTimeZone()}`);
            await requestPageB.verifyPostSnapshot();
            await verifyScreenshot("post-details-snapshot.png", requestPageB.requestLoc.detailPostedAttachment, [], 0.02);
            await contextB.close();
        });

        await test.step("User A check new noti and repond from user B", async () => {
            const { context: contextA, requestPage: requestPageA } = await requestPage.loginInAnotherBrowser(browser, conf.data.username, conf.data.password);
            await requestPageA.checkNotification("New Response", true);
            await requestPageA.verifyPostSnapshot();
            await verifyScreenshot("post-details-snapshot.png", requestPageA.requestLoc.detailPostedAttachment, [], 0.02);
            await contextA.close();
        });
    });

    test("REQ_023 - Verify comment in Post and Edit comment", {
        tag: ["@REQ_023", "@request", "@function", "@screenshot"]
    }, async ({ conf, browser }) => {
        test.setTimeout(180_000)
        const commentUnique = `${conf.data.comment}, ${randomString(10)}`;
        const commentReplyUnique = `${conf.data.comment_reply}, ${randomString(10)}`;

        await test.step("User A comment in newest post", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.addCommentToNewestPost(commentUnique);
            await expect(requestPage.dashboardLoc.comment.cmtInPost.last()).toContainText(commentUnique);
            await requestPage.page.close();
        });

        await test.step("User B get noti, verify comment, and comment back", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_recive, conf.data.password);
            await requestPageB.checkNotification("New Comment", true);
            await expect(requestPageB.dashboardLoc.comment.cmtInPost.last()).toContainText(commentUnique, { timeout: 30_000 });

            // User B comments back
            await requestPageB.addCommentToNewestPost(commentReplyUnique);
            await expect(requestPageB.dashboardLoc.comment.cmtInPost.last()).toContainText(commentReplyUnique);
            await contextB.close();
        });

        await test.step("User A check noti and verify comment from B", async () => {
            const { context: contextA, requestPage: requestPageA } = await requestPage.loginInAnotherBrowser(browser, conf.data.username, conf.data.password);
            await requestPageA.checkNotification("New Comment", true);
            await expect(requestPageA.dashboardLoc.comment.cmtInPost.last()).toContainText(commentReplyUnique, { timeout: 30_000 });
            await contextA.close();
        });
    });

    test("REQ_024 - Verify create new disscusion in request", {
        tag: ["@REQ_024", "@request", "@function"]
    }, async ({ conf, browser }) => {
        test.setTimeout(150_000);
        const title = conf.data.title + randomString(8);

        await test.step("User A create new discussion and add user B", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.createDiscussion(title, conf.data.member_in_discussion, conf.data.message);
            await expect(requestPage.dashboardLoc.discussion.titleDiscussion(title)).toBeVisible();
            await requestPage.page.close();
        });

        await test.step("Verify user B in discussion receives noti, opens discussion, and replies", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_in_discussion, conf.data.password);
            await requestPageB.open();
            await requestPageB.search(conf.data.case);
            await requestPageB.waitForSecond(2);
            await expect(requestPageB.requestLoc.itemInRowRequest(conf.data.case).last()).toBeVisible();
            await requestPageB.requestLoc.itemInRowRequest(conf.data.case).last().click();
            await expect(requestPageB.dashboardLoc.discussion.titleInDiscussion(title)).toBeVisible({ timeout: 30_000 });
            await requestPageB.dashboardLoc.discussion.titleDiscussionToClick(title).first().click();
            await expect(requestPageB.dashboardLoc.discussion.messageInDiscussion(conf.data.message)).toBeVisible({ timeout: 30_000 });
            await contextB.close();
        });
    })

    test("REQ_025 - Verify chat in discussion", {
        tag: ["@REQ_025", "@request", "@function"]
    }, async ({ conf, browser }) => {
        test.setTimeout(200_000);
        const msgUnique = `${conf.data.message}, ${randomString(10)}`
        const msgReplyUnique = `${conf.data.message_reply}, ${randomString(10)}`
        await requestPage.getDetailCase(conf.data.case);

        await test.step("verify user A deletes chat messages with himself", async () => {
            await requestPage.dashboardLoc.discussion.chatOnlyYou("Minh Phong").first().click();
            await requestPage.addMessageToDiscussion("Delete this message");
            await expect(requestPage.dashboardLoc.discussion.messageInDiscussion("Delete this message")).toBeVisible();
            await requestPage.dashboardLoc.discussion.btnThreeDotsActionDiscussion.last().click();
            await requestPage.dashboardLoc.discussion.btnDeleteMessage.click();
            await requestPage.requestLoc.detail.btnCofirmRemove.click();
            await expect(requestPage.dashboardLoc.discussion.messageInDiscussion("Delete this message")).not.toBeVisible();
            await requestPage.waitForSecond(1);
            await requestPage.dashboardLoc.common.spanText("Status Details:").first().click({ force: true })
        })

        await test.step("User A chats in newest discussion and sends message", async () => {
            await requestPage.dashboardLoc.discussion.newestDiscussion.click();
            await requestPage.addMessageToDiscussion(msgUnique);
            await expect(requestPage.dashboardLoc.discussion.messageInDiscussion(msgUnique).last()).toBeVisible({ timeout: 15_000 });
            await requestPage.page.close();
        });

        await test.step("User B receives noti, opens discussion, and replies", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_in_discussion, conf.data.password);
            await requestPageB.checkNotification("New Discussion", true);
            await expect(requestPageB.dashboardLoc.discussion.messageInDiscussion(msgUnique).last()).toBeVisible({ timeout: 40_000 });

            await requestPageB.dashboardLoc.discussion.btnThreeDotsReplyMessage.last().click();
            await requestPageB.dashboardLoc.discussion.btnReplyMessage.click();
            await expect(requestPageB.dashboardLoc.discussion.contentReply.last()).toContainText(msgUnique)

            await requestPageB.addMessageToDiscussion(msgReplyUnique);
            await expect(requestPageB.dashboardLoc.discussion.messageInDiscussion(msgReplyUnique).last()).toBeVisible();
            await contextB.close();
        });

        await test.step("User A receives noti and sees reply from B", async () => {
            const { context: contextA, requestPage: requestPageA } = await requestPage.loginInAnotherBrowser(browser, conf.data.username, conf.data.password);
            await requestPageA.checkNotification("New Discussion", true);
            await expect(requestPageA.dashboardLoc.discussion.messageInDiscussion(msgReplyUnique).last()).toBeVisible({ timeout: 40_000 });
            await expect(requestPageA.dashboardLoc.discussion.labelWasReply(msgReplyUnique)).toBeVisible();
            await contextA.close();
        });
    });

    test("REQ_026 - Verify update Status by change Status detail", {
        tag: ["@REQ_026", "@request", "@function"]
    }, async ({ conf }) => {
        test.setTimeout(180_000);
        await requestPage.getDetailCase(conf.data.case);
        await expect(requestPage.dashboardLoc.status.btnOpenStatusDetailDropdown).toBeVisible({ timeout: 35_000 });
        await requestPage.waitForSecond(2);

        for (const { detail, expectedStatus } of requestPage.statusTests) {
            await requestPage.dashboardLoc.status.btnOpenStatusDetailDropdown.click({ force: true });
            await requestPage.waitForSecond(0.5);
            await expect(requestPage.dashboardLoc.status.statusDetailOption(detail)).toBeVisible();
            await requestPage.dashboardLoc.status.statusDetailOption(detail).click({ force: true });
            await requestPage.waitForSecond(0.5);
            await expect(requestPage.dashboardLoc.status.statusText).toContainText(expectedStatus);
        }
    });

    // test("REQ_027_01 - Verify PUSH_RESPONSE notification turn off/on in app", {
    //     tag: ["@REQ_027", "@request", "@function"]
    // }, async ({ conf, browser, requestPage27 }) => {
    //     await requestPage27.handlePopupMinimize();
    //     test.setTimeout(200_000);
    //     const notiType = { name: "PUSH_RESPONSE", index: 0 };
    //     const uniqueMsg = `${conf.data.message}_${notiType.name}_${Date.now()}`;

    //     await test.step(`Turn off ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does NOT receive noti`, async () => {
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsg
    //         );
    //         await requestPage27.page.reload();
    //         await expect(requestPage27.dashboardLoc.notiCard).not.toBeVisible();
    //         await requestPage27.getDetailCase(conf.data.case);
    //     });

    //     await test.step(`User A turns ON ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does receive noti`, async () => {
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsg + "_on"
    //         );
    //         await requestPage27.page.reload();
    //         await requestPage27.checkNotification("New Response", true);
    //     });
    // });

    // test("REQ_027_02 - Verify PUSH_COMMENT notification turn off/on in app", {
    //     tag: ["@REQ_027", "@request", "@function"]
    // }, async ({ conf, browser, requestPage27 }) => {
    //     await requestPage27.handlePopupMinimize();
    //     test.setTimeout(230_000);
    //     const notiType = { name: "PUSH_COMMENT", index: 1 };
    //     const uniqueMsg = `${conf.data.message}_${notiType.name}_${Date.now()}`;

    //     await test.step(`Turn off ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does NOT receive noti`, async () => {
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsg
    //         );
    //         await requestPage27.page.reload();
    //         await expect(requestPage27.dashboardLoc.notiCard).not.toBeVisible();
    //         await requestPage27.getDetailCase(conf.data.case);
    //     });

    //     await test.step(`User A turns ON ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does receive noti`, async () => {
    //         const uniqueMsgOn = uniqueMsg + "_on";
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsgOn
    //         );
    //         await requestPage27.page.reload();
    //         await requestPage27.checkNotification("New Comment", true);
    //         await expect(requestPage27.dashboardLoc.comment.cmtInPost.last()).toContainText(uniqueMsgOn, { timeout: 30_000 });
    //     });
    // });

    // test("REQ_027_03 - Verify PUSH_DISCUSSION notification turn off/on in app", {
    //     tag: ["@REQ_027", "@request", "@function"]
    // }, async ({ conf, browser, requestPage27 }) => {
    //     await requestPage27.handlePopupMinimize();
    //     test.setTimeout(230_000);
    //     const notiType = { name: "PUSH_DISCUSSION", index: 2 };
    //     const uniqueMsg = `${conf.data.message}_${notiType.name}_${Date.now()}`;

    //     await test.step(`Turn off ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does NOT receive noti`, async () => {
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsg
    //         );
    //         await requestPage27.page.reload();
    //         await expect(requestPage27.dashboardLoc.notiCard).not.toBeVisible();
    //         await requestPage27.getDetailCase(conf.data.case);
    //     });

    //     await test.step(`User A turns ON ${notiType.name}`, async () => {
    //         await requestPage27.toggleNotification(notiType);
    //     });

    //     await test.step(`Another member triggers ${notiType.name} and check user A does receive noti`, async () => {
    //         const uniqueMsgOn = uniqueMsg + "_on";
    //         await requestPage27.triggerNotificationFromAnotherUser(
    //             browser,
    //             conf.data.username_in_discussion,
    //             conf.data.password,
    //             conf.data.case,
    //             notiType,
    //             uniqueMsgOn
    //         );
    //         await requestPage27.page.reload();
    //         await requestPage27.checkNotification("New Discussion", true);
    //         await expect(requestPage27.dashboardLoc.discussion.messageInDiscussion(uniqueMsgOn)).toBeVisible({ timeout: 35_000 });
    //     });
    // });

    // test.skip("REQ_028 - Verify when turnoff/turn on noti in mail", {
    //     tag: ["@REQ_028", "@request", "@function"]
    // }, async ({ conf, browser, requestPage27 }) => {
    //     test.setTimeout(200_000);
    //     for (let i = 0; i < requestPage27.notiEmail.length; i++) {
    //         const notiType = requestPage27.notiEmail[i];
    //         const uniqueMsg = `${conf.data.message}_${notiType.name}_${Date.now()}`;

    //         await test.step(`Turn off ${notiType.name}`, async () => {
    //             await requestPage27.requestLoc.detail.notification.btnOpenModalNoti.nth(1).click();
    //             await requestPage27.requestLoc.detail.notification.btnToggleSettingNoti.nth(1).click();
    //             await requestPage27.waitForSecond(2);
    //             await requestPage27.requestLoc.detail.notification.inputNotiByName(notiType.name).click({ force: true });
    //             await requestPage27.waitForSecond(2);
    //             await requestPage27.dashboardLoc.buttonByText("Close").nth(2).click();
    //         });

    //         await test.step(`Another member triggers ${notiType.name} and check user A does NOT receive noti in email`, async () => {
    //             msgOffNoti = uniqueMsg + " " + "OFF NOTI MAIL";
    //             const { context: contextB, requestPage: requestPageB } = await requestPage27.loginInAnotherBrowser(browser, conf.data.username_in_discussion, conf.data.password);
    //             await requestPageB.open();
    //             await requestPageB.getDetailCase(conf.data.case);
    //             await requestPageB.notiEmail[i].addNoti(msgOffNoti);
    //             await requestPageB.waitForSecond(2);
    //             await contextB.close();
    //         });

    //         await test.step(`User A turns ON ${notiType.name}`, async () => {
    //             await requestPage27.requestLoc.detail.notification.btnOpenModalNoti.nth(1).click();
    //             await requestPage27.requestLoc.detail.notification.btnToggleSettingNoti.nth(1).click();
    //             await requestPage27.waitForSecond(2);
    //             await requestPage27.requestLoc.detail.notification.inputNotiByName(notiType.name).click({ force: true });
    //             await requestPage27.waitForSecond(2);
    //             await requestPage27.dashboardLoc.buttonByText("Close").nth(2).click();
    //         });

    //         await test.step(`Another member triggers ${notiType.name} and check user A does NOT receive noti in email`, async () => {
    //             msgOnNoti = `${uniqueMsg} ON NOTI MAIL ${i + 1}`;
    //             const { context: contextB, requestPage: requestPageB } = await requestPage27.loginInAnotherBrowser(browser, conf.data.username_in_discussion, conf.data.password);
    //             await requestPageB.open();
    //             await requestPageB.getDetailCase(conf.data.case);
    //             await requestPageB.notiEmail[i].addNoti(msgOnNoti);
    //             listMailCheck.push(msgOnNoti);
    //             await requestPageB.waitForSecond(2);
    //             await contextB.close();
    //         });
    //     }
    // });

    // test.skip("REQ_28A - Verify mail from REQ_28", {
    //     tag: ["@REQ_28A", "@request", "@function"]
    // }, async ({ conf, request, page }) => {
    //     let mail: Mail;
    //     mail = new Mail(page, request);
    //     for (let i = 0; i < listMailCheck.length; i++) {
    //         const foundMail = await mail.findMail(listMailCheck[i], conf.data.username);
    //         expect(foundMail).toBeTruthy();
    //     }
    // })

    test("REQ_030 - Verify when clone request without archive", {
        tag: ["@REQ_030", "@request", "@function", "@screenshot"]
    }, async ({ conf, browser }) => {
        await test.step("Open clone request modal", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.openCloneRequestModal();
        });

        await test.step("Fill business and member info for clone", async () => {
            await requestPage.fillCloneRequestForm(conf.data.business, conf.data.member, conf.data.archive);
        });

        await test.step("Verify when clone successfully", async () => {
            await requestPage.submitCloneRequest();
            await expect(requestPage.requestLoc.detail.cloneRequest.msgCloneSucess).toBeVisible({ timeout: 25_000 });
            await requestPage.dashboardLoc.btnClosePopupNotification.click();
            await requestPage.waitForSecond(2);
            await verifyScreenshot('header-detail-request.png', requestPage.requestLoc.detail.headerDetail, [requestPage.requestLoc.detail.titleIdNameRequest], 0.02);
        });

        await test.step("Verify user B had noti and request in Share with me", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_in_shared, conf.data.password);
            await requestPageB.verifyAndOpenNotification(false);
            await contextB.close();
        });
    });

    test("REQ_031 - Verify when clone request and archive", {
        tag: ["@REQ_031", "@request", "@function"]
    }, async ({ conf, browser, requestPage31 }) => {
        test.setTimeout(180_000);
        let caseID: string = "";

        await test.step("Open clone request modal", async () => {
            await requestPage31.openCloneRequestModal();
        });

        await test.step("Fill business, member info and select archive option for clone", async () => {
            await requestPage31.fillCloneRequestForm(conf.data.business, conf.data.member, conf.data.archive);
        });

        await test.step("Verify when clone successfully and verify old request had archived for the creator", async () => {
            await requestPage31.submitCloneRequest();
            await expect(requestPage31.requestLoc.detail.cloneRequest.msgCloneSucess).toBeVisible({ timeout: 60_000 }); // Increased timeout for clone process
            await requestPage31.waitForSecond(3);
            caseID = (await requestPage31.requestLoc.caseIDDetail.innerText()).replace(/^#(\d+)\b.*/, "$1");

            // Verify request new request in list table
            await requestPage31.open();
            await requestPage31.search(caseID);
            await expect(requestPage31.dashboardLoc.table.itemInRow(caseID)).toBeVisible();

            // Verify request old request  not in list table
            await requestPage31.search(conf.data.case);
            await requestPage31.waitForSecond(2);
            await expect(requestPage31.dashboardLoc.table.itemInRow(conf.data.case)).not.toBeVisible();
        });

        await test.step("Verify user B had noti and request in Share with me", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage31.loginInAnotherBrowser(browser, conf.data.username_in_shared, conf.data.password);
            await requestPageB.verifyAndOpenNotification(false);
            expect((await requestPageB.requestLoc.caseIDDetail.innerText()).replace(/^#(\d+)\b.*/, "$1")).toBe(caseID);
            await contextB.close();
        });
    });

    test("REQ_033 - Verify deletion or add of unlinked case members", {
        tag: ["@REQ_033", "@request", "@function"]
    }, async ({ conf, browser, requestPage33 }) => {
        test.setTimeout(180_000);
        await test.step("Verify UI user triduc (not a person who share request)", async () => {
            const { context: contextB, requestPage: requestPageB } = await requestPage33.loginInAnotherBrowser(browser, conf.data.username_member_a, conf.data.password);
            await requestPageB.open();
            await requestPageB.getDetailCase(conf.data.case);
            await requestPageB.dashboardLoc.buttonByText("Share").click();
            await expect(requestPageB.page.locator('#modal-share')).toMatchAriaSnapshot(`
              - text: "To:"
              - textbox "To Add People People"
              - text: Cc Bcc
              - checkbox "Send email notification" [checked]
              - text: Send email notification Message
              - textbox "Message"
              - paragraph: People with access
              - link "Sent Summary":
                - /url: /requests/sent?request_id=275078
              - paragraph: Auto Test.Pharmacy
              - paragraph: "***********************************.com"
              - paragraph: Tri01 Duc
              - paragraph: triducgog0301+1@gmail.com (You)
              - text: Unfollow
              - paragraph: Minh Phong
              - paragraph: minhphong.simple@gmail.com
              - paragraph: Creator
              `);
            await contextB.close();
        })

        await test.step("Verify when delete user portal from request", async () => {
            await requestPage33.open();
            await requestPage33.getDetailCase(conf.data.case);
            await requestPage33.dashboardLoc.buttonByText("Share").click();
            await requestPage33.requestLoc.detail.share.btnDeleteByMemberName(conf.data.member_name_delete).click();
            await requestPage33.requestLoc.detail.btnCofirmRemove.click();
        })

        await test.step("Verify request not exist in Share with me of user had deleted", async () => {
            const { context: contextC, requestPage: requestPageC } = await requestPage33.loginInAnotherBrowser(browser, conf.data.username_member_delete, conf.data.password);
            let shareWithMePage = new SharedRequestPage(requestPageC.page);
            await shareWithMePage.open();
            await shareWithMePage.search(conf.data.case);
            await expect(shareWithMePage.dashboardLoc.table.noResult).toBeVisible();
            await contextC.close();
        })

        await test.step("Verify when add user C again", async () => {
            await requestPage33.requestLoc.detail.inputSeachMember.fill(conf.data.member_name_delete);
            await requestPage33.requestLoc.create.dropdownMemberShare(conf.data.member_name_delete).click();
            await requestPage33.dashboardLoc.buttonByText("Done").first().click()
        })

        await test.step("Verify request exist in Share with me of user had added", async () => {
            const { context: contextC, requestPage: requestPageC } = await requestPage.loginInAnotherBrowser(browser, conf.data.username_member_delete, conf.data.password);
            let shareWithMePage = new SharedRequestPage(requestPageC.page);
            await shareWithMePage.open();
            await shareWithMePage.search(conf.data.case);
            await expect(shareWithMePage.dashboardLoc.table.noResult).not.toBeVisible();
            await contextC.close();
        })
    })

    test("REQ_034 - Validate reduction and update balance medical bill", {
        tag: ["@REQ_034", "@request", "@function"]
    }, async ({ conf }) => {

        await test.step("Search and verify modal reduction", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.dashboardLoc.buttonLinkByText("Reduction").click();
            await expect(requestPage.dashboardLoc.modal.headerModal("Message")).toBeVisible();
        });

        await test.step("Verify change reduction will change the suggested Balance", async () => {
            const balanceBeforeValue = extractNumber(await requestPage.requestLoc.detail.snapshot.inputBalance.inputValue());
            const randomReduction = getRandomNumberInRange(100, 1);
            await requestPage.requestLoc.detail.snapshot.inputReduction.fill(randomReduction.toString());

            const expectedReductionOffer = parseFloat((balanceBeforeValue * randomReduction / 100).toFixed(2));
            const actualReductionOffer = extractNumber(await requestPage.requestLoc.detail.snapshot.inputReductionOffer.inputValue());

            const suggestedBalanceValue = extractNumber(await requestPage.requestLoc.detail.snapshot.inputTotal.inputValue());
            const expectedSuggestedBalance = parseFloat((balanceBeforeValue - expectedReductionOffer).toFixed(2));

            expect(actualReductionOffer).toBeCloseTo(expectedReductionOffer, 2);
            expect(suggestedBalanceValue).toBeCloseTo(expectedSuggestedBalance, 2);
        });

        await test.step("Verify change suggested Balance will change the reduction", async () => {
            const balanceBeforeValue = extractNumber(await requestPage.requestLoc.detail.snapshot.inputBalance.inputValue());
            const randomSuggestedBalance = getRandomNumberInRange(balanceBeforeValue - 1, 1);
            await requestPage.requestLoc.detail.snapshot.inputTotal.fill(randomSuggestedBalance.toString());

            const expectedReductionOffer = parseFloat((balanceBeforeValue - randomSuggestedBalance).toFixed(2));
            const actualReductionOffer = extractNumber(await requestPage.requestLoc.detail.snapshot.inputReductionOffer.inputValue());

            const actualReductionPercentage = extractNumber(await requestPage.requestLoc.detail.snapshot.inputReduction.inputValue());
            const expectedReductionPercentage = parseFloat((expectedReductionOffer / balanceBeforeValue * 100).toFixed(2));

            expect(actualReductionOffer).toBeCloseTo(expectedReductionOffer, 2);
            expect(actualReductionPercentage).toBeCloseTo(expectedReductionPercentage, 2);

            await requestPage.requestLoc.detail.btnCancelModalMessage.click();
        });

        await test.step("Verify when change update medical bill", async () => {
            const newBalance = getRandomNumberInRange(20000, 1);
            await requestPage.dashboardLoc.buttonLinkByText("Update Balance").click();
            await expect(requestPage.dashboardLoc.modal.headerModal("Message")).toBeVisible();
            await requestPage.requestLoc.detail.snapshot.inputTotal.fill(newBalance.toString());
            const balanceInMessage = await requestPage.requestLoc.detail.snapshot.balanceValueInMessage.innerText();
            expect(parseFloat(balanceInMessage.replace(/[^0-9.-]/g, ""))).toBe(newBalance);
        })
    });

    test("REQ_036 - Verify when change Medicall bill Star had change Medicall Bill in Affidavit", {
        tag: ["@REQ_036", "@request", "@function", "@screenshot"]
    }, async ({ conf, requestPage36 }) => {
        await test.step("Check medical bill before change star", async () => {
            await expect(requestPage36.requestLoc.detail.snapshot.titleMedicalBillStar).toContainText(conf.data.request_first);
            const listPostMedicalBill = (await requestPage36.requestLoc.detail.snapshot.listPostMedicalbill.all()).length;
            expect(listPostMedicalBill).toBe(2);
            await requestPage36.requestLoc.detail.snapshot.btnCloseModal.click();
        })

        await test.step("Check medical bill after change star", async () => {
            await requestPage36.requestLoc.detail.caseID(conf.data.case_client).click();
            let casePage = new CasePage(requestPage36.page);
            await casePage.changeStarFocus(conf.data.request_second);
            await requestPage36.open();
            await requestPage36.getDetailRequest(conf.data.case);

            await requestPage36.dashboardLoc.buttonLinkByText("Provide").click();
            await expect(requestPage36.dashboardLoc.modal.headerModalContainText("Prepare Records")).toBeVisible();

            await expect(requestPage36.requestLoc.detail.snapshot.titleMedicalBillStar).toContainText(conf.data.request_second);
            const listPostMedicalBill = (await requestPage36.requestLoc.detail.snapshot.listPostMedicalbill.all()).length;
            expect(listPostMedicalBill).toBe(1);
        })
    })

    test("REQ_037 - Verify prodive manually Affidavit", {
        tag: ["@REQ_037", "@request", "@function"]
    }, async ({ conf }) => {
        const filePath1 = path.resolve(__dirname, 'file/file-test.pdf');
        const filePath2 = path.resolve(__dirname, 'file/img-test.png');
        const filePathExceedMaximum = path.resolve(__dirname, 'file/file-test-50mb.pdf');
        const filePathInvalid = path.resolve(__dirname, 'file/file-test-invalid-type.exe');

        await test.step("Verify open modal update maunualy", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.dashboardLoc.buttonLinkByText("Provide").click();
            await expect(requestPage.dashboardLoc.modal.headerModalContainText("Prepare Records")).toBeVisible();
            await requestPage.dashboardLoc.buttonByText("Skip, upload manually").click();
        })

        await test.step("Verify upload exceed size file", async () => {
            await requestPage.requestLoc.detail.snapshot.inputUploadFile.setInputFiles(filePathExceedMaximum);
            await expect(requestPage.dashboardLoc.modal.errorMessageSpan(conf.data.message_error_maximum)).toBeVisible({ timeout: 20_000 });
        });

        await test.step("Verify upload invalid file", async () => {
            await requestPage.requestLoc.detail.snapshot.inputUploadFile.setInputFiles(filePathInvalid);
            await expect(requestPage.dashboardLoc.tag.errorMaxTag).toContainText(conf.data.message_invalid_file, { timeout: 15_000 });
        });

        await test.step("Verify upload more than maximum allowed", async () => {
            const filesArray = Array(51).fill(filePath1);
            await requestPage.requestLoc.detail.snapshot.inputUploadFile.setInputFiles(filesArray);
            await expect(requestPage.dashboardLoc.modal.errorMessageSpan(conf.data.message_error_maximum_file)).toBeVisible({ timeout: 20_000 });
        });

        await test.step("Verify upload maximum 50 files", async () => {
            const buffer = fs.readFileSync(filePath1);
            const filesArray = Array.from({ length: 49 }, (_, i) => ({
                name: `file-test-${i + 1}.pdf`,
                mimeType: 'application/pdf',
                buffer
            }));
            await requestPage.requestLoc.detail.snapshot.inputUploadFile.setInputFiles(filesArray, { timeout: 60_000 });
            // await expect(requestPage.requestLoc.detail.uploadZone).not.toBeVisible();
            for (let i = 0; i < 49; i++) {
                await expect(requestPage.requestLoc.detail.snapshot.fileName(`file-test-${i + 1}.pdf`)).toBeVisible();
            }
            await expect(requestPage.dashboardLoc.modal.errorMessageSpan(conf.data.message_error_maximum_file)).not.toBeVisible({ timeout: 20_000 });
        });

        await test.step("Verify upload 2 file", async () => {
            // Reopen modal to upload file again
            await requestPage.requestLoc.detail.btnCancelModalMessage.click();
            await expect(requestPage.dashboardLoc.modal.headerModalContainText("Prepare Records")).toBeVisible();
            await requestPage.dashboardLoc.buttonByText("Skip, upload manually").click();
            await requestPage.waitForSecond(5);
            await expect(requestPage.dashboardLoc.common.spanText("Type New")).toBeVisible();
            await requestPage.dashboardLoc.common.spanText("Type New").click({ force: true });
            await requestPage.requestLoc.textEditorCreateCaseArea.fill("Data Test");
            await requestPage.requestLoc.detail.snapshot.inputUploadFile.setInputFiles([filePath1, filePath2]);
            await expect(requestPage.requestLoc.detail.snapshot.fileName("file-test.pdf")).toBeVisible();
            await expect(requestPage.requestLoc.detail.snapshot.fileName("img-test.png")).toBeVisible();
        });

        await test.step("Verify submit post with file", async () => {
            await requestPage.requestLoc.detail.btnSubmitMessage.click();
            await expect(requestPage.requestLoc.messageRepondSucces.first()).toBeVisible();
            await requestPage.dashboardLoc.buttonByText("Minimize").click();
        });
    });

    test("REQ_038 - Affidavit - When Type New: Hide block “Files you have selected …”", {
        tag: ["@REQ_038", "@request", "@function"]
    }, async ({ conf }) => {
        await test.step("Verify show box selected files", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.dashboardLoc.buttonLinkByText("Provide").click();
            await requestPage.requestLoc.detail.snapshot.checkFileAffidatvit.first().click();
            await requestPage.requestLoc.detail.btnNextPrepareRecord.click();
            await expect(requestPage.requestLoc.detail.snapshot.boxSelectedFiles).toBeVisible({ timeout: 15_000 });
        })

        await test.step("Verify when change to type new not show box selected filess", async () => {
            await requestPage.requestLoc.detail.snapshot.buttonTypeNew.click();
            await expect(requestPage.requestLoc.detail.snapshot.boxSelectedFiles).not.toBeVisible();
        })
    })

    test("REQ_040 - Verify add request to Cart from action and remove requests from cart", {
        tag: ["@REQ_040", "@request", "@function"]
    }, async ({ conf, checkCart }) => {
        await test.step("Add request to cart", async () => {
            await checkCart.search(conf.data.case);
            await requestPage.waitForSecond(2);

            await checkCart.requestLoc.detail.cartRequest.iconShowListCart.first().click();
            await expect(checkCart.requestLoc.detail.cartRequest.titleListCart).toBeVisible();

            //Add 8 requests from request page
            for (let i = 0; i < 8; i++) {
                await checkCart.requestLoc.detail.cartRequest.itemsInListCart.first().click();
            }
            await expect(checkCart.requestLoc.detail.cartRequest.quickSubmitButton("8")).toBeVisible();

            //Add more 2 requests in Fast submission
            await checkCart.requestLoc.detail.cartRequest.quickSubmitButton("8").click();
            await checkCart.dashboardLoc.buttonByText("Add more").click();
            await checkCart.waitForSecond(0.5);
            await checkCart.dashboardLoc.buttonByText("Add more").click();

            const listRequest = (await checkCart.requestLoc.detail.cartRequest.listRequestsInFastCreate.all()).length;
            expect(listRequest).toBe(10);
            await checkCart.waitForSecond(2);
        })

        await test.step("Verify delete action type Letter of protection, medical bill and prescription", async () => {
            let listRequest = (await checkCart.requestLoc.detail.cartRequest.listRequestsInFastCreate.all()).length;

            while (listRequest > 7) {
                try {
                    await checkCart.requestLoc.detail.cartRequest.deleteFirstCart.click();
                    await checkCart.waitForSecond(3);
                } catch (error) {
                    console.log("Error get list request", error);
                    break;
                }
                listRequest = (await checkCart.requestLoc.detail.cartRequest.listRequestsInFastCreate.all()).length;
            }

            expect(listRequest).toBe(7);

            await checkCart.dashboardLoc.cart.buttonCart.hover();
            await expect(checkCart.dashboardLoc.cart.totalRequestsInCart("5")).toBeVisible()
        })
    })

    test("REQ_041 - Verify when adding a request by hovering over the Case ID from two different business", {
        tag: ["@REQ_041", "@request", "@function", "@screenshot"]
    }, async ({ conf, checkCart }) => {
        await test.step("Add two requests from first request", async () => {
            await checkCart.search(conf.data.case_first);
            expect(async () => {
                const rowCount = await checkCart.getTableRowCount();
                expect(rowCount).toBe(1);

            }).toPass();
            await checkCart.waitForSecond(1);

            await checkCart.dashboardLoc.table.itemInRow(conf.data.case_from_request_first).hover({ force: true });
            //Create by business (Dat Lawyer)
            await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Letter of Protection").click();

            //Create by business The Vu Law Firm
            await checkCart.requestLoc.detail.cartRequest.optionBusinessInCart("The Vu Law Firm").click();
            await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Medical Bill").click();

            await expect(checkCart.requestLoc.detail.cartRequest.quickSubmitButton("2")).toBeVisible();
        })

        await test.step("Add two requests from second request", async () => {
            await checkCart.search(conf.data.case_second);
            expect(async () => {
                const rowCount = await checkCart.getTableRowCount();
                expect(rowCount).toBe(1);
            }).toPass();
            await requestPage.waitForSecond(1);

            await checkCart.dashboardLoc.table.itemInRow(conf.data.case_from_request_second).hover();

            //Create by business A Taylor Law Firm
            await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Affidavit").click();

            //Create by business (Portal-Auto-Lawyer)
            await checkCart.requestLoc.detail.cartRequest.optionBusinessInCart("(Portal-Auto-Lawyer)").click();
            await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Others").click();

            await checkCart.requestLoc.headingRequestPage.click();
            await expect(checkCart.requestLoc.detail.cartRequest.quickSubmitButton("4")).toBeVisible();
        })

        await test.step("Verify list requests in cart", async () => {
            await checkCart.requestLoc.detail.cartRequest.quickSubmitButton("4").click();
            await expect(checkCart.requestLoc.detail.cartRequest.tdInTable("A Taylor Law Firm")).toBeVisible();
            await verifyScreenshot('list-request-overview.png', checkCart.requestLoc.create.overviewCreateFast, [], 0.02);
        })
    });

    test("REQ_043 - Share request: Sharing without a message and verify MFA on", {
        tag: ["@REQ_043", "@request", "@function", "@screenshot"]
    }, async ({ conf, request, browser }) => {
        test.setTimeout(200_000);
        await test.step("Open request detail and share without message", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.shareRequestToEmail(requestPage, conf.data.user_share);
            await requestPage.page.close();
        });

        await test.step('Verify email received and click open request', async () => {
            const newContext = await browser.newContext();
            const newPage = await newContext.newPage();

            const mail = new Mail(newPage, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("#630061").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody");
            const mask = mailFrame.locator("//table[@class='es-header-body']/tbody/descendant::p").first();
            await verifyScreenshot('share-request-without-message.png', tbodyHtml, [mask], 0.02);
            await mail.waitForSecond(2);

            const buttonOpenRequest = mailFrame.locator('//a[contains(text(),"Open")]');
            const newTabPage = await requestPage.openLinkAndCompletePasscode(requestPage, request, buttonOpenRequest);
            await newTabPage.waitForSecond(3);

            // Verify MFA page
            await expect(newTabPage.page).toHaveURL(/2fa-verification/);
            const code = authenticator.generate(conf.data.MFA);
            // Split code into 6 digits
            const digits = code.split('');
            for (let i = 0; i < 6; i++) {
                await newTabPage.page.locator(`//input[@id="digit-${i + 1}"]`).press(digits[i], {
                    delay: 200,
                });
            }
            await newTabPage.page.locator("//button[@type='submit' and normalize-space()='Confirm']").click();
            await newTabPage.waitAllRequestCompeleted();
            expect(newTabPage.page.url()).toContain(`requests/${conf.data.case}`);
        });
    });

    test("REQ_043A - Share request: Sharing without a message and verify blackup link", {
        tag: ["@REQ_043A", "@request", "@function", "@screenshot"]
    }, async ({ conf, request, browser }) => {
        await test.step("Open request detail and share without message", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.shareRequestToEmail(requestPage, conf.data.user_share);
            await requestPage.page.close();
        });

        await test.step('Verify email received and click open request', async () => {
            const newContext = await browser.newContext();
            const newPage = await newContext.newPage();

            const mail = new Mail(newPage, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("#918138").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody");
            const mask = mailFrame.locator("//table[@class='es-header-body']/tbody/descendant::p").first();
            await verifyScreenshot('share-request-without-message.png', tbodyHtml, [mask], 0.02);
            await mail.waitForSecond(2);

            const linkBackupGotoRequest = mailFrame.locator('//a[contains(.,"qa.loprx")]').last();
            const newTabPage = await requestPage.openLinkAndCompletePasscode(requestPage, request, linkBackupGotoRequest);

            await mail.page.reload();
            await mail.mailLoc.titleMail("your passcode").first().click();
            await expect(mailFrame.locator('//p[contains(text(),"5 minutes")]')).toBeVisible();

            await newTabPage.waitForSecond(3);
            expect(newTabPage.page.url()).toContain(`requests/${conf.data.case}`);
        });
    });

    test("REQ_044 - Share request: Sharing with a message", {
        tag: ["@REQ_044", "@request", "@function", "@screenshot"]
    }, async ({ conf, request, browser }) => {
        test.setTimeout(200_000);
        await test.step("Open request detail and share with message", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.shareRequestToEmail(requestPage, conf.data.user_share, conf.data.message_sent);
            await requestPage.page.close();
        });

        await test.step('Verify email received and click open request', async () => {
            const newContext = await browser.newContext();
            const newPage = await newContext.newPage();

            const mail = new Mail(newPage, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("John Doe 65423").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody");
            const mask = mailFrame.locator("//table[@class='es-header-body']/tbody/descendant::p").first();
            await verifyScreenshot('share-request-with-message.png', tbodyHtml, [mask], 0.02)

            const buttonShareRequest = mailFrame.locator('//a/span[contains(text(),"Share")]');
            const newTabPage = await requestPage.openLinkAndCompletePasscode(requestPage, request, buttonShareRequest);
            await newTabPage.waitForSecond(3);
            expect(newTabPage.page.url()).toContain(`requests/${conf.data.case}`);
            await expect(newTabPage.dashboardLoc.modal.headerModal("Share with others")).toBeVisible();
        });
    });

    test("REQ_045 - Share request: Sharing multiple requests with a single user using Bulk Edit", {
        tag: ["@REQ_045", "@request", "@function", "@screenshot"]
    }, async ({ conf, request, browser }) => {
        test.setTimeout(200_000);
        await test.step("Verify sharing multiple requests for single user", async () => {
            const SHARE_COUNT = 3;
            await requestPage.bulkShareFirstNRequests(requestPage, SHARE_COUNT, conf.data.user_share);
            await requestPage.page.close()
        });

        await test.step('Verify email received', async () => {
            const newContext = await browser.newContext();
            const newPage = await newContext.newPage();

            const mail = new Mail(newPage, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("3 requests").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody").first();
            const dataInRow = mailFrame.locator("//td[@style='font-weight:400; color:#181C32; font-size:14px;']")
            await verifyScreenshot('share-multi-requests.png', tbodyHtml, [dataInRow.first(), dataInRow.nth(1), dataInRow.nth(2)], 0.02)
        });
    });

    test("REQ_046 - Sharing a request with multiple people", {
        tag: ["@REQ_046", "@request", "@function"]
    }, async ({ conf, request }) => {
        test.setTimeout(200_000);
        await test.step("Open request detail and share without message", async () => {
            await requestPage.getDetailCase(conf.data.case);
            const emails = Object.values(conf.data.user_share).map((v: any) => String(v));
            await requestPage.waitForSecond(1);
            await expect(requestPage.dashboardLoc.buttonByText("Share")).toBeVisible();
            await requestPage.shareToMultipleEmails(requestPage, emails);
        });

        await test.step('Verify email received', async () => {
            const mail = new Mail(requestPage.page, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("Letter of Protection #543267").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const buttonOpenRequest = mailFrame.locator('//a[contains(text(),"Open")]');

            // Wait for new tab and click Open button
            const [newPage] = await Promise.all([
                requestPage.page.context().waitForEvent('page'),
                buttonOpenRequest.click()
            ]);

            const newTabPage = new RequestPage(newPage);
            await expect(newTabPage.requestLoc.detail.share.boxEnterEmail).toBeVisible();
        });
    })

    test("REQ_047 - Verify mail when chat in discussion", {
        tag: ["@REQ_047", "@request", "@function", "@screenshot"]
    }, async ({ conf, request }) => {
        const msgUnique = `${conf.data.message} discusssion ${randomString(10)}`

        await test.step("Open request detail and chat in discussion", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.dashboardLoc.discussion.newestDiscussion.click();
            await requestPage.addMessageToDiscussion(msgUnique);
            await expect(requestPage.dashboardLoc.discussion.messageInDiscussion(msgUnique).last()).toBeVisible();
        });

        await test.step('Verify email received', async () => {
            const mail = new Mail(requestPage.page, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("a message in").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody");
            const rowData = mailFrame.locator(`//p[contains(text(),"${msgUnique}")]`);
            await expect(rowData).toBeVisible();
            await verifyScreenshot('chat-in-discussion.png', tbodyHtml, [rowData], 0.03);
        });
    });

    test("REQ_048 - Verify mail when comment in post", {
        tag: ["@REQ_047", "@request", "@function", "@screenshot"]
    }, async ({ conf, request }) => {
        const commentUnique = `${conf.data.message} comment ${randomString(10)}`

        await test.step("Open request detail and chat in discussion", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.addCommentToNewestPost(commentUnique);
            await expect(requestPage.dashboardLoc.comment.cmtInPost.last()).toContainText(commentUnique);
        });

        await test.step('Verify email received', async () => {
            const mail = new Mail(requestPage.page, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail("a comment").first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            const tbodyHtml = mailFrame.locator("//table[@class='es-header-body']/tbody");
            const rowData = mailFrame.locator(`//p[contains(text(),"${commentUnique}")]`);
            await expect(rowData).toBeVisible();
            await verifyScreenshot('comment-in-post.png', tbodyHtml, [rowData], 0.04);
        });
    });

    test("REQ_049 - Verify DOI when apply with multi requests", {
        tag: ["@REQ_049", "@request", "@function"]
    }, async ({ conf }) => {
        await test.step("Goto create new with Fast Submission", async () => {
            await requestPage.gotoCreateRequest("multi");
            await expect(requestPage.dashboardLoc.buttonByText("Switch to Step-by-Step")).toBeVisible();
        })

        await test.step("Verify when click add more request", async () => {
            await requestPage.dashboardLoc.buttonByText("Add more").click();
            const listOfCreationRequests = (await requestPage.requestLoc.create.boxCreateMultiRequests.all()).length;
            expect(listOfCreationRequests).toBe(2);
        })

        await test.step("Verify add patient, apply all and check DOI in row 2", async () => {
            await requestPage.requestLoc.create.itemStep(2).first().click();
            await requestPage.fillDataCreateRequest("Type or select a name", "Name", conf.data.patient);
            await requestPage.requestLoc.create.inputCheckAll("patient").click();
            await requestPage.waitForSecond(2);
            await requestPage.requestLoc.create.inputCheckAll("patient").click()
            await expect(requestPage.requestLoc.create.itemRow2).toBeVisible();
            await requestPage.requestLoc.create.itemRow2.click();
            await expect(requestPage.requestLoc.create.inputDOIInStep2).toBeVisible();
            await requestPage.waitForSecond(2);
            await expect(requestPage.requestLoc.create.inputDOIInStep2).toHaveValue("01/01/1992")
        })
    })

    test("REQ_050 - Verify choose message template when create new request", {
        tag: ["@REQ_050", "@request", "@function"]
    }, async ({ conf }) => {
        // Handle missing info popup if it appears
        await requestPage.handleMissingInfoPopup();

        await test.step("Verify create request with Edit template message", async () => {
            await requestPage.initiateRequestCreation(conf.data.patient);

            // Select and edit template
            await requestPage.requestLoc.create.arrowIcon.click();
            await requestPage.dashboardLoc.common.spanText("Template-2 Rxs Pad (Editor)").click();

            const textEditor = requestPage.requestLoc.create.textEditorCreateFast.first();
            await textEditor.click();
            await textEditor.press('ControlOrMeta+a');
            await textEditor.press('Delete');
            await textEditor.fill(conf.data.message_edit_text);
            await requestPage.requestLoc.create.closeModalMessage.click();

            await requestPage.submitAndVerifyRequest("post-details-create-template-editor-snapshot.png");
        });

        await test.step("Verify create request with Form text message", async () => {
            await requestPage.initiateRequestCreation(conf.data.patient);

            // Select and configure form template
            await requestPage.requestLoc.create.arrowIcon.click();
            await requestPage.dashboardLoc.common.spanText("Template-3 DME Rx Pad (Form)").click();

            const textEditorForm = requestPage.page.locator('iframe[title="iframe-editor"]');
            const formContent = textEditorForm.contentFrame();

            // Clear existing content and set form options
            await formContent.getByText('Dr. Jason Phan').dblclick();
            await formContent.locator('body').press('ControlOrMeta+a');
            await formContent.locator('body').press('Delete');

            // Check all language options
            const languageOptions = ['Vietnamese', 'Chinese', 'Spanish'];
            for (const lang of languageOptions) {
                await formContent.getByRole('checkbox', { name: `Label in ${lang}` }).check();
            }

            await requestPage.requestLoc.create.closeModalMessage.click();
            await requestPage.submitAndVerifyRequest("post-details-create-template-form-snapshot.png");
        });
    });

    test.skip("REQ_051 - Add more than 20 requests to the cart and create multiple requests", {
        tag: ["@REQ_051", "@request", "@function", "@screenshot"]
    }, async ({ conf, checkCart }) => {
        test.setTimeout(300_000);
        const businesses = ["(Dat Lawyers)", "The Vu Law Firm", "A Taylor Law Firm"];
        await test.step("Add 24 requests by hovering in case id to cart", async () => {
            await checkCart.search(conf.data.request);
            await expect(checkCart.dashboardLoc.table.itemInRow(conf.data.case)).toBeVisible();
            await checkCart.waitForSecond(1);
            await checkCart.dashboardLoc.table.itemInRow(conf.data.case).hover();
            for (let i = 0; i < businesses.length; i++) {
                await checkCart.requestLoc.detail.cartRequest.optionBusinessInCart(businesses[i]).click();
                for (let j = 0; j < 8; j++) {
                    await checkCart.requestLoc.detail.cartRequest.listRequestTypeByHovering.first().click();
                }
            }
            await checkCart.page.mouse.move(30, 30);
            await expect(checkCart.requestLoc.detail.cartRequest.quickSubmitButton("24")).toBeVisible();
        })

        await test.step("Submit 24 requests, and verify that only 20 are successfully added to the cart, with 4 remaining", async () => {
            await requestPage.handleMissingInfoPopup();

            await checkCart.requestLoc.detail.cartRequest.quickSubmitButton("24").click();
            await requestPage.requestLoc.create.inputCheckAll("action").click();

            //Add message
            await requestPage.requestLoc.create.itemStep(4).first().click();
            await requestPage.requestLoc.textEditorCreateCaseArea.first().waitFor({ state: 'visible' });
            await requestPage.requestLoc.textEditorCreateCaseArea.fill("Message");

            await requestPage.requestLoc.create.inputCheckAll("message").click();
            await checkCart.dashboardLoc.buttonByText("Create").first().click();
            await expect(checkCart.dashboardLoc.buttonByText("Create Another")).toBeVisible({ timeout: 250_000 }); // Create 20 request in once can take longer time

            //Verify cart have 4 requests left
            await checkCart.dashboardLoc.cart.buttonCart.hover({ force: true });
            await expect(checkCart.dashboardLoc.cart.requestButtonCart).toBeVisible();
            await checkCart.dashboardLoc.cart.requestButtonCart.click();
            await expect(checkCart.requestLoc.detail.cartRequest.tdInTable("A Taylor Law Firm").first()).toBeVisible();
            await verifyScreenshot('list-request-left-4-requests.png', checkCart.requestLoc.create.overviewCreateFast);
        });
    });

    test("REQ_052 - Resend mail", {
        tag: ["@REQ_052", "@request", "@function"]
    }, async ({ conf, request, browser }) => {
        await test.step("Click resend mail", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await expect(requestPage.dashboardLoc.buttonByText("Share")).toBeVisible();

            await requestPage.dashboardLoc.buttonByText("Share").click();
            await expect(requestPage.dashboardLoc.modal.headerModal("Share with others")).toBeVisible();
            await expect(requestPage.requestLoc.detail.rowMemberShare(conf.data.member_share)).toBeVisible();

            await requestPage.requestLoc.detail.rowMemberShare(conf.data.member_share).hover();
            await requestPage.requestLoc.detail.btnResend.first().click();
            await expect(requestPage.requestLoc.detail.tagMemberShared(conf.data.member_share)).toBeVisible();

            await requestPage.requestLoc.detail.rowMemberShare(conf.data.member_share).hover();
            await expect(requestPage.requestLoc.detail.btnResend.first()).not.toBeVisible();
        });

        await test.step("Verify submit and email received", async () => {
            await requestPage.dashboardLoc.buttonByText("Done").first().click();
            await expect(requestPage.dashboardLoc.msgSuccess).toBeVisible();
            await requestPage.page.close();

            const newContext = await browser.newContext();
            const newPage = await newContext.newPage();

            const mail = new Mail(newPage, request);
            await mail.open();
            await mail.waitForSecond(conf.data.wait_for_email_second);

            // Find and verify the share email
            await mail.mailLoc.titleMail(`Letter of Protection #${conf.data.case}`).first().click();
            const mailFrame = mail.mailLoc.mailFrame;
            await mail.waitForSecond(2);

            const buttonOpenRequest = mailFrame.locator('//a[contains(text(),"Open")]');
            const newTabPage = await requestPage.openLinkAndCompletePasscode(requestPage, request, buttonOpenRequest);
            await newTabPage.waitForSecond(3);
            expect(newTabPage.page.url()).toContain(`requests/${conf.data.case}`);
        });
    });

    test("REQ_053 - Verify when click in the Sent Summary", {
        tag: ["@REQ_053", "@request", "@function"]
    }, async ({ conf }) => {
        await test.step("Open Sent Summary modal", async () => {
            await requestPage.getDetailCase(conf.data.case);
            await requestPage.requestLoc.detail.btnShare.click();
            await expect(requestPage.dashboardLoc.buttonLinkByText("Sent Summary")).toBeVisible();
        });

        await test.step("Verify when click Sent Summary", async () => {
            await requestPage.dashboardLoc.buttonLinkByText("Sent Summary").click();
            await expect(requestPage.page.url()).toContain(`/requests/sent?request_id=${conf.data.case}`);
            await expect(requestPage.dashboardLoc.table.boxSelectedFilter(conf.data.case)).toBeVisible();
        });
    });
});
