import { test, expect } from '../../../fixtures/index';
import { LoginPage } from '../../../pom/login.page';
import { CasePage } from '../../../pom/case/case.page';
import { getPagingMessage } from '../../../utils/paging';

test.describe('Case Module - Listing Features', 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_003 - Verify feature Search', {
    tag: ['@CASE_003', '@case', '@listing']
  }, async ({ conf }) => {
    for (const [key, value] of Object.entries(conf.data.search_field as Record<string, any>)) {
      await test.step(`Search with invalid ${key}`, async () => {
        await casePage.search(value.invalid_data);
        await expect(casePage.caseLoc.msgNoResultFound).toBeVisible();
      });
    }

    for (const [key, value] of Object.entries(conf.data.search_field as Record<string, any>)) {
      await test.step(`Search with valid ${key}`, async () => {
        await casePage.search(value.valid_data);
        expect(async () => {
          const rowCount = await casePage.getRowCount();
          expect(rowCount).toBeGreaterThan(0);
          await expect(casePage.dashboardLoc.table.itemInRow(value.valid_data).first()).toBeVisible();
          await expect(casePage.caseLoc.msgNoResultFound).not.toBeVisible();
        }).toPass();
      });
    }
  });

  test('CASE_005 - Verify feature sort cases', {
    tag: ['@CASE_005', '@case', '@listing']
  }, async () => {
    // Sort configuration for better maintainability
    const sortConfig = [
      { displayName: 'Case #', propertyName: 'id', direction: 'asc' },
      { displayName: 'Client Name', propertyName: 'customer_name', direction: 'asc' },
      { displayName: 'DOI', propertyName: 'date_of_injury', direction: 'asc' }
    ];

    for (const config of sortConfig) {
      // Verify column is visible and clickable
      await expect(casePage.dashboardLoc.table.headingColumn(config.displayName)).toBeVisible();
      await casePage.dashboardLoc.table.headingColumn(config.displayName).click();

      // Verify URL contains sort parameters
      await expect(casePage.page).toHaveURL(
        new RegExp(`.*sort=${config.propertyName}&direction=${config.direction}`)
      );

      // Get and verify sorted data
      const apiDataUrl = `cases?return_type=json&per_page=10&page=1&is_archived=false&sort=${config.propertyName}&direction=${config.direction}`;
      const data = await casePage.getDataInTable(config.displayName, config.propertyName, apiDataUrl);
      expect(data.dataApi).toEqual(data.dataUI);
    }
  });

  test('CASE_006 - Verify feature filter cases', {
    tag: ['@CASE_006', '@case', '@feature']
  }, async ({ conf }) => {
    const filterFields = casePage.caseProps.filterProperties;

    for (const filterField of filterFields) {
      // Reset to clean state
      await casePage.open();

      // Prepare locator based on filter type
      let fieldLocator;
      switch (filterField.type) {
        case 'input':
          fieldLocator = casePage.dashboardLoc.search.filter.popup.inputField(filterField.name);
          break;
        default:
          throw new Error(`Unsupported filter type: ${filterField.type}`);
      }

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

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

  test('CASE_008 - Verify màn contact page - customized column', {
    tag: ['@CASE_008', '@case', '@function']
  }, async ({ conf }) => {
    test.setTimeout(150_000)
    // Verify default columns displayed
    await test.step("Verify default columns displayed", async () => {
      const customizedColumns = casePage.caseProps.customizedColumns;
      for (const column of customizedColumns) {
        if (column.default) {
          await expect(casePage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)).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);

      // Verify enabled column and disabled column
      const customizedColumns = casePage.caseProps.customizedColumns;
      for (const column of customizedColumns) {
        if (column.default) {
          await expect(casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name)).toBeDisabled();
        } else {
          await expect(casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name)).toBeEnabled();
        }
      }
      await casePage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
    });

    // Pre-condition: disable all enabled column
    await test.step("Pre-condition: disable all enabled column", async () => {
      const customizedColumns = casePage.caseProps.customizedColumns.filter(column => !column.default);
      for (const column of customizedColumns) {
        await casePage.openThreedotMenu(casePage.caseProps.threeDotDropdownMenus.customizedColumn);
        await casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name).setChecked(false);
        await casePage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
      }
    });

    // Check each columns and verify it shown
    await test.step("Check each columns and verify it shown", async () => {
      await casePage.open();
      const customizedColumns = casePage.caseProps.customizedColumns.filter(column => !column.default);
      for (const column of customizedColumns) {
        await casePage.openThreedotMenu(casePage.caseProps.threeDotDropdownMenus.customizedColumn);
        await casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name).setChecked(true);
        await casePage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
        await expect(casePage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)).toBeVisible();
      }
    });

    // Uncheck each columns and verify it hidden
    await test.step("Uncheck each columns and verify it hidden", async () => {
      await casePage.open();
      const customizedColumns = casePage.caseProps.customizedColumns.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);
        await casePage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name).setChecked(false);
        await casePage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
        await expect(casePage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)).not.toBeVisible();
      }
    });
  });

  test('CASE_004 - Verify when change entries per page', {
    tag: ['@CASE_004', '@case', '@ui']
  }, async ({ conf }) => {
    const totalEntries = await casePage.getTotalEntries("cases");
    const testEntries = [10, 25];

    for (const entries of testEntries) {
      await test.step(`Select ${entries} entries per page`, async () => {
        await casePage.caseLoc.perPageInput.fill(entries.toString());
        await casePage.page.keyboard.press('Enter');

        const rowCount = await casePage.getRowCount();
        expect(rowCount).toBeLessThanOrEqual(entries);

        const expectedPaging = getPagingMessage(totalEntries, entries, 1);
        await expect(casePage.caseLoc.entriesTotal).toContainText(expectedPaging);
      });
    }
  });
});
