import { test, expect } from '../../../fixtures/index';
import { LoginPage } from '../../../pom/login.page';
import { CasePage } from '../../../pom/case/case.page';
import { getTodayInTimeZone, randomDate } from '../../../pom/utils/utlisFunc';
import { takeScreenshot, verifyScreenshot } from '../../../utils/screenshot';

test.describe('Case Module - Advanced Features', async () => {
  let loginPage: LoginPage;
  let casePage: CasePage;

  test.beforeEach("Login and verify data", async ({ page, conf }) => {
    // Initialize page objects
    loginPage = new LoginPage(page);
    casePage = new CasePage(page);

    await test.step("Login and go to case page", async () => {
      await loginPage.open();
      await loginPage.login(conf.data.username, conf.data.password);
      await expect(loginPage.baseLoc.dashboardContainer).toBeVisible();
      await casePage.open();
    });

    await test.step("Search with exist case", async () => {
      if (conf.data.no_search) {
        return;
      }
      if (conf.data.only_search) {
        return casePage.search(conf.data.case);
      }
      await casePage.getDetailCase(conf.data.case);
      await casePage.waitForSecond(2);
      if (conf.data.not_update) {
        return;
      }
      await expect(casePage.caseLoc.detail.buttonUpdateCase).toBeVisible();
      await casePage.caseLoc.detail.buttonUpdateCase.click({ force: true });
      await expect(casePage.dashboardLoc.modal.headerModal("Case Detail")).toBeVisible();
    });

    // Bổ sung thêm check info detail và info modal update (sau sẽ có thêm api -> bổ sung sau)
  });

  test("CASE_019 - Verify when add tag to case", {
    tag: ['@CASE_019', '@case', '@function']
  }, async () => {
    test.setTimeout(100_000);

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

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

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

    await test.step("Clear all tag", async () => {
      await casePage.clearAllTags();
      await casePage.saveTags();
      await expect(casePage.dashboardLoc.msgSuccess.first()).toBeVisible();
      await casePage.dashboardLoc.btnClosePopupNotification.click();
      await expect(casePage.dashboardLoc.tag.btnSaveTag).not.toBeVisible();

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

  test("CASE_020 - Verify status when change status detail case", {
    tag: ['@CASE_020', '@case', '@function']
  }, async () => {
    test.setTimeout(180_000);
    for (const { detail, expectedStatus } of casePage.statusTests) {
      await test.step(`Change Status Details to ${detail} and verify Status is ${expectedStatus}`, async () => {
        await casePage.caseLoc.detail.statusDetailsInput.click();
        await casePage.waitForSecond(1);
        await casePage.caseLoc.detail.statusDetailsOption(detail).click();
        await expect(casePage.caseLoc.detail.statusDisplay).toContainText(expectedStatus);
      });
    }
  })

  test("CASE_021 - Verify when Assignee case", {
    tag: ['@CASE_021', '@case', '@function']
  }, async ({ conf }) => {
    test.setTimeout(150_000)
    let currentAssignee: string = "";

    await test.step("Verify list option assignee member", async () => {
      currentAssignee = await casePage.caseLoc.detail.fullnameAssignee.innerText();
      const totalMembers = await casePage.getTotalMemberInBusiness();
      await casePage.caseLoc.detail.btnAssignee.click();
      await casePage.caseLoc.detail.inputSearchMember.click();
      await casePage.waitForSecond(2);
      const totalMembersUI = (await casePage.caseLoc.detail.optionMember.all()).length;
      expect(totalMembers).toBe(totalMembersUI - 1);
    });

    await test.step("Verify when add member not in Business", async () => {
      await casePage.caseLoc.detail.inputSearchMember.clear();
      await casePage.caseLoc.detail.inputSearchMember.fill(conf.data.member_not_in_business);
      await expect(casePage.caseLoc.detail.noOptionFound).toBeVisible();
      await casePage.caseLoc.detail.inputSearchMember.clear();
    });

    await test.step("Verify when assignee to member in business", async () => {
      await casePage.caseLoc.detail.inputSearchMember.type(conf.data.member_in_business, { delay: 100 });
      await expect(casePage.caseLoc.detail.optionSearchExist(conf.data.member_in_business)).toBeVisible({ timeout: 15_000 });
      await casePage.caseLoc.detail.optionSearchExist(conf.data.member_in_business).click();
      await casePage.dashboardLoc.buttonByText("Submit").nth(3).click();

      await expect(casePage.caseLoc.detail.fullnameAssignee).toContainText(conf.data.member_assignee);

      // Verify activity change
      const newestActivity = await casePage.getNewestActivity();
      expect(newestActivity).toContain(`changed the Assignee ${currentAssignee} ${conf.data.member_assignee} ${await getTodayInTimeZone()}`);
    });

    await test.step("Verify that the member who received the assignee gets a notification", async () => {
      await casePage.changeUser(conf.data.username_get_noti, conf.data.password_get_noti, casePage.page);
      await expect(loginPage.baseLoc.dashboardContainer).toBeVisible();
      await casePage.checkNotification("Assignee", true);
      await expect(casePage.caseLoc.detail.fullnameAssignee).toContainText(conf.data.member_assignee);
    });

    await test.step("Teardown: Assignee to old member", async () => {
      await casePage.caseLoc.detail.btnAssignee.click();
      await casePage.caseLoc.detail.inputSearchMember.fill(conf.data.member_first_assignee);
      await expect(casePage.caseLoc.detail.optionSearchExist(conf.data.member_first_assignee)).toBeVisible({ timeout: 15_000 });
      await casePage.caseLoc.detail.optionSearchExist(conf.data.member_first_assignee).click();
      await casePage.dashboardLoc.buttonByText("Submit").nth(3).click();
    });
  });

  test("CASE_022 - Dive deeper: Verify archive/unarchive a Business in case", {
    tag: ['@CASE_022', '@case', '@function']
  }, async ({ conf, casePage22 }) => {
    test.setTimeout(190_000);
    await test.step("Verify when archive business", async () => {
      await casePage22.clickButtonDropdownSelect("BTN_ARCHIVE_UNARCHIVE_BUSINESS_IN_CASE_DETAIL");

      await expect(casePage22.caseLoc.detail.popupSwal).toBeVisible();
      await casePage22.caseLoc.detail.btnCofirmArchive.click();

      await expect(casePage22.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage22.caseLoc.detail.btnViewArchivedBusiness).toBeVisible();
      await expect(casePage22.caseLoc.detail.singleBusinesses(conf.data.business_archive)).not.toBeVisible();

      // Verify activity
      const newestActivity = await casePage22.getNewestActivity();
      expect(newestActivity).toContain(`archive the business ${conf.data.business_archive} ${await getTodayInTimeZone()}`);
    });

    await test.step("Verify when unArchive business", async () => {
      await expect(casePage22.caseLoc.detail.btnViewArchivedBusiness).toBeVisible();
      await casePage22.gotoArchive(conf.data.case)
      await expect(casePage22.caseLoc.detail.singleBusinesses(conf.data.business_archive)).toBeVisible();

      await casePage22.clickButtonDropdownSelect("BTN_ARCHIVE_UNARCHIVE_BUSINESS_IN_CASE_DETAIL");
      await expect(casePage22.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await casePage22.waitForSecond(3);

      const listBusinesses = (await casePage22.caseLoc.detail.listBusinesses.all()).length;
      expect(listBusinesses).toBe(3);
      await expect(casePage22.caseLoc.detail.singleBusinesses(conf.data.business_archive)).toBeVisible();
      await expect(casePage22.caseLoc.detail.noDataRequest).toBeVisible();

      // Verify activity
      const newestActivity = await casePage22.getNewestActivity();
      expect(newestActivity).toContain(`unarchive the business ${conf.data.business_archive} ${await getTodayInTimeZone()}`);
    });

    await test.step("Unarchive all requests", async () => {
      let attempts = 0;

      while (attempts < 20) {
        const archiveLinks = casePage22.caseLoc.detail.listLinkArchiveRequests;
        const count = await archiveLinks.count();
        if (count === 0) {
          break;
        }
        try {
          await expect(archiveLinks.first()).toBeVisible({ timeout: 10_000 });
          await archiveLinks.first().click();
          await casePage22.caseLoc.detail.update.btnUnArchive.click();
          await casePage.dashboardLoc.buttonByText("Unarchive").click();
          await casePage.caseLoc.detail.btnClosePopup.click();
          await casePage22.caseLoc.btnCloseModal.click();
          await casePage22.caseLoc.linkToCase(conf.data.case).click();
          attempts++;
        } catch (error) {
          break;
        }
      }
      await expect(casePage22.caseLoc.detail.noDataRequest).not.toBeVisible({ timeout: 5000 });
    });
  });

  test("CASE_024 - Dive deeper: Verify when Start it in same type request", {
    tag: ['@CASE_024', '@case', '@function']
  }, async ({ conf, casePage24 }) => {
    await test.step("Verify request medical bill had star in table", async () => {
      await expect(casePage24.caseLoc.detail.requestHadStarIt(conf.data.case_had_star)).toBeVisible();
    });

    await test.step("Verify when change star it", async () => {
      await casePage24.changeStarFocus(conf.data.case_star_to);
      await expect(casePage24.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage24.caseLoc.detail.requestHadStarIt(conf.data.case_had_star)).not.toBeVisible();
      await expect(casePage24.caseLoc.detail.requestHadStarIt(conf.data.case_star_to)).toBeVisible();
    });
  });

  test("CASE_025 - Dive deeper: Customize column in request table", {
    tag: ['@CASE_025', '@case', '@function']
  }, async ({ conf }) => {
    // Verify default columns displayed
    await test.step("Verify default columns displayed", async () => {
      const customizedColumns = casePage.caseProps.requestsColumns;
      for (let i = 0; i < customizedColumns.length; i++) {
        if (customizedColumns[i].default) {
          await expect(casePage.caseLoc.detail.headingTableRequest(customizedColumns[i].tableDisplayName).first()).toBeVisible();
        }
      }
    });

    // Verify customized column show disable items and active items
    await test.step("Verify customized columns popup state", async () => {
      await casePage.openThreedotMenu(casePage.caseProps.threeDotDropdownMenus.customizedColumn, casePage.caseLoc.detail.threeDotCustomizeColumnRequest.first(), false);

      // Verify enabled column and disabled column
      const customizedColumns = casePage.caseProps.requestsColumns;
      for (let i = 0; i < customizedColumns.length; i++) {
        if (customizedColumns[i].default) {
          await expect(casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckboxRequestCase(customizedColumns[i].tableDisplayName).first()).toBeDisabled();
        } else {
          await expect(casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckboxRequestCase(customizedColumns[i].tableDisplayName).first()).toBeEnabled();
        }
      }
      await casePage.caseLoc.buttonByText("Apply").first().click();
    });

    // Check each columns and verify it shown
    await test.step("Check each columns and verify it shown", async () => {
      const customizedColumns = casePage.caseProps.requestsColumns.filter(column => !column.default);
      for (const column of customizedColumns) {
        await casePage.openThreedotMenu(casePage.caseProps.threeDotDropdownMenus.customizedColumn, casePage.caseLoc.detail.threeDotCustomizeColumnRequest.first(), false);
        await casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckboxRequestCase(column.tableDisplayName).first().setChecked(true);
        await casePage.caseLoc.buttonByText("Apply").first().click();
        await expect(casePage.caseLoc.detail.headingTableRequest(column.tableDisplayName).first()).toBeVisible();
      }
    });

    // Uncheck each columns and verify it hidden
    await test.step("Uncheck each columns and verify it hidden", async () => {
      const customizedColumns = casePage.caseProps.requestsColumns.filter(column => !column.default);
      // TODO: change to all columns. We're facing with some issues with the last column
      for (const column of customizedColumns) {
        await casePage.openThreedotMenu(casePage.caseProps.threeDotDropdownMenus.customizedColumn, casePage.caseLoc.detail.threeDotCustomizeColumnRequest.first(), false);
        await casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckboxRequestCase(column.tableDisplayName).first().setChecked(false);
        await casePage.caseLoc.buttonByText("Apply").first().click();
        await expect(casePage.caseLoc.detail.headingTableRequest(column.tableDisplayName).first()).not.toBeVisible();
      }
    });
  });

  test("CASE_026 - Quick summary: Verify filter activity by action type", {
    tag: ['@CASE_026', '@case', '@function']
  }, async () => {
    for (const { name, expectedRequests } of casePage.actionType) {
      await casePage.caseLoc.detail.dataRequestType(name).click();
      await expect(casePage.caseLoc.detail.textSummaryDisplay).toContainText(name);
      await casePage.waitForSecond(1);
      // Sau khi có api cần bổ sung thêm check request dựa và action type
    }
  });

  test("CASE_027 - Verify move request to another exist case", {
    tag: ['@CASE_027', '@case', '@function']
  }, async ({ conf, casePage27 }) => {
    test.setTimeout(100_000);
    await test.step("Verify business and request exist and open modal move request", async () => {
      await expect(casePage27.caseLoc.detail.singleBusinesses(conf.data.business)).toBeVisible();
      await casePage27.waitForSecond(1);
      expect((await casePage27.caseLoc.detail.listRequestOfBusiness.all()).length).toBeGreaterThan(0);

      await casePage27.clickButtonDropdownSelect("BTN_SHOW_MOVE_REQUEST_OF_BUSINESS_MODAL");
      await expect(casePage27.dashboardLoc.modal.headerModal("Move Requests")).toBeVisible();
    });

    await test.step("Verify when fill case and move request", async () => {
      await casePage27.caseLoc.detail.inputMoveRequest.click();
      await casePage27.caseLoc.detail.inputMoveRequest.type(conf.data.case_to_move, { delay: 100 });
      await casePage27.caseLoc.detail.transfer.boxOption(conf.data.case_to_move).click();
      await casePage27.caseLoc.buttonByText("Move").click();

      await expect(casePage27.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await casePage27.caseLoc.detail.btnClosePopup.click();
      await expect(casePage27.caseLoc.detail.textNoRequest).toBeVisible();

      // Verify activity
      const newestActivity = await casePage27.getNewestActivity();
      expect(newestActivity).toContain(`moved request from ${conf.data.business} Case: #${conf.data.case} #${conf.data.case_to_move} ${await getTodayInTimeZone()}`);
    });

    await test.step("Verify case and business exist ", async () => {
      await casePage27.open();
      await casePage27.getDetailCase(conf.data.case_to_move);
      await expect(casePage27.caseLoc.detail.singleBusinesses(conf.data.business)).toBeVisible();
      await casePage27.waitForSecond(2);
      expect((await casePage27.caseLoc.detail.listRequestOfBusiness.all()).length).toBeGreaterThan(0);
    });
  });

  test("CASE_028 - Verify move request to another new case", {
    tag: ['@CASE_028', '@case', '@function']
  }, async ({ conf }) => {
    await test.step("Verify business and request exist and open modal move request", async () => {
      await expect(casePage.caseLoc.detail.singleBusinesses(conf.data.business)).toBeVisible();
      expect((await casePage.caseLoc.detail.listRequestOfBusiness.all()).length).toBeGreaterThan(0);

      await casePage.clickButtonDropdownSelect("BTN_SHOW_MOVE_REQUEST_OF_BUSINESS_MODAL");
      await expect(casePage.dashboardLoc.modal.headerModal("Move Requests")).toBeVisible();
    });

    await test.step("Verify when move request to new case", async () => {
      await casePage.caseLoc.detail.radioCheckAddNew.click();
      await expect(casePage.caseLoc.detail.inputAddNewDOI).toBeVisible();
      await casePage.caseLoc.detail.inputAddNewDOI.fill(await randomDate());
      await casePage.dashboardLoc.modal.headerModal("Move Requests").click();
      await casePage.caseLoc.buttonByText("Move").click();

      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await casePage.dashboardLoc.btnClosePopupNotification.click();
      await expect(casePage.caseLoc.detail.textNoRequest).toBeVisible();
    });

    await test.step("Verify request in new case created and moved to", async () => {
      await casePage.dashboardLoc.notification.btnNotification.click();
      await casePage.dashboardLoc.notification.notificationType("Reminder").click();
      await casePage.dashboardLoc.notification.listNotiReminder.first().click();

      await expect(casePage.caseLoc.detail.singleBusinesses(conf.data.business)).toBeVisible();
      await casePage.waitForSecond(2);
      expect((await casePage.caseLoc.detail.listRequestOfBusiness.all()).length).toBeGreaterThan(0);
    });

    await test.step("Tear down move request to old case", async () => {
      await casePage.tearDownMoveToOldCase(conf.data.case);
    });
  });

  test("CASE_030 - Verify discussion in detail case", {
    tag: ['@CASE_030', '@case', '@function']
  }, async ({ conf, browser }) => {
    const uniqueMsg = `${conf.data.message}_${Date.now()}`;
    const uniqueMsgReply = `${conf.data.message_reply}_${Date.now()}`;
    await test.step("User A send inbox to team discussion", async () => {
      await casePage.caseLoc.detail.discussionCase.hover();
      await expect(casePage.caseLoc.detail.teamDiscussion).toBeVisible();
      await casePage.caseLoc.detail.teamDiscussion.click();
      await casePage.caseLoc.detail.discussion.inputMsg.fill(uniqueMsg);
      await casePage.caseLoc.detail.discussion.inputMsg.press("Enter");
      await expect(casePage.caseLoc.detail.discussion.contentMsg(uniqueMsg)).toBeVisible();
    });

    await test.step("User B get noti and reply to user A", async () => {
      const { context: contextB, casePage: casePageB } = await casePage.loginInAnotherBrowser(browser, conf.data.user_recive_message, conf.data.password);
      await casePageB.checkNotification("New Discussion", true);
      await expect(casePage.caseLoc.detail.discussion.contentMsg(uniqueMsg)).toBeVisible();

      await casePageB.caseLoc.detail.discussion.inputMsg.fill(uniqueMsgReply);
      await casePageB.caseLoc.detail.discussion.inputMsg.press("Enter");

      await expect(casePageB.caseLoc.detail.discussion.contentMsg(uniqueMsgReply)).toBeVisible();
      await contextB.close();
    });

    await test.step("User A revice noti and message", async () => {
      await casePage.page.reload();
      await casePage.checkNotification("New Discussion", true);
      await expect(casePage.caseLoc.detail.discussion.contentMsg(uniqueMsgReply)).toBeVisible();
    });
  });

  test("CASE_031 - Verify when click New request from detail case only load 1 time", {
    tag: ['@CASE_031', '@case', '@function']
  }, async ({ page, conf }) => {
    let navigatedOnce = false;

    page.on('framenavigated', (frame) => {
      if (frame === page.mainFrame() && frame.url().includes('/requests/create')) {
        if (navigatedOnce) {
          throw new Error('DOUBLE NAVIGATION DETECTED!');
        }
        navigatedOnce = true;
      }
    });

    await Promise.all([
      page.waitForURL(/.*\/requests\/create.*/, { timeout: 15_000 }),
      casePage.caseLoc.detail.btnCreateNewRequest.click(),
    ]);

    expect(navigatedOnce).toBe(true);

    await expect(casePage.caseLoc.detail.labelByStepCreateRequest(2))
      .toContainText(conf.data.patient_name);
    await expect(casePage.caseLoc.detail.labelByStepCreateRequest(3))
      .toContainText(conf.data.business_name);
  });

  test('CASE_007 - Verify feature Pin/Unpin for case', {
    tag: ['@CASE_007', '@case', '@function']
  }, async () => {
    const caseNumber = '999033';

    // Step 1: Search
    await casePage.caseLoc.inputSearch.fill(caseNumber);
    await expect(casePage.caseLoc.tableHeadingColumn('Pin')).toBeVisible();

    // Step 2: Verify pin icon hiển thị
    await expect(casePage.caseLoc.pinIcon(caseNumber)).toBeVisible();

    // Step 3: Click Pin
    await test.step('Click pin and verify', async () => {
      await casePage.caseLoc.pinIcon(caseNumber).click();
      await expect(casePage.caseLoc.pinnedIcon(caseNumber)).toBeVisible();
      await expect(casePage.caseLoc.firstCaseNumber(caseNumber)).toBeVisible();
    });

    // Step 4: Click Unpin
    await test.step('Click unpin and verify', async () => {
      await casePage.caseLoc.pinnedIcon(caseNumber).click();
      await expect(casePage.caseLoc.pinIcon(caseNumber)).toBeVisible();
    });
  });

  test("CASE_032 - Verify data when add to request cart", {
    tag: ['@CASE_032', '@case', '@function']
  }, async ({ conf, checkCart }) => {
    await test.step("Add requests to cart", async () => {
      await casePage.open();
      await checkCart.search(conf.data.case);
      await checkCart.waitForSecond(1);
      await checkCart.dashboardLoc.table.itemInRow(conf.data.case).hover({ force: true });
      await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Letter of Protection").click();
      await checkCart.requestLoc.detail.cartRequest.optionCartHoverCaseID("Medical Bill").click();
      await expect(checkCart.requestLoc.detail.cartRequest.quickSubmitButton("2")).toBeVisible();
    });

    await test.step("Verify cart data", async () => {
      await checkCart.page.mouse.move(0, 0);
      await checkCart.requestLoc.detail.cartRequest.quickSubmitButton("2").click();
      await expect(checkCart.requestLoc.detail.cartRequest.tdInTable("John Doe 65423").first()).toBeVisible();
      await checkCart.waitForSecond(1);
      await verifyScreenshot('list-request-by-case-overview.png', checkCart.requestLoc.create.overviewCreateFast);
    })
  })
});
