import { Browser, BrowserContext, expect, Locator, Page } from "@playwright/test";
import { DashboardPage } from "../dashboard.page";
import { createRequestFastSubmission, createRequestFastSubmissionMulti, createRequestStepByStep, detailRequestBody, detailRequestEditShare, detailRequestEditShareProduction, detailRequestHeader, detailRequestHeaderProduction, emptyState, headingAndCreateButton, tipsBlock } from "./request.snapshot";
import { assertionHelper } from "../../helper/assertion.helper";
import { LoginPage } from "../login.page";
import { SharedRequestPage } from "../share-request.page";
import { extractVerificationCode } from "../../utils/mail";
import { takeScreenshot, verifyScreenshot } from "../../utils/screenshot";

export class RequestPage extends DashboardPage {
  constructor(page: Page) {
    super(page);
  }

  get requestSnapshot() {
    return {
      headingAndCreateButton: headingAndCreateButton,
      tipsBlock: tipsBlock,
      emptyState: emptyState,
      createRequestFastSubmission: createRequestFastSubmission,
      createRequestStepByStep: createRequestStepByStep,
      detailRequestHeader: detailRequestHeader,
      detailRequestBody: detailRequestBody,
      detailRequestEditShare: detailRequestEditShare,
      detailRequestHeaderProduction: detailRequestHeaderProduction,
      detailRequestEditShareProduction: detailRequestEditShareProduction,
      createRequestFastSubmissionMulti: createRequestFastSubmissionMulti
    };
  }

  statusTests = [
    { detail: 'Inquiry', expectedStatus: 'Open' },
    { detail: 'Awaiting', expectedStatus: 'Open' },
    { detail: 'Preparing', expectedStatus: 'In Progress' },
    { detail: 'Verbal Approval', expectedStatus: 'In Progress' },
    { detail: 'On Hold', expectedStatus: 'On Hold' },
    { detail: 'Processed', expectedStatus: 'Closed' },
    { detail: 'Provided', expectedStatus: 'Closed' },
    { detail: 'Accepted', expectedStatus: 'Closed' },
    { detail: 'Cancelled', expectedStatus: 'Closed' },
    { detail: 'Declined', expectedStatus: 'Closed' }
  ];

  notiApp = [
    {
      name: "PUSH_RESPONSE",
      addNoti: (reponse: string) => this.respondToRequest(reponse)
    },
    {
      name: "PUSH_COMMENT",
      addNoti: (comment: string) => this.addCommentToNewestPost(comment)
    },
    {
      name: "PUSH_DISCUSSION",
      addNoti: (inbox: string) => this.addNewMessageToDiscussion(inbox)
    }
  ]

  notiEmail = [
    {
      name: "EMAIL_COMMENT",
      addNoti: (comment: string) => this.addCommentToNewestPost(comment)
    },
    {
      name: "EMAIL_DISCUSSION",
      addNoti: (inbox: string) => this.addNewMessageToDiscussion(inbox)
    }
  ]

  get requestProps() {
    return {
      filterProperties: [
        { name: 'case_id', type: 'input' },
        { name: 'patient', type: 'input' }
      ],
      threeDotDropdownMenus: {
        customizedColumn: 'Customized Columns',
      },
      customizedColumns: [
        { name: 'Pin', default: true, tableDisplayName: 'Pin' },
        { name: 'Request #', default: true, tableDisplayName: 'Request #' },
        { name: 'Case #', default: true, tableDisplayName: 'Case #' },
        { name: 'Request', default: true, tableDisplayName: 'Request' },
        { name: 'Client Name', default: true, tableDisplayName: 'Client Name' },
        { name: 'Creator', default: true, tableDisplayName: 'Creator' },
        { name: 'Directed To', default: true, tableDisplayName: 'Directed To' },
        { name: 'Status', default: true, tableDisplayName: 'Status' },
        { name: 'Status Details', default: true, tableDisplayName: 'Status Details' },
        { name: 'Submitted User', default: false, tableDisplayName: 'Submitted User' },
        { name: 'Assignee', default: false, tableDisplayName: 'Assignee' },
        { name: 'Date', default: false, tableDisplayName: 'Date' },
        { name: 'Updated', default: false, tableDisplayName: 'Updated' },
        { name: 'Actions', default: true, tableDisplayName: 'Actions' }
      ]
    }
  }

  get requestLoc() {
    return {
      itemBoldUnread: this.genLoc("//tr[contains(@class,'not_field_read fw-bold')]"),
      requestNewID: (requestID: string) => this.genLoc(`//a[contains(.,'${requestID}')]/descendant::span[text()='${requestID}']`),
      linkcase: {
        bannerCreatedCaseSuccess: this.genLoc("//div[@class='case-confirm-banner']")
      },

      headingRequestPage: this.genLoc("//span[@class='line-height-normal']"),
      itemInRowRequest: (caseID: string) => this.genLoc(`//a/span[text()='${caseID}']`),
      detail: {
        caseConfirmID: this.genLoc("//div[contains(@class, 'cell-popover-hover-wrapper')]"),
        caseNeedToConfirm: this.genLoc("//span[@class='cl-green fw-bold']"),
        btnShare: this.genLoc("//button[@data-test-id='request-detail-btn-share']"),
        optionsMember: this.genLoc("//div[contains(@class,'autocomplete-option')]"),
        uploadZone: this.genLoc("//div[contains(@class,'upload-dropzone')]"),
        btnSubmitCloneRequest: this.genLoc("//button[@data-test-id='btn-modal-clone-request-submit']"),
        btnSubmitAssignee: this.genLoc("//button[@data-test-id='btn-modal-assignee-member-submit']"),
        btnCancelModalMessage: this.genLoc("//button[@data-test-id='btn-modal-respond-snapshot-cancel']"),
        btnSubmitMessage: this.genLoc("//button[@data-test-id='btn-modal-respond-snapshot-submit']"),
        btnSubmitShare: this.genLoc("//button[@data-test-id='btn-request-bulk-edit-action-detail-share-submit']"),
        businessFirstRecommend: this.genLoc("(//div[@class='recommend-items mb-3'])[2]/div[position()=1]/p"),
        btnNextPrepareRecord: this.genLoc("//button[@data-test-id='btn-modal-prepare-record-request-next']"),
        tagMemberShared: (member: string) => this.genLoc(`//div[contains(@class,'date-option') and contains(.,'${member}')]`),
        btnResend: this.genLoc("//button[@class='btn btn-resend-share']"),
        rowMemberShare: (member: string) => this.genLoc(`//div[@class='row align-items-center wp-box-share' and contains(.,'${member}')]`),
        btnBackToReq: this.genLoc("//a[contains(.,'Back to request')]"),
        listBoxTag: this.genLoc("//div[@class='list-request-tag']"),
        clickAddTag: this.genLoc("//div[@class='create active']"),
        iconTag: this.genLoc("//div[@class='icon-request-tag']"),
        boxTag: this.genLoc("//div[contains(@class,'box-request-tag-info')]/div[@class='box-contact-tag box-hashtag']"),
        btnDropdownEditBusiness: this.genLoc("//div[@class='list-info-name-pin pin-item']/div[@class='dropdown d-flex align-items-center']"),
        btnEdit: this.genLoc("//a[contains(@class,'open-modal-update-business')]"),
        inputSearchChangeBusiness: this.genLoc("//input[@name='business_provider_id' and @placeholder='Type or select a business']"),
        btnDelteMember: this.genLoc("//div[@class='btn-delete-share cursor-pointer']"),
        btnCofirmRemove: this.genLoc("//button[@class='swal2-confirm swal2-styled']"),
        inputSeachMember: this.genLoc("(//input[@name='emails'])[1]"),
        btnAssignee: this.genLoc("//div[contains(@class,'box-status-request')]/span[@class='cursor-pointer']"),
        inputSearchAssignee: this.genLoc("//input[@name='assignee_id' and @placeholder='Search...']"),
        headerDetail: this.genLoc("//div[@class='box-business-contact-wrapper box-page-detail-wrapper']"),
        titleIdNameRequest: this.genLoc("//div[@class='list-info-name-pin pin-item']"),
        fullnameAssignee: this.genLoc("//span[contains(@class,'assignee-full-name')]"),
        caseID: (caseID: string) => this.genLoc(`//a[contains(text(),'${caseID}')] | //span[contains(.,'${caseID}')]`),

        cartRequest: {
          listRequestTypeByHovering: this.genLoc("//div[@class='cart-item']"),
          tdInTable: (name: string) => this.genLoc(`//label[text()='${name}']`),
          iconShowListCart: this.genLoc("//*[@data-test-id='add-request-to-cart-icon']"),
          titleListCart: this.genLoc("//div[@class='request-action-title']"),
          itemsInListCart: this.genLoc("//div[@class='request-action-item']/span"),
          quickSubmitButton: (number: string) => this.genLoc(`//button[contains(text(),'Quick Submit')]/span[@class='tag-num-btn' and text()='${number}']`),
          listRequestsInFastCreate: this.genLoc("//div[@class='box-items box-apply-all box-select position-relative row-normal']"),
          deleteFirstCart: this.genLoc("(//div[@class='box-items box-apply-all box-select position-relative row-normal']/div[@class='btn-delete'])[1]"),
          listButtonDelete: this.genLoc("//div[@class='btn-delete']"),
          optionCartHoverCaseID: (option: string) => this.genLoc(`//span[@class='d-inline-block text-ellipsis' and text()='${option}']`),
          optionBusinessInCart: (business: string) => this.genLoc(`//div[contains(@class,'cart-request-item text-ellipsis') and text()='${business}']`)
        },

        cloneRequest: {
          optionArchive: (archiveType: string) => this.genLoc(`//div[@class='title-option' and text()='${archiveType}']`),
          inputBusiness: this.genLoc("//input[@name='business_provider_id']"),
          inputMember: this.genLoc("//input[@name='emails' and @placeholder='Select or type an email address']"),
          msgCloneSucess: this.genLoc("//p[text()='Cloned Request Successfully!']"),
          inputArchive: this.genLoc("//input[@name='is_archived']")
        },

        snapshot: {
          fileName: (file: string) => this.genLoc(`//p[text()='${file}']`),
          listPostMedicalbill: this.genLoc("//ul/label"),
          titleMedicalBillStar: this.genLoc("//li[contains(@class,'step-item')]/span"),
          btnCloseModal: this.genLoc("(//h3[contains(text(),'Prepare Records')]/parent::div)/child::button"),
          inputUploadFile: this.genLoc("//input[@id='attachments']"),
          btnClickToOpenMultiFile: this.genLoc("//span[text()='Click here']"),
          prevFile: this.genLoc("//div[contains(@class,'box-preview')]/div[@class='box-text']/p"),
          inputReduction: this.genLoc("//input[@id='input_reduction']"),
          inputBalance: this.genLoc("//input[@id='input_balance']"),
          inputReductionOffer: this.genLoc("//input[@id='input_reduction-offer']"),
          inputTotal: this.genLoc("//input[@id='input_total']"),
          balanceValueInMessage: this.genLoc("//span[@name='submit_medical_lien_balance']"),
          checkFileAffidatvit: this.genLoc("//input[@name='affidavit_record_id']"),
          boxSelectedFiles: this.genLoc("//div[contains(@class,'box-selected-records')]"),
          buttonTypeNew: this.genLoc("//span[contains(@class,'show-type-message')]")
        },

        notification: {
          btnOpenModalNoti: this.genLoc("//button[contains(@class,'btn-soft-primary')]"),
          btnToggleSettingNoti: this.genLoc("//button[@class='accordion-button after-none collapsed']"),
          inputNotiByName: (name: string) => this.genLoc(`//input[@name='${name}']`),
          btnTurnOffAll: this.genLoc("//input[@id='checkbox-slide-turn-off-all-false']/parent::div"),
          btnTurnOnAll: this.genLoc("//input[@id='checkbox-slide-turn-off-all-true']/parent::div")
        },

        medicalBill: {
          inputBalance: this.genLoc("//input[@name='total']")
        },

        share: {
          boxEnterEmail: this.genLoc("//div[contains(@class,'box-action-receiver-null')]"),
          inputEmail: this.genLoc("//input[@id='multi_select_emails']"),
          inputMessage: this.genLoc("//textarea[@id='text_area_personalized_message']"),
          listMembers: this.genLoc("//div[@class='modal-share-name']"),
          btnDeleteByMemberName: (memberName: string) => this.genLoc(`//p[text()='${memberName}']/ancestor::div[@class='row align-items-center wp-box-share']/descendant::div[@class='btn-delete-share cursor-pointer']`)
        },

        bulkEdit: {
          listCheckbox: this.genLoc("//input[contains(@id,'checkbox-undefined-undefined')]"),
          bulkAction: (action: string) => this.genLoc(`//span[text()="${action}"]/preceding-sibling::input`),
          listMailShare: this.genLoc("//span[text()='Email']")
        },

        posts: {
          btnSubmitComment: this.genLoc("//button[@class='submit-send-comment']"),
          inputComment: this.genLoc("//input[@name='content']"),
          msgCreateCmtSuccess: this.genLoc("//p[text()='Added New Successfully!']"),
          cmtInPost: this.genLoc("(//div[contains(@class,'shadow-body box-attachment-tour list-letters')])[1]/descendant::span[contains(@class,'text-content-comment')]")
        },

        discussion: {
          chatOnlyYou: (accountName: string) => this.genLoc(`//span[@class='title-conversation' and text()='${accountName} (You)']`),
          btnThreeDotsActionDiscussion: this.genLoc("//div[@class='dropdown ms-auto']"),
          btnThreeDotsReplyMessage: this.genLoc("//div[contains(@class,'icon-more-message')]"),
          btnDeleteMessage: this.genLoc("//span[@class='dropdown-item btn-message-discussion btn-remove-message-discussion cursor-pointer']"),
          btnReplyMessage: this.genLoc("//div[@class='dropdown-menu dropdown-menu-end box-dropdown-btn show']"),
          contentReply: this.genLoc("//p[@class='content-reply']"),
          labelWasReply: (message: string) => this.genLoc(`//div[text()='${message}']/ancestor::div[@class='item-message']/descendant::span[@class='reply-owner']`),
          btnCreateDiscussion: this.genLoc("(//span[@data-user-tracking='BTN_SHOW_CREATE_REQUEST_DISCUSSION_MODAL'])[1]"),
          inputTitle: this.genLoc("//input[@name='title']"),
          inputMessage: this.genLoc("//input[@placeholder='Message']"),
          titleInDiscussion: (title: string) => this.genLoc(`//span[text()='${title}']/ancestor::div[@class='request-discussion-wrapper']`),
          titleDiscussion: (title: string) => this.genLoc(`//span[text()='${title}']/ancestor::div[@class='request-discussion-wrapper']`),
          titleDiscussionToClick: (title: string) => this.genLoc(`//span[text()='${title}']/ancestor::div[@class='request-discussion-wrapper']/descendant::span[text()='${title}']`),
          messageInDiscussion: (message: string) => this.genLoc(`//div[text()='${message}']`),
          newestDiscussion: this.genLoc("(//div[contains(@class,'item-content')])[1]"),
          inputMsgDis: this.genLoc("//input[@placeholder='Message']"),
          btnSendMsg: this.genLoc("//button[@class='btn-send-message btn-message']"),
          msgFirstDis: this.genLoc("(//textarea[@name='content'])[2]")
        },
      },

      create: {
        optionMember: (member: string) => this.genLoc(`//span[text()='${member}']/ancestor::span[contains(@class,'date-option')]`),
        btnCloseAction: this.genLoc("//span[@class='closed-action']"),
        btnAddNewOption: (option: string) => this.genLoc(`//button[contains(.,'${option}')]`),
        closeModalMessage: this.genLoc("(//span[@class='closed-action'])[4]"),
        textEditorCreateFast: this.genLoc("//div[@class='jodit-wysiwyg']"),
        arrowIcon: this.genLoc("//span[@class='arrow-icon']"),
        inputDOIInStep2: this.genLoc("//input[@id='date_time_rows.1.date_of_injury']"),
        itemRow2: this.genLoc("(//div[@class='apply-all item item-steps-2 position-relative'])[2]"),
        tableRowUI: this.genLoc("//div[@class='add-rows-request']/ancestor::div[@class='mb-3']"),
        dataPreview: (type: string) => this.genLoc(`(//label[text()='${type}']/following::div[@class='note'])[1]`),
        boxTextBusiness: (business: string) => this.genLoc(`//div[@class='box-text box-text-business' and contains(.,'${business}')]`),
        inputByPlaceholder: (placeholder: string) => this.genLoc(`//input[@placeholder='${placeholder}']`),
        headerInCreateStep: (headerName: string) => this.genLoc(`//div[contains(@class,'title-header')]/descendant::span[text()='${headerName}']`),
        dropdownMemberShare: (member: string) => this.genLoc(`//div[text()='${member}']/parent::div[contains(@class,'box-text box-text-business')]`),
        dropdownMemberShareNew: (member: string) => this.genLoc(`//strong[contains(text(),'${member}')]/ancestor::div[@class='dropdown-menu-wrapper']`),
        btnCreateAndShare: this.genLoc("//a[text()='Create & Share']"),
        caseIDRequest: this.genLoc("//div[@class='list-info-name-pin pin-item']"),
        boxCreateMultiRequests: this.genLoc("//div[@class='box-items box-apply-all box-select position-relative row-normal']"),
        itemStep: (step: number) => this.genLoc(`//div[contains(@class,'item-steps-${step}')]`),
        inputCheckAll: (name: string) => this.genLoc(`//input[@name='check-box-apply-all-${name}']`),
        viewRequest: this.genLoc("//a[@class='view-request-success']"),
        overviewCreateFast: this.genLoc("//div[@class='new-request request-multi send-new-request-multi row justify-content-center']")
      },
      btnTakeActions: this.genLoc("(//button[@class='btn d-flex align-items-center ga-8 btn-soft-primary pr-8px'])[1]"),
      mainContainer: this.genLoc(`//div[@id='root']`),
      heading: this.genLoc(`//div[@id='root']//span[contains(text(), 'Requests')]`),
      inputSearch: this.genLoc(`//div[contains(@class, 'personal-search')]//input[@placeholder='Search...']`),
      tableHeadingColumn: (nameHeading: string) => this.genLoc(`//th[contains(@class, 'title-table')]//span[contains(normalize-space(),'${nameHeading}')]`),
      pinIcon: (caseNumber: string) => this.genLoc(`//a[normalize-space()=${caseNumber}]//ancestor::tr//a[@data-tooltip-content='Click here to pin!']`),
      pinnedIcon: (caseNumber: string) => this.genLoc(`//a[normalize-space()=${caseNumber}]//ancestor::tr//a[@data-tooltip-content='Click here to unpin!']`),
      firstCaseNumber: (caseNumber: string) => this.genLoc(`//div[contains(@class, 'card pin-card')]//a[@href='/requests/${caseNumber}']`),
      btnNewRequest: this.genLoc(`//div[@id='root']//button[contains(text(), 'New Request')]`),
      btnFilter: this.genLoc(`//div[@id='root']//button[contains(text(), 'Filter')]`),
      btnBulkEdit: this.genLoc(`//div[@id='root']//button[contains(text(), 'Bulk Edit')]`),
      inputShow: this.genLoc(`//input[@class='form-control show-record-number ']`),
      caseAlreadyExist: (caseID: string) => this.genLoc(`//td/a[text()='${caseID}'] | //span[text()='${caseID}']`),
      buttonRepond: this.genLoc("//a[text()='Respond']"),
      caseIDDetail: this.genLoc("//span[contains(@class,'business-contact-name')]"),
      headerModalNewPost: this.genLoc("//h3[text()='New Post: Minimize Previous Post?']"),
      buttonLeaveIt: this.genLoc("//button[text()='Leave it']"),
      messageRepondSucces: this.genLoc("//p[text()='Added New Successfully!']"),
      buttonSubmitTextEditor: this.genLoc("(//div[@class='box-btn-reset-apply-filter']/button[text()='Submit'])[2]"),
      thumbImagePosted: this.genLoc("//div[@class='letter-thumb-image']"),
      detailPostedAttachment: this.genLoc(".tab-detail-attachment"),
      siteCreateNewRequest: this.genLoc("//div[@class='request-index']"),
      btnNextStep: this.genLoc("//a[text()='Next']"),
      actionLetterOfProtection: this.genLoc("//p[text()='Letter of Protection']"),
      listPatientSuggested: this.genLoc("//div[@class='steps step-2']/descendant::div[contains(@class, 'item action-items')][1]"),
      listBusinessSuggested: this.genLoc("//div[@class='steps step-3']/descendant::div[contains(@class, 'item action-items')][1]"),
      modalChoosePatient: this.genLoc("//span[text()='Selection of patients']/parent::div"),
      modalChooseBusiness: this.genLoc("//span[text()='Selection of businesses']/parent::div"),
      textEditorCreateCaseArea: this.genLoc("(//div[@class='jodit-react-container']/descendant::div[@class='jodit-wysiwyg'])[2]"),
      btnItalicEditorCreate: this.genLoc("(//span[@data-ref='italic']/button)[2]"),
      btnBoldEditorCreate: this.genLoc("(//span[@data-ref='bold']/button[@class='jodit-toolbar-button__button'])[2]"),
      btnListNumberTypeCreate: this.genLoc("(//span[@role='listitem' and @data-ref='ol']/button)[2]"),
      btnListDotTypeCreate: this.genLoc("(//span[@role='listitem' and @data-ref='ul']/button)[2]"),
      btnCreateOnly: this.genLoc("//a[text()='Create Only']"),
    };
  }

  async open(): Promise<void> {
    await this.page.goto("requests");
  }

  async gotoCreateRequest(type: string): Promise<void> {
    await this.page.goto(`requests/create?switch=${type}`);
  }

  // Respond to a request with a message
  async respondToRequest(message: string): Promise<void> {
    const textEditorBody = this.requestLoc.textEditorCreateCaseArea;
    await this.requestLoc.buttonRepond.click();
    await textEditorBody.waitFor({ state: 'visible' });
    await textEditorBody.type(message, { delay: 20 });
    await this.requestLoc.detail.btnSubmitMessage.click();
    await this.requestLoc.messageRepondSucces.waitFor({ state: 'visible' });
    await textEditorBody.waitFor({ state: 'hidden' });
  }

  // Edit business and share request with another member
  async editBusinessAndShare(business: string, memberToAdd: string, nameMemberAdd: string): Promise<void> {
    await this.requestLoc.detail.btnDropdownEditBusiness.waitFor({ state: 'visible' });
    await this.waitForSecond(1);
    await this.requestLoc.detail.btnDropdownEditBusiness.click();
    await this.requestLoc.detail.btnEdit.click();
    await assertionHelper.verifyModalVisible(this.dashboardLoc.modal.headerModal("Edit Business"));
    await this.requestLoc.detail.inputSearchChangeBusiness.fill(business);
    await this.requestLoc.create.boxTextBusiness(business).click();
    await this.dashboardLoc.buttonByText("Update").first().click();
    await assertionHelper.verifyModalVisible(this.dashboardLoc.notificationUpdateSuccess);
    await this.dashboardLoc.buttonByText("Share").click();
    await assertionHelper.verifyModalVisible(this.dashboardLoc.modal.headerModal("Share with others"));
    await this.requestLoc.detail.btnDelteMember.click();
    await this.requestLoc.detail.btnCofirmRemove.click();
    await assertionHelper.verifyModalVisible(this.dashboardLoc.notificationUpdateSuccess);
    await this.requestLoc.detail.inputSeachMember.fill(memberToAdd);
    await this.waitForSecond(2);
    await this.requestLoc.create.dropdownMemberShare(nameMemberAdd).click();
    await this.dashboardLoc.buttonByText("Done").first().click();
    await assertionHelper.verifyModalVisible(this.dashboardLoc.notificationUpdateSuccess);
  }

  // Fill data in create request form
  async fillDataCreateRequest(inputPlaceHolder: string, preview: string, data: string): Promise<any> {
    await this.requestLoc.create.inputByPlaceholder(inputPlaceHolder).first().fill(data);
    const infoPatient = await this.requestLoc.create.boxTextBusiness(data).innerText();
    await this.waitForSecond(2);
    await this.requestLoc.create.boxTextBusiness(data).click({ force: true });
    const infoPatientPreview = await this.requestLoc.create.dataPreview(preview).innerText();
    const address = infoPatientPreview.split('\n')[0].replace('Address:', '').trim();
    return { infoPatient, address }
  }

  // Render a list in the text editor
  async rendListTextEditor(text: string): Promise<void> {
    const textEditorBody = this.requestLoc.textEditorCreateCaseArea;
    for (let i = 0; i < 3; i++) {
      await textEditorBody.type(text, { delay: 20 });
      await textEditorBody.press('Enter');
    }
    await textEditorBody.press('Enter');
  }

  //Open notification and the latest post, then run an optional callback
  async verifyAndOpenNotification(gotoDetail: boolean): Promise<void> {
    await this.dashboardLoc.notiCard.waitFor({ state: 'visible' });
    await this.dashboardLoc.notiCard.click();
    if (gotoDetail) {
      await this.requestLoc.thumbImagePosted.first().waitFor({ state: 'visible' });
      await this.requestLoc.thumbImagePosted.first().click();
    }
    await this.waitForSecond(2);
  }

  // Open the latest post and wait for it to load
  async verifyPostSnapshot(): Promise<void> {
    await this.requestLoc.thumbImagePosted.first().waitFor({ state: 'visible' });
    await this.requestLoc.thumbImagePosted.first().click();
    await this.waitForSecond(2);
  }

  //Go back to the request list if the button is visible
  async backToRequestList(): Promise<void> {
    if (await this.requestLoc.detail.btnBackToReq.isVisible()) {
      await this.requestLoc.detail.btnBackToReq.click();
    }
  }

  //Verify if a request is shared with a member (in a new browser context)
  async verifyShareRequest(browser: Browser, conf: any, memberKey: string, shouldBeVisible: boolean): Promise<void> {
    const context = await browser.newContext();
    const page = await context.newPage();
    const loginPage = new LoginPage(page);
    const shareWithMePage = new SharedRequestPage(page);
    try {
      await loginPage.open();
      await loginPage.login(conf.data.user[memberKey], conf.data.password);
      await shareWithMePage.open();
      await shareWithMePage.search(conf.data.case);
      await shareWithMePage.waitForSecond(2);
      const isVisible = await shareWithMePage.dashboardLoc.table.noResult.isVisible();
      if (isVisible !== shouldBeVisible) {
        throw new Error(`Unexpected visibility for ${memberKey}: expected ${shouldBeVisible}, got ${isVisible}`);
      }
    } finally {
      await context.close();
    }
  }

  // Login as another user in a new browser context and return the new RequestPage
  async loginInAnotherBrowser(browser: Browser, username: string, password: string): Promise<{ context: BrowserContext; page: Page; requestPage: RequestPage }> {
    const context = await browser.newContext();
    const page = await context.newPage();
    const loginPage = new LoginPage(page);
    await loginPage.open();
    await loginPage.login(username, password);
    await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
    return { context, page, requestPage: new RequestPage(page) };
  }

  async addNewMessageToDiscussion(message: string): Promise<void> {
    await this.dashboardLoc.discussion.newestDiscussion.click();
    await this.dashboardLoc.discussion.inputMessage.waitFor({ state: 'visible' })
    await this.dashboardLoc.discussion.inputMessage.fill(message);
    await this.dashboardLoc.discussion.btnSendMsg.click();
    await this.waitForSecond(2);
  }

  async addTags(count: number): Promise<void> {
    await this.requestLoc.detail.boxTag.click();
    for (let i = 0; i < count; i++) {
      await this.dashboardLoc.tag.inputTag.fill(`test${i}`);
      await this.dashboardLoc.tag.inputTag.press("Enter");
    }
    await this.dashboardLoc.tag.btnSaveTag.click();
  }

  async clearAllTags(): Promise<void> {
    await this.dashboardLoc.tag.listTagDetail.first().click();
    for (let i = 8; i > 0; i--) {
      await this.dashboardLoc.tag.listRemoveTag.nth(i).click();
    }
    await this.dashboardLoc.tag.listRemoveTag.first().click();
    await this.dashboardLoc.tag.btnSaveTag.click();
    await this.dashboardLoc.btnClosePopupNotification.click();
  }

  async assignToUser(username: string): Promise<void> {
    await this.requestLoc.detail.inputSearchAssignee.fill(username);
    await this.requestLoc.create.boxTextBusiness(username).click();
    await this.requestLoc.detail.btnSubmitAssignee.click();
  }

  async openCloneRequestModal(): Promise<void> {
    await this.dashboardLoc.buttonByText("Activity").click();
    await this.dashboardLoc.buttonByText("Clone Request").first().click();
  }

  async fillCloneRequestForm(business: string, member: string, archiveOption?: string): Promise<void> {
    await this.requestLoc.detail.cloneRequest.inputBusiness.first().fill(business);
    await this.requestLoc.create.boxTextBusiness(business).click();
    await this.requestLoc.detail.cloneRequest.inputMember.fill(member);
    await this.requestLoc.create.dropdownMemberShare(member).click();
    await this.dashboardLoc.modal.headerModal("Clone Request").click();
    // await this.requestLoc.detail.cloneRequest.inputMember.fill(member);
    if (archiveOption) {
      await this.requestLoc.detail.cloneRequest.inputArchive.click();
      await this.requestLoc.detail.cloneRequest.inputArchive.type(archiveOption, { delay: 100 });
      await this.requestLoc.detail.cloneRequest.optionArchive(archiveOption).click();
    }
  }

  async submitCloneRequest(): Promise<void> {
    await this.requestLoc.detail.btnSubmitCloneRequest.click();
  }

  async toggleNotification(notiType: any): Promise<void> {
    await this.requestLoc.detail.notification.btnOpenModalNoti.nth(1).click();
    await this.requestLoc.detail.notification.btnToggleSettingNoti.first().click();
    await this.waitForSecond(2);
    await this.requestLoc.detail.notification.inputNotiByName(notiType.name).click({ force: true });
    await this.waitForSecond(2);
    await this.dashboardLoc.buttonByText("Close").nth(2).click();
    await this.open();
  }

  async triggerNotificationFromAnotherUser(browser: Browser, username: string, password: string, caseID: string, notiType: any, uniqueMsg: string): Promise<void> {
    const { context, requestPage: requestPageB } = await this.loginInAnotherBrowser(browser, username, password);
    await requestPageB.open();
    await requestPageB.getDetailCase(caseID);
    await requestPageB.notiApp[notiType.index].addNoti(uniqueMsg);
    await requestPageB.waitForSecond(1);
    await context.close();
  }

  async findMail(request: { get: (arg0: string) => any; }): Promise<any> {
    let mailUrl = process.env.MAIL_SERVER || 'http://69.28.90.112:8025/'
    // Call API to get mails
    const rawResponse = await request.get(`${mailUrl}/api/v1/messages`);
    expect(rawResponse.status()).toEqual(200);
    const response = await rawResponse.json();
    const messages = await response.messages;
    return messages[0];
  }

  async shareRequestToEmail(requestPage: RequestPage, email: string, message?: string) {
    await expect(requestPage.dashboardLoc.buttonByText("Share")).toBeVisible();
    await requestPage.waitForSecond(1);
    await requestPage.dashboardLoc.buttonByText("Share").click();
    await requestPage.requestLoc.detail.share.inputEmail.first().fill(email);
    await expect(requestPage.requestLoc.create.dropdownMemberShare(email)).toBeVisible();
    await requestPage.requestLoc.create.dropdownMemberShare(email).click();
    if (message) {
      await requestPage.requestLoc.detail.share.inputMessage.fill(message);
    }
    await requestPage.dashboardLoc.buttonByText("Done").first().click();
  }

  async openLinkAndCompletePasscode(requestPage: RequestPage, requestCtx: any, buttonLocator: Locator): Promise<RequestPage> {
    const buttonPage = await buttonLocator.elementHandle().then(el => el?.ownerFrame()).then(frame => frame?.page()) || buttonLocator.page();
    const [newPage] = await Promise.all([
      buttonPage.context().waitForEvent('page'),
      buttonLocator.click()
    ]);

    const newTabPage = new RequestPage(newPage);
    await newTabPage.dashboardLoc.buttonByText("Next").click();
    await newTabPage.waitForSecond(3);

    const foundMail = await newTabPage.findMail(requestCtx);
    expect(foundMail).toBeTruthy();

    const verificationCode = extractVerificationCode(foundMail.Subject) || '';
    await newTabPage.dashboardLoc.inputCode.fill(verificationCode);
    await newTabPage.dashboardLoc.buttonByText("Next").click();

    return newTabPage;
  }

  async bulkShareFirstNRequests(requestPage: RequestPage, n: number, email: string): Promise<void> {
    await requestPage.dashboardLoc.buttonByText("Bulk Edit").click();
    await requestPage.waitForSecond(3);

    for (let i = 0; i < n; i++) {
      await requestPage.requestLoc.detail.bulkEdit.listCheckbox.nth(i).check();
      await requestPage.requestLoc.detail.bulkEdit.listCheckbox.nth(i).isChecked();
    }
    await requestPage.waitForSecond(1);
    await requestPage.dashboardLoc.buttonByText("Next").click();
    await requestPage.requestLoc.detail.bulkEdit.bulkAction("Share/Remove Shared").check();
    await requestPage.dashboardLoc.buttonByText("Next").click();
    await requestPage.requestLoc.detail.bulkEdit.bulkAction("Share").check();

    for (let i = 0; i < n; i++) {
      await requestPage.requestLoc.detail.bulkEdit.listMailShare.first().click();
      await expect(requestPage.dashboardLoc.modal.headerModal("Share")).toBeVisible();
      await requestPage.requestLoc.detail.share.inputEmail.first().fill(email);
      await expect(requestPage.requestLoc.create.dropdownMemberShare(email)).toBeVisible();
      await requestPage.requestLoc.create.dropdownMemberShare(email).click();
      await requestPage.dashboardLoc.modal.headerModal("Share").click();;
      await requestPage.requestLoc.detail.btnSubmitShare.click();
      await expect(requestPage.dashboardLoc.modal.headerModal("Share")).not.toBeVisible();
    }

    await requestPage.dashboardLoc.buttonByText("Next").click();
    await requestPage.dashboardLoc.buttonByText("Confirmation").click();
  }

  async shareToMultipleEmails(requestPage: RequestPage, emails: string[]): Promise<void> {
    await requestPage.dashboardLoc.buttonByText("Share").click({ force: true });
    await requestPage.dashboardLoc.modal.headerModal("Share with others").waitFor({ state: 'visible' });

    for (const email of emails) {
      await requestPage.requestLoc.detail.share.inputEmail.first().type(email, { delay: 150 });
      await expect(requestPage.requestLoc.create.dropdownMemberShare(email)).toBeVisible();
      await requestPage.requestLoc.create.dropdownMemberShare(email).click();
    }
    await requestPage.dashboardLoc.buttonByText("Done").first().click();
  }

  async handleMissingInfoPopup(): Promise<void> {
    const popupMissingInfo = this.dashboardLoc.modal.headerModal("Missing Information");
    await this.page.addLocatorHandler(popupMissingInfo, async () => {
      await this.waitForSecond(1);
      await this.dashboardLoc.buttonByText("Continue").click();
    });
  };

  async initiateRequestCreation(patientName: string): Promise<void> {
    await this.gotoCreateRequest("multi");
    await expect(this.dashboardLoc.buttonByText("Switch to Step-by-Step")).toBeVisible();

    await this.requestLoc.create.itemStep(1).first().click();
    await this.dashboardLoc.common.pText("Prescription").first().click();

    await this.requestLoc.create.itemStep(2).first().click();
    await this.fillDataCreateRequest("Type or select a name", "Name", patientName);

    await this.requestLoc.create.itemStep(4).first().click();
  };

  async submitAndVerifyRequest(screenshotName: string): Promise<void> {
    await this.dashboardLoc.buttonByText("Create").first().click();
    await expect(this.requestLoc.thumbImagePosted).toBeVisible({ timeout: 50_000 });
    await this.requestLoc.thumbImagePosted.first().click();
    await this.waitForSecond(8);
    await verifyScreenshot(screenshotName, this.requestLoc.detailPostedAttachment, [], 0.02);
  };

  async handlePopupMinimize(): Promise<void> {
    const popupNewPost = this.dashboardLoc.modal.headerModal("New Post: Minimize Previous Post?");
    await this.page.addLocatorHandler(popupNewPost, async () => {
      await this.dashboardLoc.buttonByText("Leave it").click();
    })
  };

  async getDetailRequest(caseID: string): Promise<void> {
    await this.dashboardLoc.search.inputSearch.fill(caseID);
    await this.waitForSecond(2);
    await this.requestLoc.itemInRowRequest(caseID).waitFor({ state: 'visible' });
    await this.requestLoc.itemInRowRequest(caseID).click({ force: true });
  };

  async createSimpleAndShareRequest(emailRecive: string, businessName: string, clientName: string): Promise<void> {
    await this.requestLoc.create.itemStep(1).first().click();
    await this.dashboardLoc.common.pText("Medical Bill").first().click();

    //Choose Patient
    await this.requestLoc.create.itemStep(2).first().click();
    await this.requestLoc.create.inputByPlaceholder("Type or select a name").first().fill(clientName);
    await this.waitForSecond(2);
    await this.requestLoc.create.boxTextBusiness(clientName).click({ force: true });

    //Choose Business
    await this.requestLoc.create.itemStep(3).first().click();
    await this.requestLoc.create.inputByPlaceholder("Type or select a business").first().fill(businessName);
    await this.waitForSecond(2);
    await this.requestLoc.create.boxTextBusiness(businessName).click({ force: true });

    await this.requestLoc.create.itemStep(5).first().click();
    await this.requestLoc.create.inputByPlaceholder("Type or select an email address").first().type(emailRecive, { delay: 200 });
    await this.requestLoc.create.optionMember(emailRecive).click();

    await this.requestLoc.create.btnCloseAction.last().click();
    await this.dashboardLoc.buttonByText("Create").first().click();

    await this.dashboardLoc.modal.headerModal("Missing Information").waitFor({ state: 'visible' });
    await this.dashboardLoc.buttonByText("Continue").click();
  };
}


