import { test, expect } from "../../../fixtures/index";
import { ContactPage } from "../../../pom/contact/contact.page";
import { LoginPage } from "../../../pom/login.page";

test.describe("Listing operations for contact tests", async () => {
    let loginPage: LoginPage;
    let contactPage: ContactPage;

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

        await test.step("Navigate to login page", async () => {
            await loginPage.open();
            await page.waitForLoadState('networkidle');
        });

        await test.step("Perform login authentication", async () => {
            await loginPage.login(conf.data.username, conf.data.password);
            await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
        });

        if (conf.data.not_redirect) {
            return;
        }

        await test.step("Navigate to contact page", async () => {
            await contactPage.open();
            await page.waitForLoadState('networkidle');
        });
    });

    test("CONTACT_003 - Verify contact search functionality", {
        tag: ["@CONTACT_003", "@contact", "@function"]
    }, async ({ conf }) => {
        for (const [key, value] of Object.entries(conf.data.search_data.invalid_data as Record<string, any>)) {
            await test.step(`Search with invalid ${key}`, async () => {
                await contactPage.search(value);
                await expect(contactPage.dashboardLoc.table.noResult.first()).toBeVisible();
            });
        }

        for (const [key, value] of Object.entries(conf.data.search_data.valid_data as Record<string, any>)) {
            await test.step(`Search with valid ${key}`, async () => {
                await contactPage.search(value);

                // Nếu là phone, vẫn kiểm tra invalid_data trước
                if (key === 'contact_phone') {
                    await expect(contactPage.dashboardLoc.table.itemInRow(conf.data.search_data.invalid_data.phone_invalid).first()).toBeVisible();
                } else {
                    await expect(contactPage.dashboardLoc.table.itemInRow(value).first()).toBeVisible();
                }
            });
        }
    });

    test("CONTACT_004 - Verify entries per page functionality", {
        tag: ["@CONTACT_004", "@contact", "@function"]
    }, async ({ conf }) => {
        const totalContacts = await contactPage.getTotalEntries("contact-members?return_type=json&return_type=json&type=1");
        const firstEntries = conf.data.first_entries;
        const secondEntries = conf.data.second_entries;
        
        await test.step("Verify 10 entries per page", async () => {
            await expect(contactPage.dashboardLoc.table.tabInTable("All")).toBeVisible();
            await contactPage.dashboardLoc.table.tabInTable("All").click();
            await contactPage.page.waitForResponse(
                response => response.url().includes('api/v1/contact-members') &&
                    response.url().includes('group=0,1,2') &&
                    response.status() === 200,
                { timeout: 15_000 }
            );
            await contactPage.contactLoc.inputEntries.fill(firstEntries.toString());
            await expect(contactPage.contactLoc.inputEntries).toHaveValue(firstEntries);

            const expectedText = `Showing 1 to ${firstEntries} of ${totalContacts} entries`;
            expect(await contactPage.contactLoc.showingEntries.innerText()).toBe(expectedText);
        });

        await test.step("Verify 25 entries per page", async () => {
            await contactPage.contactLoc.inputEntries.fill(secondEntries.toString());
            await contactPage.waitForSecond(3);
            await expect(contactPage.contactLoc.inputEntries).toHaveValue(secondEntries);

            const expectedText = `Showing 1 to ${secondEntries} of ${totalContacts} entries`;
            expect(await contactPage.contactLoc.showingEntries.innerText()).toBe(expectedText);
        });
    });

    test("CONTACT_005 - Verify contact sorting functionality", {
        tag: ["@CONTACT_005", "@contact", "@function"]
    }, async () => {
        test.setTimeout(200_000);

        const sortConfig = {
            displayNames: ['Name', 'Email', 'Phone', 'Address'],
            sortedFieldName: ['full_name', 'email_address', 'phone_number', 'full_address'],
            propertyNames: ['full_name', 'email_address', 'phone_number', 'full_address'],
            sortTypes: ["asc", "desc"],
            defaultPerPage: 10,
            defaultPage: 1
        };
        await test.step("Navigate to All tab", async () => {
            await contactPage.dashboardLoc.table.tabInTable("All").click();
        });

        for (const sortType of sortConfig.sortTypes) {
            for (let j = 0; j < sortConfig.displayNames.length; j++) {
                const displayName = sortConfig.displayNames[j];
                const sortedFieldName = sortConfig.sortedFieldName[j];
                const propertyName = sortConfig.propertyNames[j];

                await test.step(`Sort by ${displayName} - ${sortType}`, async () => {
                    await expect(contactPage.dashboardLoc.table.headingColumn(displayName)).toBeVisible();

                    if (sortType === "asc") {
                        await contactPage.dashboardLoc.table.headingColumn(displayName).click();
                    } else {
                        await contactPage.dashboardLoc.table.headingColumn(displayName).click();
                        await contactPage.waitForSecond(2);
                        await contactPage.dashboardLoc.table.headingColumn(displayName).click();
                    }

                    await expect(contactPage.page).toHaveURL(
                        new RegExp(`.*sort=${sortedFieldName}&direction=${sortType}`)
                    );

                    const apiDataUrl = `api/v1/contact-members?return_type=json&is_archived=false&per_page=${sortConfig.defaultPerPage}&page=${sortConfig.defaultPage}&sort=${sortedFieldName}&direction=${sortType}`;
                    const data = await contactPage.getDataInTable(displayName, propertyName, apiDataUrl, true);

                    console.log(`Sort by: ${displayName}, direction: ${sortType}, property: ${propertyName}`);
                    expect(data.dataApi).toEqual(data.dataUI);
                });
            }
        }
    });

    test("CONTACT_006 - Verify contact filtering functionality", {
        tag: ["@CONTACT_006", "@contact", "@function"]
    }, async ({ conf }) => {
        const filterFields = contactPage.filterProperties.filterName;

        for (const filterField of filterFields) {
            await contactPage.open();
            const fieldLocator = contactPage.dashboardLoc.search.filter.popup.inputField(filterField.name);
            const filterData = conf.data.filter_data[filterField.name];

            await test.step(`Test filtering by ${filterField.name} with invalid data`, async () => {
                await contactPage.dashboardLoc.search.filter.btn.click();
                await expect(contactPage.dashboardLoc.search.filter.popup.container).toBeVisible();
                await fieldLocator.fill(filterData.invalid_data);

                if (filterField.type === "input") {
                    await contactPage.dashboardLoc.search.filter.popup.btnApply.click();
                    await expect(contactPage.dashboardLoc.table.noResult.first()).toBeVisible();
                } else {
                    await expect(contactPage.filterProperties.msgNoOption).toBeVisible();
                    await contactPage.dashboardLoc.search.filter.popup.btnApply.click();
                }
            });

            await test.step(`Test filtering by ${filterField.name} with valid data`, async () => {
                await contactPage.dashboardLoc.search.filter.btn.click();
                await expect(contactPage.dashboardLoc.search.filter.popup.container).toBeVisible();

                let dataFilterFields: any;

                if (filterField.type === "input") {
                    await fieldLocator.fill(filterData.valid_data);
                    dataFilterFields = await contactPage.filterSingleField(
                        "contact-members",
                        filterField.name,
                        filterData.valid_data,
                        filterField.paramFilter
                    );
                } else {
                    await fieldLocator.fill(conf.data.filter_group);
                    await contactPage.contactLoc.optionInSelect(conf.data.filter_group).click();
                    await expect(contactPage.contactLoc.boxSelectOption(conf.data.filter_group)).toBeVisible();
                    dataFilterFields = await contactPage.filterSingleField(
                        "contact-members",
                        filterField.name,
                        conf.data.filter_group,
                        filterField.paramFilter
                    );
                }

                await contactPage.dashboardLoc.search.filter.popup.btnApply.click();
                expect(dataFilterFields.every((item: any) => item === filterData.valid_data)).toBeTruthy();
                await expect(contactPage.dashboardLoc.table.noResult).not.toBeVisible();
            });
        }
    });

    test("CONTACT_008 - Verify customized columns functionality", {
        tag: ["@CONTACT_008", "@contact", "@function"],
    }, async () => {
        const customThreeDotLocator = contactPage.genLoc("(//div[contains(@class, 'card-header')]//span[contains(@class, 'cursor-pointer')])[1]");
        const customizedColumns = contactPage.contactProps.customizedColumns;
        const customizedColumnMenu = contactPage.contactProps.threeDotDropdownMenus.customizedColumn;

        await test.step("Verify default columns are displayed", async () => {
            for (const column of customizedColumns) {
                if (column.default) {
                    await expect(
                        contactPage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)
                    ).toBeVisible();
                }
            }
        });

        await test.step("Verify customized columns popup state", async () => {
            await contactPage.openThreedotMenu(customizedColumnMenu, customThreeDotLocator);

            for (const column of customizedColumns) {
                const columnCheckbox = contactPage.dashboardLoc.listing.popup.customizedColumn.columnCheckbox(column.name);

                if (column.default) {
                    await expect(columnCheckbox).toBeDisabled();
                } else {
                    await expect(columnCheckbox).toBeEnabled();
                }
            }
        });

        await test.step("Pre-condition: disable all optional columns", async () => {
            const optionalColumns = customizedColumns.filter(column => !column.default);

            for (const column of optionalColumns) {
                await contactPage.dashboardLoc.listing.popup.customizedColumn
                    .columnCheckbox(column.name)
                    .setChecked(false);
            }
            await contactPage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();
        });

        await test.step("Enable each column and verify visibility", async () => {
            await contactPage.open();
            const optionalColumns = customizedColumns.filter(column => !column.default);

            for (const column of optionalColumns) {
                await contactPage.openThreedotMenu(customizedColumnMenu, customThreeDotLocator);
                await contactPage.dashboardLoc.listing.popup.customizedColumn
                    .columnCheckbox(column.name)
                    .setChecked(true);
                await contactPage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();

                await expect(
                    contactPage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)
                ).toBeVisible();
            }
        });

        await test.step("Disable each column and verify it's hidden", async () => {
            await contactPage.open();
            const optionalColumns = customizedColumns.filter(column => !column.default);

            for (const column of optionalColumns) {
                await contactPage.openThreedotMenu(customizedColumnMenu, customThreeDotLocator);
                await contactPage.dashboardLoc.listing.popup.customizedColumn
                    .columnCheckbox(column.name)
                    .setChecked(false);
                await contactPage.dashboardLoc.listing.popup.customizedColumn.btnApply.click();

                console.log(`Verifying column hidden: ${column.tableDisplayName}`);
                await expect(
                    contactPage.dashboardLoc.listing.heading.headingColumn(column.tableDisplayName)
                ).not.toBeVisible();
            }
        });
    });

    test("CONTACT_026 - Verify list Bulk Edit", {
        tag: ["@CONTACT_026", "@contact", "@function"],
    }, async ({ conf }) => {
        // Initialize
        await contactPage.getDetailCase(conf.data.contact_name);

        // Test scenarios
        await contactPage.verifyBulkEditForTab("Cases", 3, "Contact Detail");
        await contactPage.verifyBulkEditForTab("Cases", 5, "Contact Detail");
        await contactPage.verifyBulkEditForTab("Request", 3, "Contact Detail");
        await contactPage.verifyBulkEditForTab("Request", 5, "Contact Detail", false);
    })
});
