import { isTestSuiteActive } from "../../support/page_objects/projectConstants";
import { mainPage } from "../../support/page_objects/mainPage";

let storedURL = "";

// 0: all enabled
// 1: field hide
// 2: field sort
// 3: field filter
// 4: default (address table): for view operation validation
// 5: default (country table): for update row/column validation
let viewURL = {};

export const genTest = (apiType, dbType) => {
    if (!isTestSuiteActive(apiType, dbType)) return;

    const generateViewLink = (viewName) => {
        // click on share view
        // cy.get(".v-navigation-drawer__content > .container")
        //   .find(".v-list > .v-list-item")
        //   .contains("Share View")
        //   .click();
        mainPage.shareView().click({ force: true });
        
        cy.wait(5000);
        
        // wait, as URL initially will be /undefined
        cy.getActiveModal(".nc-modal-share-view")
            .find(".share-link-box")
            .contains("/nc/view/", { timeout: 10000 })
            .should("exist");

        // copy link text, visit URL
        cy.getActiveModal(".nc-modal-share-view")
            .find(".share-link-box")
            .contains("/nc/view/", { timeout: 10000 })
            .then(($obj) => {
                cy.get("body").type("{esc}");
                // viewURL.push($obj.text())
                viewURL[viewName] = $obj.text().trim();
            });
    };

    describe(`${apiType.toUpperCase()} api - GRID view (Share)`, () => {
        // Run once before test- create project (rest/graphql)
        //
        before(() => {
            cy.fileHook();
            mainPage.tabReset();
            // open a table to work on views
            //
            cy.openTableTab("Address", 25);

            cy.saveLocalStorage();
        });

        beforeEach(() => {
            cy.restoreLocalStorage();
        });

        afterEach(() => {
            cy.saveLocalStorage();
        });

        after(() => {
            // close table
            // mainPage.deleteCreatedViews()
            cy.closeTableTab("Address");
        });

        // Common routine to create/edit/delete GRID & GALLERY view
        // Input: viewType - 'grid'/'gallery'
        //
        const viewTest = (viewType) => {
            it(`Create ${viewType.toUpperCase()} view`, () => {
                // create a normal public view
                cy.get(`.nc-create-${viewType}-view`).click();
                cy.getActiveModal(".nc-modal-view-create").find("button:contains(Submit)").click();
                cy.toastWait("View created successfully");

                // store base URL- to re-visit and delete form view later
                cy.url().then((url) => {
                    storedURL = url;
                });
            });

            it(`Share ${viewType.toUpperCase()} hide, sort, filter & verify`, () => {
                cy.get(`.nc-view-item.nc-${viewType}-view-item`)
                    .contains("Address1")
                    .click();
                mainPage.hideField("Address2");
                mainPage.sortField("Address", "Z → A");
                mainPage.filterField("Address", "is like", "Ab");
                generateViewLink("combined");
                cy.log(viewURL["combined"]);
            });

            it(`Share GRID view : ensure we have only one link even if shared multiple times`, () => {
                // generate view link multiple times
                generateViewLink("combined");
                generateViewLink("combined");

                // verify if only one link exists in table
                // cy.get(".v-navigation-drawer__content > .container")
                //   .find(".v-list > .v-list-item")
                //   .contains("Share View")
                //   .parent()
                //   .find("button.mdi-dots-vertical")
                //   .click();
                mainPage.shareViewList().click();

                // cy.getActiveMenu().find(".v-list-item").contains("Views List").click();

                cy.get('th:contains("View Link")').should("exist");

                cy.get('th:contains("View Link")')
                    .parent()
                    .parent()
                    .next()
                    .find("tr")
                    .its("length")
                    .should("eq", 1)
                    .then(() => {
                        // cy.get(".v-overlay__content > .d-flex > .v-icon").click();
                        // close modal (fix me! add a close button to share view list modal)
                        cy.get(".v-overlay--active > .v-overlay__scrim").click({
                            force: true,
                        });
                    });
            });

            it(`Share ${viewType.toUpperCase()} view : Visit URL, Verify title`, () => {
                // visit public view
                cy.visit(viewURL["combined"], {
                    baseUrl: null,
                });
                cy.wait(5000);

                // wait for page rendering to complete
                cy.get(".nc-grid-row").should("have.length", 18);

                // verify title
                cy.get("div.model-name").contains("Address1").should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : verify fields hidden/open`, () => {
                // verify column headers
                cy.get('[data-col="Address"]').should("exist");
                cy.get('[data-col="Address2"]').should("not.exist");
                cy.get('[data-col="District"]').should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : verify fields sort/ filter`, () => {
                // country column content verification before sort
                mainPage
                    .getCell("Address", 1)
                    .contains("669 Firozabad Loop")
                    .should("exist");
                mainPage
                    .getCell("Address", 2)
                    .contains("48 Maracabo Place")
                    .should("exist");
                mainPage
                    .getCell("Address", 3)
                    .contains("44 Najafabad Way")
                    .should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : verify download CSV`, () => {
                mainPage.hideField("LastUpdate");
                const verifyCsv = (retrievedRecords) => {
                    // expected output, statically configured
                    let storedRecords = [
                        `Address,District,PostalCode,Phone`,
                        `669 Firozabad Loop,,92265,,[object Object],2,,Kanchrapara,`,
                        `48 Maracabo Place,,1570,,[object Object],2,,Tafuna,`,
                        `44 Najafabad Way,,61391,,[object Object],2,,Tambaram,`,
                        `381 Kabul Way,,87272,,[object Object],1,,Pudukkottai,`,
                    ];

                    for (let i = 0; i < storedRecords.length; i++) {
                        let strCol = storedRecords[i].split(",");
                        let retCol = retrievedRecords[i].split(",");
                        expect(strCol[0]).to.be.equal(retCol[0]);
                        expect(strCol[2]).to.be.equal(retCol[2]);
                        // expect(retrievedRecords[i]).to.be.equal(storedRecords[i])
                    }
                };

                // download & verify
                mainPage.downloadAndVerifyCsv(
                    `Address_exported_1.csv`,
                    verifyCsv
                );
                mainPage.unhideField("LastUpdate");
            });

            it(`Share ${viewType.toUpperCase()} view : Disable sort`, () => {
                // remove sort and validate
                mainPage.clearSort();
                mainPage
                    .getCell("Address", 1)
                    //ncv2@fixme
                    .contains("669 Firozabad Loop")
                    //.contains("217 Botshabelo Place")
                    .should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : Enable sort`, () => {
                // Sort menu operations (Country Column, Z->A)
                mainPage.sortField("Address", "Z → A");
                mainPage
                    .getCell("Address", 1)
                    .contains("669 Firozabad Loop")
                    .should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : Create Filter`, () => {
                // add filter & validate
                mainPage.filterField("Address", "is like", "drive");
                // wait for page rendering to complete
                cy.get(".nc-grid-row").should("have.length", 3);
                mainPage
                    .getCell("Address", 1)
                    .contains("1888 Kabul Drive")
                    .should("exist");
            });

            it(`Share ${viewType.toUpperCase()} view : verify download CSV after local filter`, () => {
                mainPage.hideField("LastUpdate");
                const verifyCsv = (retrievedRecords) => {
                    // expected output, statically configured
                    let storedRecords = [
                        `Address,District,PostalCode,Phone,Location,Customer List,Staff List,City,Staff List`,
                        `1888 Kabul Drive,,20936,,1,,Ife,,`,
                        `1661 Abha Drive,,14400,,1,,Pudukkottai,,`,
                    ];

                    // for (let i = 0; i < storedRecords.length; i++) {
                    //     expect(retrievedRecords[i]).to.be.equal(storedRecords[i])
                    // }

                    for (let i = 0; i < storedRecords.length; i++) {
                        let strCol = storedRecords[i].split(",");
                        let retCol = retrievedRecords[i].split(",");
                        expect(strCol[0]).to.be.equal(retCol[0]);
                        expect(strCol[2]).to.be.equal(retCol[2]);
                    }
                };
                mainPage.downloadAndVerifyCsv(
                    `Address_exported_1.csv`,
                    verifyCsv
                );
                mainPage.unhideField("LastUpdate");
            });

            it(`Share ${viewType.toUpperCase()} view : Delete Filter`, () => {
                // Remove sort and Validate
                mainPage.filterReset();
                mainPage
                    .getCell("Address", 1)
                    .contains("669 Firozabad Loop")
                    .should("exist");
            });

            it(`Share GRID view : Virtual column validation > has many`, () => {
                // verify column headers
                cy.get('[data-col="Customer List"]').should("exist");
                cy.get('[data-col="Staff List"]').should("exist");
                cy.get('[data-col="City"]').should("exist");
                cy.get('[data-col="Staff List"]').should("exist");

                // has many field validation
                mainPage
                    .getCell("Customer List", 3)
                    .click()
                    .find("button.mdi-close-thick")
                    .should("not.exist");
                mainPage
                    .getCell("Customer List", 3)
                    .click()
                    .find("button.mdi-plus")
                    .should("not.exist");
                mainPage
                    .getCell("Customer List", 3)
                    .click()
                    .find("button.mdi-arrow-expand")
                    .click();

                cy.getActiveModal(".nc-modal-child-list").find("button.mdi-reload").should("exist");
                cy.getActiveModal(".nc-modal-child-list")
                    .find("button")
                    .contains("Link to")
                    .should("not.exist");
                cy.getActiveModal(".nc-modal-child-list")
                    .find(".child-card")
                    .contains("2")
                    .should("exist");
                cy.getActiveModal(".nc-modal-child-list")
                    .find(".child-card")
                    .find("button")
                    .should("not.exist");
                cy.get("body").type("{esc}");
            });

            it(`Share GRID view : Virtual column validation > belongs to`, () => {
                // belongs to field validation
                mainPage
                    .getCell("City", 1)
                    .click()
                    .find("button.mdi-close-thick")
                    .should("not.exist");
                mainPage
                    .getCell("City", 1)
                    .click()
                    .find("button.mdi-arrow-expand")
                    .should("not.exist");
                mainPage
                    .getCell("City", 1)
                    .find(".v-chip")
                    .contains("al-Ayn")
                    .should("exist");
            });

            it(`Share GRID view : Virtual column validation > many to many`, () => {
                // many-to-many field validation
                mainPage
                    .getCell("Staff List", 1)
                    .click()
                    .find("button.mdi-close-thick")
                    .should("not.exist");
                mainPage
                    .getCell("Staff List", 1)
                    .click()
                    .find("button.mdi-plus")
                    .should("not.exist");
                mainPage
                    .getCell("Staff List", 1)
                    .click()
                    .find("button.mdi-arrow-expand")
                    .click();

                cy.getActiveModal(".nc-modal-child-list").find("button.mdi-reload").should("exist");
                cy.getActiveModal(".nc-modal-child-list")
                    .find("button")
                    .contains("Link to")
                    .should("not.exist");
                cy.get("body").type("{esc}");
            });

            it(`Delete ${viewType.toUpperCase()} view`, () => {
                // go back to base page
                cy.visit(storedURL, {
                    baseUrl: null,
                });
                cy.wait(5000);

                // number of view entries should be 2 before we delete
                cy.get(".nc-view-item").its("length").should("eq", 2);

                cy.get(".nc-view-delete-icon").eq(0).click({ force: true });
                cy.toastWait("View deleted successfully");

                // confirm if the number of veiw entries is reduced by 1
                cy.get(".nc-view-item").its("length").should("eq", 1);
            });
        };

        // below scenario's will be invoked twice, once for rest & then for graphql
        viewTest("grid");
    });

    describe(`${apiType.toUpperCase()} api - Grid view/ row-column update verification`, () => {
        before(() => {
            cy.fileHook();
            // Address table has belongs to, has many & many-to-many
            cy.openTableTab("Country", 25);

            cy.saveLocalStorage();
            // store base URL- to re-visit and delete form view later
            cy.url().then((url) => {
                storedURL = url;
                generateViewLink("rowColUpdate");
            });
        });

        after(() => {
            // close table
            cy.restoreLocalStorage();
            cy.visit(storedURL, {
                baseUrl: null,
            });
            cy.wait(5000);

            // delete row
            mainPage.getPagination(5).click();
            // kludge: flicker on load
            cy.wait(3000)

            // wait for page rendering to complete
            cy.get(".nc-grid-row").should("have.length", 10);
            mainPage
                .getRow(10)
                .find(".mdi-checkbox-blank-outline")
                .click({ force: true });
            mainPage.getCell("Country", 10).rightclick();
            cy.getActiveMenu(".nc-dropdown-grid-context-menu").contains("Delete Selected Row").click();

            // delete column
            cy.get(`th:contains('dummy') .mdi-menu-down`)
                .trigger("mouseover")
                .click();
            cy.get(".nc-column-delete").click();
            cy.get("button:contains(Confirm)").click();

            cy.toastWait("Update table successful");

            mainPage.deleteCreatedViews();

            // close table
            cy.closeTableTab("Country");
        });

        it(`Generate default Shared GRID view URL`, () => {
            // add row
            cy.get(".nc-add-new-row-btn").click();
            cy.get("#data-table-form-Country > input")
                .first()
                .click()
                .type("a");
            cy.contains("Save row").filter("button").click({ force: true });
            cy.toastWait("updated successfully");

            // add column
            mainPage.addColumn("dummy", "Country");

            // visit public view
            cy.log(viewURL["rowColUpdate"]);
            cy.restoreLocalStorage();
            cy.visit(viewURL["rowColUpdate"], {
                baseUrl: null,
            });
            cy.wait(5000);

            //5
            // wait for public view page to load!
            // wait for page rendering to complete
            cy.get(".nc-grid-row").should("have.length", 25);
        });

        it(`Share GRID view : new row visible`, () => {
            // verify row
            cy.get(`.v-pagination > li:contains('5') button`).click();
            // wait for page rendering to complete
            cy.get(".nc-grid-row").should("have.length", 10);
            mainPage.getCell("Country", 10).contains("a").should("exist");
        });

        it.skip(`Share GRID view : new column visible`, () => {
            // verify column headers
            cy.get('[data-col="dummy"]').should("exist");
        });
    });
};

/**
 * @copyright Copyright (c) 2021, Xgene Cloud Ltd
 *
 * @author Pranav C Balan <pranavxc@gmail.com>
 * @author Raju Udava <sivadstala@gmail.com>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */