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

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

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

    await loginPage.open();
    await loginPage.login(conf.data.username, conf.data.password);
    await expect(loginPage.baseLoc.dashboardContainer).toBeVisible();
    await casePage.open();

  });

  test("CASE_010 - Verify when create new case with new client", {
    tag: ['@CASE_010', '@case', '@function']
  }, async ({ conf }) => {
    const uniqueBusiness = `Business New ${randomString(8)}`
    const randomName = `${conf.data.detail.client_name} ${randomString(5)}`;
    const email = `${randomName.trim().toLowerCase().replaceAll(" ", "")}@gmail.com`;
    const expectDataPreview = [randomName, conf.data.create_client.birthday, conf.data.create_client.address, email, conf.data.create_client.phone, conf.data.detail.description];

    await test.step("Fill data and fill new client", async () => {
      await casePage.caseLoc.buttonByText("New Case").click();

      //Fill new Business
      await casePage.caseLoc.create.detail.bussiness.type(uniqueBusiness, { delay: 100 });
      await expect(casePage.caseLoc.create.optionBusiness(uniqueBusiness)).toBeVisible();
      await casePage.caseLoc.create.optionBusiness(uniqueBusiness).click();

      await expect(casePage.dashboardLoc.modal.headerModal("New Business")).toBeVisible();
      await expect(casePage.dashboardLoc.modal.inputByID("autocomplete_name")).toHaveValue(uniqueBusiness);
      await casePage.dashboardLoc.buttonByText("Create").nth(1).click();

      await expect(casePage.dashboardLoc.msgCreateSuccess).toBeVisible();
      await casePage.dashboardLoc.btnClosePopupNotification.click();
      await expect(casePage.caseLoc.create.tagBusinessCreate(uniqueBusiness)).toBeVisible();

      // Fill detail case
      await casePage.fillCaseDetail(conf.data.detail, randomName, conf.data.detail.doi, true);

      //Open modal create new client
      await casePage.caseLoc.create.detail.createActive.click();
      await expect(casePage.dashboardLoc.modal.headerModal("New Patient")).toBeVisible();
    })

    await test.step("Add new Client and verify Preview", async () => {
      await casePage.fillDataCreateClient(conf.data.create_client, email);
      await expect(casePage.caseLoc.create.msgCreateSuccess.first()).toBeVisible();

      // Verify all preview data matches expected values
      for (let i = 0; i < casePage.infoPrev.length; i++) {
        await expect(casePage.caseLoc.create.preview.infoClient(casePage.infoPrev[i])).toContainText(expectDataPreview[i]);
      }
    });

    await test.step("Verify when create new case", async () => {
      await casePage.caseLoc.create.btnCreateCase.click();

      await expect(casePage.caseLoc.create.msgCreateSuccess.first()).toBeVisible();
      await expect(casePage.caseLoc.detail.noDataRequest).toBeVisible();
      await expect(casePage.caseLoc.detail.noLegal).toBeVisible();
      await expect(casePage.caseLoc.detail.businessContact).toContainText(uniqueBusiness);

      // Verify activity
      const newestActivity = await casePage.getNewestActivity();
      expect(newestActivity).toContain(`created the case ${await getTodayInTimeZone()}`);
    });
  });

  test("CASE_011 - Verify when create new case with exist client", {
    tag: ['@CASE_011', '@case', '@function']
  }, async ({ conf }) => {
    const doi = await randomDate();
    const expectDataPreview = [conf.data.detail.client_name, conf.data.info_client.birthday, conf.data.info_client.address, conf.data.info_client.email, conf.data.info_client.phone, conf.data.detail.description];

    await test.step("Fill data and verify it in preview", async () => {
      //Fill data
      await casePage.caseLoc.buttonByText("New Case").click();
      await casePage.fillCaseDetail(conf.data.detail, conf.data.detail.client_name, doi);
      await casePage.caseLoc.detail.boxClientNameActive.first().click()

      // Verify data show in preview
      for (let i = 0; i < casePage.infoPrev.length; i++) {
        await expect(casePage.caseLoc.create.preview.infoClient(casePage.infoPrev[i])).toContainText(expectDataPreview[i]);
      }
    });

    await test.step("Verify when create new case", async () => {
      await casePage.caseLoc.create.btnCreateCase.click();
      await casePage.waitForSecond(1);
      await expect(casePage.caseLoc.create.msgCreateSuccess.first()).toBeVisible();
      await expect(casePage.caseLoc.detail.noDataRequest).toBeVisible();
      await expect(casePage.caseLoc.detail.noLegal).toBeVisible();
      await expect(casePage.caseLoc.detail.businessContact).toContainText(conf.data.detail.business);

      // Verify activity
      const newestActivity = await casePage.getNewestActivity();
      expect(newestActivity).toContain(`created the case ${await getTodayInTimeZone()}`);
    });

    await test.step("Verify when add legal contact", async () => {
      await casePage.fillLegalContact(conf.data.detail.business, conf.data.user_recive_case);
      await casePage.dashboardLoc.modal.headerModal("Legal contacts representing this case").click();
      await casePage.dashboardLoc.buttonByText("Submit").nth(2).click();
      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage.caseLoc.detail.existLegal(conf.data.detail.client_name)).toBeVisible();
    });
  });
});

test.describe("Case already exists", async () => {
  let loginPage: LoginPage;
  let casePage: CasePage;

  test.beforeEach("Login and verify data", async ({ page, conf }) => {
    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.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_014 - Verify update case", {
    tag: ['@CASE_014', '@case', '@function']
  }, async ({ conf }) => {
    await test.step("Fill data to update modal", async () => {
      for (const formField of casePage.caseUpdateForm) {
        const fieldLocator = casePage.caseLoc.detail.update.fieldForm(formField.type, formField.inputName);
        await fieldLocator.fill(conf.data.update[formField.inputName]);
        await expect(fieldLocator).toHaveValue(conf.data.update[formField.inputName]);
      }
    });

    await test.step("Click update and verify data", async () => {
      await casePage.waitForSecond(2);
      await casePage.dashboardLoc.modal.headerModal("Case Detail").click();
      await casePage.dashboardLoc.buttonByText("Update").first().click({ force: true });
      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage.dashboardLoc.modal.headerModal("Case Detail")).not.toBeVisible();
    })

    await test.step("Teardown data", async () => {
      await casePage.caseLoc.detail.buttonUpdateCase.click();
      await expect(casePage.dashboardLoc.modal.headerModal("Case Detail")).toBeVisible();

      // Clear all form fields
      for (const formField of casePage.caseUpdateForm) {
        await casePage.caseLoc.detail.update.fieldForm(formField.type, formField.inputName).clear();
      }

      await casePage.dashboardLoc.buttonByText("Update").first().click();
      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
    });
  })

  test("CASE_015 - Verify update case when clear Law Firm, Counsel and Case Manager", {
    tag: ['@CASE_015', '@case', '@function']
  }, async ({ conf }) => {
    await test.step("Clear Law Firm, Counsel and Case Manager and submit", async () => {
      await casePage.caseLoc.detail.update.selectLawFirm("autocomplete_law_firm_id").first().click();
      await casePage.caseLoc.detail.update.selectLawFirm("autocomplete_lawyer_id").first().click();
      await casePage.caseLoc.detail.update.selectLawFirm("autocomplete_case_manager_id").first().click();
      await casePage.dashboardLoc.buttonByText("Update").first().click();

      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage.dashboardLoc.modal.headerModal("Case Detail")).not.toBeVisible();
      await expect(casePage.caseLoc.detail.noLegal).toBeVisible();
    })

    await test.step("Teardown data", async () => {
      await casePage.fillLegalContact(conf.data.business, conf.data.user_recive_case);
      await casePage.dashboardLoc.buttonByText("Submit").nth(2).click();
      await expect(casePage.caseLoc.detail.addLegalModal.msgSuccess.first()).toBeVisible();
      await expect(casePage.caseLoc.detail.noLegal).not.toBeVisible();
    })
  })

  test("CASE_016 - Verify when archived/unArchived case has no request yet", {
    tag: ['@CASE_016', '@case', '@function']
  }, async ({ conf, casePage16 }) => {
    test.setTimeout(150_000);
    await test.step("Verify when archive case", async () => {
      await expect(casePage16.caseLoc.detail.buttonUpdateCase).toBeVisible();
      await casePage16.caseLoc.detail.buttonUpdateCase.click({ force: true });
      await casePage16.dashboardLoc.buttonByText("Archive").first().click();
      await expect(casePage16.caseLoc.detail.update.msgArchive).toBeVisible();
      await casePage.dashboardLoc.btnClosePopupNotification.click();

      await expect(casePage16.dashboardLoc.modal.headerModalh2("Case Detail")).not.toBeVisible();
      await expect(casePage16.caseLoc.detail.update.boxHeaderArchive).toBeVisible();
      await casePage16.page.reload();// Sau khi client update tự reload cần bỏ

      // Verify activity
      const newestActivity = await casePage16.getNewestActivity();
      expect(newestActivity).toContain(`archive case ${await getTodayInTimeZone()}`);

      //Verify not show in table
      await casePage16.open();
      await casePage16.dashboardLoc.search.inputSearch.fill(conf.data.case);
      await expect(casePage16.caseLoc.msgNoResultFound).toBeVisible();
    })

    await test.step("Verify when unArchive case", async () => {
      //Verify data show in archived table
      await casePage16.dashboardLoc.search.filter.btn.click();
      await casePage16.caseLoc.inputArchive.fill("Yes");
      await casePage16.caseLoc.boxSelectArchive.click();
      await casePage16.dashboardLoc.search.filter.popup.btnApply.click();
      await expect(casePage16.dashboardLoc.table.itemInRow(conf.data.case)).toBeVisible();

      //Verify when unArchive case
      await casePage16.dashboardLoc.table.itemInRow(conf.data.case).click();
      await casePage16.caseLoc.detail.update.btnUnArchive.click();
      await expect(casePage16.caseLoc.detail.update.msgUnArchive.first()).toBeVisible();
      await expect(casePage16.caseLoc.detail.update.boxHeaderArchive).not.toBeVisible();
      await casePage16.page.reload(); // Sau khi client update tự reload cần bỏ

      // Verify change activity
      const newestActivity = await casePage16.getNewestActivity();
      expect(newestActivity).toContain(`unarchive case ${await getTodayInTimeZone()}`);

      //Verify case exist in table
      await casePage16.open();
      await casePage16.dashboardLoc.search.inputSearch.fill(conf.data.case);
      await expect(casePage16.dashboardLoc.table.itemInRow(conf.data.case)).toBeVisible();
    })
  })

  test("CASE_017 - Verify when archived/unArchived case has request and transfer to another case", {
    tag: ['@CASE_017', '@case', '@function']
  }, async ({ conf, casePage17 }) => {
    await test.step("Verify when archive case and transfer case", async () => {
      await expect(casePage17.dashboardLoc.buttonByText("Archive").first()).toBeVisible();
      await casePage17.dashboardLoc.buttonByText("Archive").first().click();

      await expect(casePage17.dashboardLoc.modal.headerModal("Archive")).toBeVisible();
      await casePage17.caseLoc.detail.transfer.inputTransfer.click();
      await casePage17.caseLoc.detail.transfer.inputTransfer.type(conf.data.case_transfer_to, { delay: 100 });
      await casePage17.caseLoc.detail.transfer.boxOption(conf.data.case_transfer_to).click();
      await casePage17.dashboardLoc.buttonByText("Archive").nth(1).click();

      await expect(casePage17.caseLoc.detail.update.btnUnArchive).toBeVisible();

      // Verify activity 
      await casePage17.waitForSecond(3); // Load for update new activity
      const newestActivity = await casePage17.getNewestActivity();
      expect(newestActivity).toContain(`archive case and moved request Case: #${conf.data.case_transfer} #${conf.data.case_transfer_to}`);
    });

    await test.step("Verify when unarchive case", async () => {
      await casePage17.caseLoc.detail.update.btnUnArchive.click();
      await expect(casePage17.caseLoc.detail.update.msgUnArchive.first()).toBeVisible();
      await expect(casePage17.caseLoc.detail.update.boxHeaderArchive).not.toBeVisible();
    })

    await test.step("Verify case have request had transfered", async () => {
      await casePage17.open();
      await casePage17.getDetailCase(conf.data.case_transfer_to);
      await casePage17.waitForSecond(2);
      const requests = (await casePage17.caseLoc.detail.requestExist(conf.data.request_id_exist).all()).length;
      expect(requests).toBe(2);
    })

    await test.step("Transfer teardown data", async () => {
      //Transfer again to old case
      await casePage17.clickButtonDropdownSelect("BTN_SHOW_MOVE_REQUEST_OF_BUSINESS_MODAL");
      await expect(casePage17.dashboardLoc.modal.headerModal("Move Requests")).toBeVisible();
      await casePage17.caseLoc.detail.inputMoveRequest.click();
      await casePage17.caseLoc.detail.inputMoveRequest.type(conf.data.case_transfer, { delay: 100 });
      await casePage17.caseLoc.detail.transfer.boxOption(conf.data.case_transfer).click();
      await casePage17.caseLoc.buttonByText("Move").click();
    })
  })

  test("CASE_018 - Verify when archived/unArchived case has been requested and not transferred to another case", {
    tag: ['@CASE_018', '@case', '@function']
  }, async ({ conf, casePage18 }) => {
    test.setTimeout(180_000);
    let numberRequest: number;

    await test.step("Go to get number requests in dashboard", async () => {
      await casePage18.page.goto("")
      await expect(casePage18.dashboardLoc.common.pText("My Requests")).toBeVisible();
      await casePage18.dashboardLoc.common.pText("My Requests").click();

      await expect(casePage18.dashboardLoc.filterMonitor.requestTypeNumber.first()).toBeVisible();
      await casePage18.waitForSecond(2);
      const textRequest = await casePage18.dashboardLoc.filterMonitor.requestTypeNumber.first().innerText();
      numberRequest = parseInt(textRequest);
    });

    await test.step("Verify archive and not transferred to another case", async () => {
      // Get detail case
      await casePage18.open();
      await casePage18.getDetailCase(conf.data.case);
      await expect(casePage18.caseLoc.detail.buttonUpdateCase).toBeVisible();

      // Archive case
      await casePage18.caseLoc.detail.buttonUpdateCase.click({ force: true });
      await casePage.dashboardLoc.buttonByText("Archive").first().click();
      await expect(casePage18.dashboardLoc.modal.headerModal("Archive")).toBeVisible();

      await casePage18.caseLoc.detail.transfer.radioCheckArchive.click();
      await casePage.dashboardLoc.buttonByText("Archive").nth(1).click();
      await expect(casePage18.caseLoc.detail.transfer.msgArchive).toBeVisible();
      await casePage18.dashboardLoc.btnClosePopupNotification.click();
    });

    await test.step("Verify requests archive in table", async () => {
      await casePage18.page.reload();
      await expect(casePage18.caseLoc.detail.dataIntable("Archived Request", conf.data.request_id_exist)).toBeVisible();
      await expect(casePage18.caseLoc.detail.requestTableNoResult).toBeVisible();

      // unArchive case
      await casePage18.caseLoc.detail.update.btnUnArchive.click();
      await expect(casePage18.caseLoc.detail.update.msgUnArchive.first()).toBeVisible();
      await casePage18.dashboardLoc.btnClosePopupNotification.click();
    });

    await test.step("Verify requests change number in dashboard", async () => {
      await casePage18.page.goto("")
      await expect(casePage18.dashboardLoc.common.pText("My Requests")).toBeVisible();
      await casePage18.dashboardLoc.common.pText("My Requests").click();
      await casePage18.waitForSecond(2);
      const textRequestAfter = await casePage18.dashboardLoc.filterMonitor.requestTypeNumber.first().innerText();
      const numberRequestAfter = parseInt(textRequestAfter);
      expect(numberRequestAfter).toBe(numberRequest - 1);
    });

    await test.step("Verify requests back to request table", async () => {
      await casePage18.open();
      await casePage18.getDetailCase(conf.data.case);
      await expect(casePage18.caseLoc.detail.requestExist(conf.data.request_id_exist).first()).toBeVisible();
      await casePage18.waitForSecond(1);
      await casePage18.caseLoc.detail.requestExist(conf.data.request_id_exist).first().click({ force: true });
      await casePage18.caseLoc.detail.update.btnUnArchive.click();
      await casePage.dashboardLoc.buttonByText("Unarchive").click()
      await casePage.caseLoc.btnCloseModal.click();
      await casePage18.caseLoc.linkToCase(conf.data.case).click();
      await casePage18.waitForSecond(2);
      await expect(casePage18.caseLoc.detail.requestTableNoResult).not.toBeVisible();
    });

    await test.step("Verify requests number in dashboard back to initial", async () => {
      await casePage18.page.goto("");
      await expect(casePage18.dashboardLoc.common.pText("My Requests")).toBeVisible();
      await casePage18.dashboardLoc.common.pText("My Requests").click();
      await casePage18.waitForSecond(2);
      const textRequestFinal = await casePage18.dashboardLoc.filterMonitor.requestTypeNumber.first().innerText();
      const numberRequestFinal = parseInt(textRequestFinal);
      expect(numberRequestFinal).toBe(numberRequest);
    });
  });

  test("CASE_033 - Add and manage businesses in case's detail", {
    tag: ['@CASE_033', '@case', '@function']
  }, async ({ conf }) => {
    await test.step("Setup and verify initial business state", async () => {
      if (!await casePage.caseLoc.detail.singleBusinesses(conf.data.business_no_request_1).isVisible({ timeout: 3_000 })) {
        await casePage.addBusinessInDetail(conf.data.business_no_request_1);
      }
    });

    await test.step("Verify business actions based on request status", async () => {
      // Verify business with requests
      await casePage.caseLoc.detail.btnDropDownActionBySingleBusiness(conf.data.business_had_request).click();
      await expect(casePage.caseLoc.detail.btnDropdownBusiness).toBeVisible();
      await casePage.caseLoc.detail.btnDropdownBusiness.click();
      await expect(casePage.dashboardLoc.root).toMatchAriaSnapshot(`- text: Archive Move Requests`);

      // Verify business without requests
      await casePage.caseLoc.detail.btnDropDownActionBySingleBusiness(conf.data.business_no_request_1).click();
      await casePage.caseLoc.detail.btnDropdownBusiness.click();
      await expect(casePage.dashboardLoc.root).toMatchAriaSnapshot(`- text: Remove`);
    });

    await test.step("Add business through case update modal", async () => {
      await casePage.dashboardLoc.buttonByText("Update Case").click();
      await expect(casePage.dashboardLoc.modal.headerModal("Case Detail")).toBeVisible();
      await casePage.dashboardLoc.modal.inputByID("multi_select_provider_ids").type(conf.data.business_no_request_2, { delay: 100 });
      await casePage.caseLoc.create.detail.boxTextBusinessByName(conf.data.business_no_request_2).click();
      await casePage.dashboardLoc.modal.headerModal("Case Detail").click();
      await casePage.dashboardLoc.buttonByText("Update").first().click();
      await expect(casePage.caseLoc.detail.btnDropDownActionBySingleBusiness(conf.data.business_no_request_2)).toBeVisible();
      await expect(casePage.dashboardLoc.msgSuccess).toBeVisible();
      await casePage.dashboardLoc.btnClosePopupNotification.click();
    });

    await test.step("Add and remove businesses in detail view", async () => {
      // Add business
      await casePage.addBusinessInDetail(conf.data.business_no_request_3);
      await expect(casePage.caseLoc.detail.btnDropDownActionBySingleBusiness(conf.data.business_no_request_3)).toBeVisible();

      // Remove businesses
      await casePage.removeBusiness(conf.data.business_no_request_2);
      await casePage.removeBusiness(conf.data.business_no_request_3);
    });
  })
});
