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

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

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

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

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

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

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

                await expect(sentPage.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 sentPage.dashboardLoc.search.perPage.input.fill(String(entrie));
                await expect(sentPage.dashboardLoc.search.perPage.input).not.toHaveValue(String(entrie));
            }
        })
    })

    test("SENT_005 - Verify feature sort sent", {
        tag: ["@SENT_005", "@sent", "@function"]
    }, async () => {
        test.setTimeout(150_000);
        const displayNames = ['Request #', 'Message', 'Sent Date'];
        const sortedFieldName = ['request_id', 'message', 'created_at'];
        const propertyNames = ['request.id', '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(sentPage.dashboardLoc.table.headingColumn(displayNames[j])).toBeVisible();

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

                let apiDataUrl = `api/v1/share-requests/sent?sort=${sortedFieldName[j]}&direction=${sortType[i]}`;
                const data = await sentPage.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("SENT_006 - Verify feature filter", {
        tag: ["@SENT_006", "@sent", "@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 sentPage.dashboardLoc.search.filter.btn.click();
                        await sentPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await sentPage.sentLoc.filter.inputByID(validField.id).fill(validField.value);

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

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

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

                case 'select':
                    for (const [fieldName, field] of Object.entries(fields as Record<string, any>)) {
                        const { valid: validField, invalid: invalidField } = field;

                        // Test valid case
                        await sentPage.dashboardLoc.search.filter.btn.click();
                        await sentPage.dashboardLoc.search.filter.popup.btnReset.click();

                        await sentPage.sentLoc.filter.inputByID(validField.id).fill(validField.value);
                        await sentPage.sentLoc.table.dataInRow(validField.value).waitFor({ state: 'visible' });
                        await sentPage.sentLoc.table.dataInRow(validField.value).click();

                        // Handle special case for recipient email vs general case
                        const isRecipientEmail = validField.id === "autocomplete_recipient_email";
                        const expectedValue = isRecipientEmail ? "Minh Phong" : validField.value;
                        const expectedRowData = isRecipientEmail ? "Minh" : validField.value;

                        await expect(sentPage.sentLoc.filter.inputByID(validField.id)).toHaveValue(expectedValue);
                        await sentPage.dashboardLoc.search.filter.popup.btnApply.click();
                        await expect(sentPage.sentLoc.table.dataInRowSpan(expectedRowData).first()).toBeVisible();

                        // Test invalid case
                        await sentPage.dashboardLoc.search.filter.btn.click();
                        await sentPage.dashboardLoc.search.filter.popup.btnReset.click();
                        await sentPage.sentLoc.filter.inputByID(invalidField.id).fill(invalidField.value);
                        await expect(sentPage.sentLoc.filter.noOption).toBeVisible();
                    }
                    break;

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