import { test, expect } from '../../fixtures/index';
import { InboxPage } from '../../pom/inbox/inbox.page';
import { LoginPage } from '../../pom/login.page';

test.describe("Verify feature inbox", () => {
    let loginPage: LoginPage;
    let inboxPage: InboxPage;

    test.beforeEach(async ({ page, conf }) => {
        loginPage = new LoginPage(page);
        inboxPage = new InboxPage(page);

        await loginPage.open();
        await loginPage.login(conf.data.username, conf.data.password);
        await expect(loginPage.baseLoc.dashboardContainer).toBeVisible({ timeout: 15_000 });
        await inboxPage.open();
    });

    test("INBOX_003 - Verify feature Search", {
        tag: ["@INBOX_003", "@inbox", "@function"]
    }, async ({ conf }) => {
        await test.step(`Verify search valid data`, async () => {
            for (const value of Object.values(conf.data.valid)) {
                await inboxPage.dashboardLoc.search.inputSearch.fill(String(value));
                if (value === conf.data.valid.month_day_slashed || value === conf.data.valid.month_day_numeric || value === conf.data.valid.full_date_numeric) {
                    await inboxPage.waitForSecond(1);
                    await expect(inboxPage.dashboardLoc.table.noResult).not.toBeVisible();
                } else {
                    await inboxPage.waitForSecond(1);
                    await expect(inboxPage.inboxLoc.table.dataInRow(String(value)).first()).toBeVisible();
                }
            }
        })

        await test.step("Verify when search with invalid data", async () => {
            await inboxPage.dashboardLoc.search.inputSearch.fill(conf.data.invalid);
            await expect(inboxPage.dashboardLoc.table.noResult).toBeVisible();
        })
    })

    test("INBOX_004 - Verify when change entries per page", {
        tag: ["@INBOX_004", "@inbox", "@function"]
    }, async ({ conf }) => {
        await test.step("Verify with valid entries", async () => {
            const totalInboxes = await inboxPage.getTotalEntries("api/v1/share-requests/inbox");
            for (const entrie of Object.values(conf.data.valid)) {
                await inboxPage.dashboardLoc.search.perPage.input.fill(String(entrie));
                await expect(inboxPage.dashboardLoc.search.perPage.input).toHaveValue(String(entrie));
                await inboxPage.page.waitForResponse(/api\/v1\/share-requests\/inbox\?per_page/, { timeout: 15_000 });
                const tableRows = await inboxPage.getTableRowCount();
                const showingData = parseFloat(String(entrie)) > totalInboxes ? totalInboxes : parseFloat(String(entrie))

                await expect(inboxPage.dashboardLoc.table.pagingSummary).toContainText(`Showing 1 to ${showingData} of ${totalInboxes} entries`);
                expect(tableRows).toBe(parseFloat(showingData));
            }
        })

        await test.step("Verify when enter invalid entrie", async () => {
            for (const entrie of Object.values(conf.data.invalid)) {
                await inboxPage.dashboardLoc.search.perPage.input.fill(String(entrie));
                await expect(inboxPage.dashboardLoc.search.perPage.input).not.toHaveValue(String(entrie));
            }
        })
    })

    test("INBOX_005 - Verify feature sort inbox", {
        tag: ["@INBOX_005", "@inbox", "@function"]
    }, async () => {
        test.setTimeout(150_000);
        const displayNames = ['Request #', 'Sender', 'Message', 'Inbox Date'];
        const sortedFieldName = ['request_id', 'sender_email', 'message', 'created_at'];
        const propertyNames = ['request.id', 'mails.from.name', 'message', 'created_at'];
        const sortType = ["asc", "desc"];

        for (let i = 0; i < sortType.length; i++) {
            for (let j = 0; j < displayNames.length; j++) {
                await expect(inboxPage.dashboardLoc.table.headingColumn(displayNames[j])).toBeVisible();

                if (sortType[i] === "asc") {
                    await inboxPage.dashboardLoc.table.headingColumn(displayNames[j]).click();
                } else {
                    await inboxPage.dashboardLoc.table.headingColumn(displayNames[j]).click();
                    await inboxPage.waitForSecond(2);
                    await inboxPage.dashboardLoc.table.headingColumn(displayNames[j]).click();
                    await inboxPage.waitForSecond(2);
                }
                await expect(inboxPage.page).toHaveURL(
                    new RegExp(`.*sort=${sortedFieldName[j]}&direction=${sortType[i]}`)
                );

                let apiDataUrl = `api/v1/share-requests/inbox?sort=${sortedFieldName[j]}&direction=${sortType[i]}`;
                const data = await inboxPage.getDataInTable(displayNames[j], propertyNames[j], apiDataUrl, false);
                console.log(`Sort by: ${displayNames[j]}, direction: ${sortType[i]}, property: ${propertyNames[j]}`);
                if (sortedFieldName[j] === "sender_email") {
                    data.dataApi.forEach(name => {
                        expect(data.dataUI.some(uiVal => uiVal.includes(name))).toBeTruthy();
                    });
                } else {
                    expect(data.dataApi).toEqual(data.dataUI);
                }
            }
        }
    })

    test("INBOX_006 - Verify feature filter", {
        tag: ["@INBOX_006", "@inbox", "@function"]
    }, async ({ conf }) => {
        for (const [filterType, fields] of Object.entries(conf.data.filter)) {
            switch (filterType) {
                case 'text':
                    for (const [fieldName, field] of Object.entries(fields as Record<string, any>)) {
                        // Handle valid case
                        const validField = field.valid;
                        await inboxPage.dashboardLoc.search.filter.btn.click();
                        await inboxPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await inboxPage.inboxLoc.filter.inputByID(validField.id).fill(validField.value);

                        await expect(inboxPage.inboxLoc.filter.inputByID(validField.id)).toHaveValue(validField.value);
                        await inboxPage.dashboardLoc.search.filter.popup.btnApply.click();
                        await expect(inboxPage.inboxLoc.table.dataInRow(validField.value).first()).toBeVisible();

                        // Handle invalid case
                        const invalidField = field.invalid;
                        await inboxPage.dashboardLoc.search.filter.btn.click();
                        await inboxPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await inboxPage.inboxLoc.filter.inputByID(invalidField.id).fill(invalidField.value);

                        await expect(inboxPage.inboxLoc.filter.inputByID(invalidField.id)).toHaveValue(invalidField.value);
                        await inboxPage.dashboardLoc.search.filter.popup.btnApply.click();
                        await expect(inboxPage.dashboardLoc.table.noResult).toBeVisible();
                    }
                    break;

                case 'select':
                    for (const [fieldName, field] of Object.entries(fields as Record<string, any>)) {
                        // Handle valid case
                        const validField = field.valid;
                        await inboxPage.dashboardLoc.search.filter.btn.click();
                        await inboxPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await inboxPage.inboxLoc.filter.inputByID(validField.id).fill(validField.value);
                        await inboxPage.inboxLoc.filter.dropdownOption(validField.value).waitFor({ state: 'visible' });
                        await inboxPage.inboxLoc.filter.dropdownOption(validField.value).click();
                        await expect(inboxPage.inboxLoc.filter.inputByID(validField.id)).toHaveValue(validField.value);

                        await inboxPage.dashboardLoc.search.filter.popup.btnApply.click();
                        await expect(inboxPage.inboxLoc.table.dataInRow(validField.value).first()).toBeVisible();

                        // Handle invalid case
                        const invalidField = field.invalid;
                        await inboxPage.dashboardLoc.search.filter.btn.click();
                        await inboxPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await inboxPage.inboxLoc.filter.inputByID(invalidField.id).fill(invalidField.value);
                        await expect(inboxPage.inboxLoc.filter.noOption).toBeVisible();
                    }
                    break;

                default:
                    console.warn(`Unknown filter type: ${filterType}`);
            }
        }
    })
})