import { Browser, BrowserContext, expect, Locator, Page } from "@playwright/test";
import { DashboardPage } from "../dashboard.page";
import { createRequestFastSubmission, createRequestFastSubmissionMulti, createRequestStepByStep, createSingleRequestStep1, createSingleRequestStep3, createSingleRequestStep4, createSingleRequestStep5, detailRequestBody, detailRequestEditShare, detailRequestEditShareProduction, detailRequestHeader, detailRequestHeaderProduction, emptyState, headingAndCreateButton, tipsBlock, createFastSubmissionStep1, createFastSubmissionStep2, createFastSubmissionStep3, createFastSubmissionStep4, createFastSubmissionStep5, req054DetailBeforeMove, req054ModalMove, req054DetailAfterMove } from "./request.snapshot";
import { reviewCaseDoiPending, reviewSenderDefinedDoi, reviewUnspecifiedDoi, reviewUserDefinedDoiNoSenderDoi, reviewUserDefinedDoiWithSenderDoi, successNewCaseDoiPending, successNewCaseUserDoi, successNewClientCaseSenderDoi, createNewPatientForm, reviewNewClientUserDefinedDoiWithSenderDoi, successNewClientUserDefinedDoiWithSenderDoi, reviewNewClientUserDefinedDoiNoSenderDoi, successNewClientUserDefinedDoiNoSenderDoi, reviewNewClientSenderDefinedDoi, successNewClientSenderDefinedDoi, reviewNewClientUnspecifiedDoiWithSenderDoi, successNewClientUnspecifiedDoiWithSenderDoi, reviewNewClientUnspecifiedDoiNoSenderDoi, successNewClientUnspecifiedDoiNoSenderDoi, reviewLinkExistingCaseNoDoiChange, successVerifiedLinkedToCase, reviewMaintainExistingCaseAssociation, reviewMaintainExistingCaseUnspecifiedDoi, successLinkedToExistingCaseDoiPending, reviewUpdateExistingCaseSenderDefinedDoi, successExistingCaseUpdatedSenderDoi, reviewUpdateExistingCaseUserDefinedDoi, successExistingCaseUpdatedUserDoi, reviewMaintainExistingCaseAssociationNoSenderDoi, reviewUpdateExistingCaseUserDefinedDoiNoSenderDoi, successLinkedToExistingCaseUserDoi, reviewMaintainExistingCaseUnspecifiedDoiNoSenderDoi, successLinkedToExistingCaseNoChanges, reviewExistingRecordFound, reviewDuplicateFound } from "./linkcaseoff.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 linkCaseOffSnapshot() {
    return {
      // Full Match - Review & Success snapshots
      reviewLinkExistingCaseNoDoiChange,
      successVerifiedLinkedToCase,
      // Existing Client - Review snapshots
      reviewSenderDefinedDoi,
      reviewUserDefinedDoiWithSenderDoi,
      reviewUserDefinedDoiNoSenderDoi,
      reviewCaseDoiPending,
      reviewUnspecifiedDoi,
      // Existing Client - Success snapshots
      successNewClientCaseSenderDoi,
      successNewCaseUserDoi,
      successNewCaseDoiPending,
      // New Client - Common
      createNewPatientForm,
      // New Client - Review snapshots
      reviewNewClientUserDefinedDoiWithSenderDoi,
      reviewNewClientUserDefinedDoiNoSenderDoi,
      reviewNewClientSenderDefinedDoi,
      reviewNewClientUnspecifiedDoiWithSenderDoi,
      reviewNewClientUnspecifiedDoiNoSenderDoi,
      // New Client - Success snapshots
      successNewClientUserDefinedDoiWithSenderDoi,
      successNewClientUserDefinedDoiNoSenderDoi,
      successNewClientSenderDefinedDoi,
      successNewClientUnspecifiedDoiWithSenderDoi,
      successNewClientUnspecifiedDoiNoSenderDoi,
      // Existing Client - Existing DOI snapshots
      reviewMaintainExistingCaseAssociation,
      reviewMaintainExistingCaseUnspecifiedDoi,
      successLinkedToExistingCaseDoiPending,
      reviewUpdateExistingCaseSenderDefinedDoi,
      successExistingCaseUpdatedSenderDoi,
      reviewUpdateExistingCaseUserDefinedDoi,
      successExistingCaseUpdatedUserDoi,
      reviewMaintainExistingCaseAssociationNoSenderDoi,
      reviewUpdateExistingCaseUserDefinedDoiNoSenderDoi,
      successLinkedToExistingCaseUserDoi,
      reviewMaintainExistingCaseUnspecifiedDoiNoSenderDoi,
      successLinkedToExistingCaseNoChanges,
      reviewExistingRecordFound,
      reviewDuplicateFound
    }
  }

  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,
      createSingleRequestStep1: createSingleRequestStep1,
      createSingleRequestStep5: createSingleRequestStep5,
      createSingleRequestStep3: createSingleRequestStep3,
      createSingleRequestStep4: createSingleRequestStep4,
      createFastSubmissionStep1: createFastSubmissionStep1,
      createFastSubmissionStep2: createFastSubmissionStep2,
      createFastSubmissionStep5: createFastSubmissionStep5,
      createFastSubmissionStep3: createFastSubmissionStep3,
      createFastSubmissionStep4: createFastSubmissionStep4,
      req054DetailBeforeMove: req054DetailBeforeMove,
      req054ModalMove: req054ModalMove,
      req054DetailAfterMove: req054DetailAfterMove
    };
  }

  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: {
        rowModalCompare: (rowName: string, index: number) => this.genLoc(`//td[@class='table-compare__td table-compare__td--label' and text()='${rowName}']/following::td[${index}]`),
        btnTickConfirmEdit: this.genLoc("//*[local-name()='svg' and @class='cursor-pointer mt-2']"),
        btnEditInModalCompare: (index: number) => this.genLoc(`(//*[local-name()='svg' and @class='ml-8 cursor-pointer icon'])[${index}]`),
        boxDOIExisting: (doi: string) => this.genLoc(`//span[contains(text(),'${doi}')]/ancestor::div[contains(@class,'item action-items')]`),
        boxClientExisting: (clientName: string) => this.genLoc(`//span[text()='${clientName}']/preceding::h2[text()='Manual Case Association']/following::div[@class='swiper-slide swiper-slide-active']`),
        rowInTableCompare: (index: number) => this.genLoc(`//td[@class='table-compare__td table-compare__td--label' and text()='DOI']/following::td[${index}]`),
        btnCopyInModalCompare: this.genLoc(`//*[local-name()='svg' and @data-tooltip-content='Copy']`),
        wordBreakReview: this.genLoc("//span[contains(@class,'word-break')]"),
        btnAddNewPatientRecord: this.genLoc("//button[@class='btn btn-filter btn-size-large']"),
        doiLinkBlue: this.genLoc("//span[@class='link-blue-2 fw-bold']"),
        boxSuggestDOI: (doi: string) => this.genLoc(`//div[@class='recommend-items-v2 v2']/descendant::span[contains(text(),'${doi}')]`),
        boxSuggestClient: (clientName: string) => this.genLoc(`//div[contains(@class,'item action-items')]/descendant::span[text()='${clientName}']`),
        boxInformationCase: (text: string) => this.genLoc(`//span[@class='box-infomation-case-item' and contains(.,'${text}')]`),
        informationsInModal: (text: string) => this.genLoc(`//div[@class='modal-body p-0 w-full modal-organize-now']/descendant::span[text()='${text}']`),
        bannerAssignToCase: this.genLoc("//div[@class='box-request-organized']"),
        bannerRequestRelevant: this.genLoc("//div[@class='box-is-this-relevant mb-3']"),
        bannerRequestLinkedToCase: this.genLoc("//div[@class='box-request-link-case mb-3']"),
        svgBannerRequestLinkedToCase: this.genLoc("//div[@class='box-request-link-case mb-3']//span[@class='svg']"),
        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: {
        iconActionsThumb: this.genLoc("//li[@class='menu-item-letter']"),
        iconDownloadThumb: this.genLoc("//li[@class='menu-item-letter']/a[contains(@class,'icon-letter-download')]"),
        btnMenuActions: this.genLoc("//div[contains(@class,'btn-action-archive-clone-move')]"),
        caseIDInDetail: this.genLoc("(//a[contains(@href,'/cases/')])[2]"),
        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')]"),
        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[contains(@class,'recommend-items')])[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')]"),
        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]"),
          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[contains(@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[@id='autocomplete_archive_original']")
        },

        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']"),
          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']"),
          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")
        },

        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']")
        },

      },

      create: {
        btnCloseShareInStep3: this.genLoc("//div[@class='steps step-5 position-absolute step-width-default']/descendant::span[@class='closed-action']"),
        alertBoxMessageStep2: this.genLoc("//div[@class='alert-box-message']"),
        optionMember: (member: string) => this.genLoc(`//span[text()='${member}']/ancestor::span[contains(@class,'date-option')]`),
        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[contains(@class,'arrow-icon')]"),
        inputDOIInStep2: this.genLoc("//input[@id='date_time_rows.1.date_of_injury']"),
        itemRow3: this.genLoc("(//div[@class='apply-all item item-steps-3 position-relative'])[2]"),
        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}']`),
        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]"),
      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//div[@data-tooltip-content='Click here to pin!']`),
      pinnedIcon: (caseNumber: string) => this.genLoc(`//a[normalize-space()=${caseNumber}]//ancestor::tr//div[@data-tooltip-content='Click here to unpin!']`),
      firstCaseNumber: (caseNumber: string) => this.genLoc(`//div[contains(@class, 'card pin-card')]//a[@href='/requests/${caseNumber}']`),
      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!']"),
      thumbImagePosted: this.genLoc("//div[@class='letter-thumb-image']"),
      detailPostedAttachment: this.genLoc(".tab-detail-attachment"),
      btnNextStep: this.genLoc("//a[text()='Next']"),
      actionLetterOfProtection: this.genLoc("//p[text()='Letter of Protection']"),
      listPatientSuggested: this.genLoc("//div[@class='steps step-3']/descendant::div[contains(@class, 'item action-items')][1]"),
      listBusinessSuggested: this.genLoc("//div[@class='steps step-2']/descendant::div[contains(@class, 'item action-items')][1]"),
      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']"),

      // Additional locators from ReqPage
      msgNoCaseFound: this.genLoc(`//div[contains(text(),'No matching results found. Try again.') or contains(text(), 'Create a new request.')]`),
      pageTitle: this.genLoc(`//div[@id='root']//span[contains(text(), 'Requests')]`),
      nameResult: (caseName: number) => this.genLoc(`//table[contains(@class, 'table-business-client')]//a[contains(@class, 'cl-gray') and contains(text(), "${caseName}")]`),
      entriesDropdown: this.genLoc(`//input[@name="per_page"]`),
      pagingSummary: this.genLoc(`//p[@class="m-0 text-muted f-14 cl-gray info"]`),
      btnThreedot: this.genLoc(`//div[@class="cursor-pointer"]`),
      customizedColumnMenu: this.genLoc(`//span[contains(@class, 'dropdown-item') and normalize-space()='Customized Columns']`),
      modalCustomizedColumn: this.genLoc(`//div[contains(@class, 'modal-content') and .//h3[contains(text(),'Customized Columns')]]`),
      iconCloseModalCustomizedColumn: this.genLoc(`//div[contains(@class, 'modal-content')]//button[contains(@class, 'btn-close')]`),
      checkboxColumn: (columnLabel: string) =>
        this.genLoc(`//label[contains(., '${columnLabel}')]/preceding-sibling::input[@type='checkbox']`),
      btnApplyCustomizedColumn: this.genLoc(`//button[contains(text(),'Apply')]`),
      viewTips: this.genLoc(`//div[@data-tooltip-content='View Tips']`),
      closeTips: this.genLoc(`//a[@data-tooltip-content='Close Tips']`),
    };
  }

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

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

  // Methods from ReqPage
  async fillReq(reqinfor: string): Promise<void> {
    await this.requestLoc.inputSearch.fill(reqinfor);
    await this.requestLoc.inputSearch.press('Enter');
  }

  async selectEntriesPerPage(count: number): Promise<void> {
    await this.requestLoc.entriesDropdown.fill(`${count}`);
    await this.requestLoc.entriesDropdown.press('Enter');
  }

  // 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 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.page.waitForResponse(
      response => response.url().includes('/api/v1/members?s=') && response.status() === 200
    );
    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();
    await expect(requestPage.dashboardLoc.buttonByText("Done")).toBeVisible();
  }

  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(3).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 });
  };

  /**
     * Verify request unread và screenshot
     */
  async verifyRequestUnread(requestId: string, caseId: string, clientName: string) {
    await expect(this.requestLoc.requestNewID(requestId)).toBeVisible();
    await expect(this.requestLoc.itemBoldUnread.first()).toBeVisible();
    await this.resetToDefaultColumn(this.requestProps.customizedColumns, 1);
    await verifyScreenshot('new-request-unread.png', this.requestLoc.itemBoldUnread.first(), [this.requestLoc.requestNewID(requestId), this.requestLoc.requestNewID(caseId), this.dashboardLoc.common.aText(clientName)], 0.02);
  }

  /**
   * Open request detail và verify Banner 1 hoặc Banner 2
   */
  async openRequestAndVerifyBanner(requestId: string, bannerType: 'banner1' | 'banner2' = 'banner1') {
    await this.requestLoc.requestNewID(requestId).click();
    await expect(this.requestLoc.linkcase.bannerCreatedCaseSuccess).toBeVisible();

    if (bannerType === 'banner2') {
      await this.page.reload();
      await expect(this.requestLoc.linkcase.bannerCreatedCaseSuccess).toBeVisible();
      await expect(this.dashboardLoc.common.divText("Keep this Request in Active?")).toBeVisible();
      await verifyScreenshot('banner-request-relevant.png', this.requestLoc.linkcase.bannerRequestRelevant, [], 0.02);
    } else {
      await verifyScreenshot('banner-new-request-created.png', this.requestLoc.linkcase.bannerRequestLinkedToCase, [this.requestLoc.linkcase.svgBannerRequestLinkedToCase], 0.02);
    }
  }

  /**
   * Accept hoặc Reject request via Banner
   */
  async handleRequestBanner(action: 'accept' | 'reject') {
    const buttonText = action === 'accept' ? "Yes, Keep" : "No, Move";
    await this.dashboardLoc.buttonByText(buttonText).click();
    await expect(this.dashboardLoc.msgSuccess).toBeVisible();
    await expect(this.requestLoc.linkcase.bannerCreatedCaseSuccess).not.toBeVisible();
  }

  /**
   * Verify request ở tab Actionable hoặc Reference
   */
  async verifyRequestInTab(requestId: string, tab: 'actionable' | 'reference') {
    await this.open();
    await this.search(requestId);

    if (tab === 'reference') {
      await expect(this.dashboardLoc.table.noResult).toBeVisible();
      await this.dashboardLoc.common.divText("Reference").click();
      await this.search(requestId);
    }

    await expect(this.requestLoc.requestNewID(requestId)).toBeVisible();
  }

  // ==================== Link Case Helper Methods ====================

}