"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelerHomePage = void 0;
const test_1 = require("@playwright/test");
const sleep_1 = require("../../utils/sleep");
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
class ModelerHomePage {
    defaultFolderName = 'Cross Component Test Project';
    page;
    modelerPageBanner;
    createNewProjectButton;
    projectNameInput;
    formNameInput;
    chooseBpmnTemplateButton;
    diagramTypeDropdown;
    bpmnTemplateOption;
    formTemplateOption;
    idpTemplateOption;
    idpApplicationNameInput;
    createIdpApplicationButton;
    projectBreadcrumb;
    openOrganizationsButton;
    optionsButton;
    manageButton;
    crossComponentProjectFolder;
    homeBreadcrumb;
    rows;
    uploadFilesButton;
    dialog;
    messageBanner;
    closeButton;
    formNameBreadcrumb;
    constructor(page) {
        this.page = page;
        this.modelerPageBanner = page.getByRole('banner', {
            name: 'Camunda Modeler',
        });
        this.createNewProjectButton = page.getByRole('button', {
            name: 'New project',
        });
        this.projectNameInput = page.locator('[data-test="editable-input"]');
        this.formNameInput = page.locator('[data-test="editable-input"]');
        this.idpApplicationNameInput = page.getByPlaceholder('New IDP Application');
        this.createIdpApplicationButton = page.getByRole('button', {
            name: 'Create',
            exact: true,
        });
        this.chooseBpmnTemplateButton = page.getByRole('button', {
            name: 'Choose BPMN template',
        });
        this.diagramTypeDropdown = page.locator('[data-test="diagram-dropdown"]');
        this.bpmnTemplateOption = page
            .locator('[data-test="create-bpmn-diagram"]')
            .getByText('BPMN Diagram');
        this.formTemplateOption = page
            .locator('[data-test="create-form"]')
            .getByText('Form');
        this.idpTemplateOption = page
            .locator('[data-test="create-idp-application"]')
            .getByText('IDP Application');
        this.projectBreadcrumb = page.locator('[data-test="breadcrumb-project"]');
        this.homeBreadcrumb = page.locator('[data-test="breadcrumb-home"]');
        this.openOrganizationsButton = page.getByLabel('Open Organizations');
        this.manageButton = page.getByRole('menuitem', { name: 'Manage' });
        this.crossComponentProjectFolder = page
            .getByTitle(this.defaultFolderName, {
            exact: true,
        })
            .first();
        this.rows = page.getByRole('row');
        this.uploadFilesButton = page.getByRole('menuitem', { name: 'Upload files' });
        this.dialog = page.getByRole('dialog');
        this.messageBanner = page.locator('[data-test="close-top-banner"]');
        this.closeButton = page.getByRole('button', { name: 'Got it - Dismiss' });
        this.optionsButton = page.getByRole('button', { name: 'Options' });
        this.formNameBreadcrumb = (formName) => page.locator('button[data-test="breadcrumb-form"]', {
            hasText: formName,
        });
    }
    async dismissOverlays() {
        for (const locator of [
            this.closeButton,
            this.page.getByRole('button', { name: 'Close' }).first(),
            this.messageBanner,
        ]) {
            await locator
                .waitFor({ state: 'visible', timeout: 3000 })
                .then(() => locator.click())
                .catch(() => { });
        }
    }
    async clickCreateNewProjectButton() {
        await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.createNewProjectButton, {
            preAction: async () => {
                await this.dismissOverlays();
            },
            totalTimeout: 120000,
            visibilityTimeout: 10000,
        });
    }
    async enterNewProjectName(name) {
        await this.projectNameInput.click({ timeout: 60000 });
        await this.projectNameInput.fill(name);
        await this.projectNameInput.press('Enter');
    }
    async enterIdpApplicationName(name) {
        await this.idpApplicationNameInput.click({ timeout: 60000 });
        await this.idpApplicationNameInput.fill(name);
    }
    async selectCluster(clusterName) {
        //Select the correct cluster if multiple exist
        const cluster = this.dialog.getByText(clusterName);
        await (0, test_1.expect)(cluster).toBeVisible({
            timeout: 30000,
        });
        await cluster.click();
        await (0, test_1.expect)(this.dialog
            .locator('label')
            .filter({
            hasText: clusterName,
        })
            .getByRole('switch')).toBeChecked({ timeout: 30000 });
        //Check healthy status of the selected cluster
        const regex = new RegExp(`${clusterName}.*?HealthydevManage`);
        await (0, test_1.expect)(this.dialog).toHaveText(regex, {
            timeout: 120000,
        });
    }
    async createForm(formName) {
        await this.clickDiagramTypeDropdown();
        await this.clickFormOption();
        await this.enterFormName(formName);
        await (0, sleep_1.sleep)(10000);
    }
    async clickCreateIdpApplicationButton() {
        await this.createIdpApplicationButton.click();
    }
    async clickChooseBpmnTemplateButton() {
        await this.chooseBpmnTemplateButton.click();
    }
    async reload() {
        await this.page.reload();
    }
    async getProjectNames(name) {
        return this.rows
            .filter({ hasText: name })
            .getByTitle(name)
            .evaluateAll((elements) => elements
            .map((el) => el.textContent || '')
            .filter((text) => text !== ''));
    }
    async clickProcessDiagram(name) {
        const process = this.rows.filter({ hasText: name }).getByTitle(name).first();
        await (0, test_1.expect)(process).toBeVisible({ timeout: 90000 });
        await process.click();
    }
    async clickDiagramTypeDropdown() {
        await (0, test_1.expect)(this.diagramTypeDropdown).toBeVisible({
            timeout: 60000,
        });
        await this.diagramTypeDropdown.click({ timeout: 120000 });
    }
    async clickBpmnTemplateOption() {
        try {
            await this.bpmnTemplateOption.click({ timeout: 120000 });
        }
        catch {
            // Element may be detaching during re-render; wait briefly then force-click
            await this.page.waitForTimeout(3000);
            await this.bpmnTemplateOption.click({ force: true, timeout: 60000 });
        }
    }
    async clickIdpApplicationTemplateOption() {
        await this.idpTemplateOption.click({ timeout: 120000 });
    }
    async clickFormOption() {
        await this.formTemplateOption.click();
    }
    async enterFormName(name) {
        await this.formNameInput.click({ timeout: 60000 });
        await this.formNameInput.fill(name);
        await this.formNameInput.press('Enter');
    }
    async clickProjectBreadcrumb() {
        await this.projectBreadcrumb.click({ timeout: 60000 });
    }
    async clickHomeBreadcrumb() {
        try {
            await this.homeBreadcrumb.click();
        }
        catch (error) {
            await this.page.getByText('Home', { exact: true }).first().click();
        }
    }
    async clickOpenOrganizationsButton() {
        await (0, sleep_1.sleep)(5000);
        await (0, test_1.expect)(this.openOrganizationsButton).toBeVisible({
            timeout: 10000,
        });
        await this.openOrganizationsButton.click({ timeout: 30000 });
    }
    async clickCrossComponentProjectFolder() {
        await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.crossComponentProjectFolder, {
            preAction: async () => {
                try {
                    const blockingModal = this.page.locator('.cds--modal.is-visible');
                    if ((await blockingModal.count()) > 0) {
                        await this.page.keyboard.press('Escape');
                        await (0, sleep_1.sleep)(1000);
                    }
                }
                catch {
                    // No blocking modal to dismiss
                }
                await this.clickMessageBanner();
            },
        });
    }
    async createCrossComponentProjectFolder() {
        await (0, sleep_1.sleep)(15000);
        await this.dismissOverlays();
        if (await this.crossComponentProjectFolder.isVisible()) {
            console.log('Cross Component Project folder already exists. Clicking into it');
            await this.clickCrossComponentProjectFolder();
            return;
        }
        await this.clickCreateNewProjectButton();
        await this.enterNewProjectName(this.defaultFolderName);
    }
    async clickManageButton(retries = 3) {
        await this.optionsButton.click({ timeout: 30000 });
        for (let i = 0; i < retries; i++) {
            try {
                await (0, sleep_1.sleep)(5000);
                if (await this.manageButton.isVisible({ timeout: 30000 })) {
                    await this.manageButton.click({ timeout: 10000 });
                }
                else {
                    await this.clickOpenOrganizationsButton();
                    await this.optionsButton.click({ timeout: 30000 });
                    await (0, test_1.expect)(this.manageButton).toBeVisible({ timeout: 30000 });
                    await this.manageButton.click({ timeout: 30000 });
                }
                // Wait for the Console org management page to finish loading
                await this.page
                    .waitForLoadState('networkidle', { timeout: 30000 })
                    .catch(() => { });
                return;
            }
            catch (error) {
                console.error(`Attempt ${i + 1} to click manage button failed: ${error}`);
                await (0, sleep_1.sleep)(10000);
            }
        }
        throw new Error(`Failed to click manage button after ${retries} retries`);
    }
    async clickUploadFilesButton() {
        await this.uploadFilesButton.click({ timeout: 60000 });
    }
    async clickMessageBanner() {
        try {
            await Promise.race([
                this.messageBanner.click(),
                this.closeButton.click({ timeout: 30000 }),
            ]);
        }
        catch {
            console.log('No additional banner or close button found to click');
        }
    }
    async assertFormBreadcrumbVisible(formName) {
        await (0, test_1.expect)(this.formNameBreadcrumb(formName)).toBeVisible({
            timeout: 120000,
        });
    }
    /**
     * Handles navigation after clicking an invitation link in email.
     *
     * The invited user follows the link while logged out, so the invitation flow
     * presents the Auth0 login. Completing the login ON the invitation flow lets
     * SaaS accept the invite and land the user directly in the SHARED org's
     * Modeler, where the shared project is listed.
     *
     * We deliberately do NOT clear cookies and re-login via the app switcher:
     * that path authenticates into the user's PERSONAL org, where the shared
     * project does not exist and the folder can never appear — the previous
     * fallback raced a 15s window and, whenever the (normal) login + invite-accept
     * redirect chain took longer, dropped into that personal-org path and hung.
     *
     * If the link auto-authenticated (the banner is already up), no login is
     * needed. The redirect chain routinely takes longer than a few seconds, so
     * wait generously for the banner instead of racing a short window.
     */
    async navigateAfterInvitationLink(loginPage, credentials) {
        // If the invitation flow shows the Auth0 login, authenticate in place so
        // the invite is accepted in the shared-org context. If it doesn't appear,
        // the link already auto-authenticated us and we skip straight to the banner.
        const onLogin = await loginPage.usernameInput
            .waitFor({ state: 'visible', timeout: 60000 })
            .then(() => true)
            .catch(() => false);
        if (onLogin) {
            await loginPage.fillUsername(credentials.username);
            await loginPage.clickContinueButton();
            await loginPage.fillPassword(credentials.password);
            await loginPage.clickLoginButton();
        }
        await (0, test_1.expect)(this.modelerPageBanner).toBeVisible({ timeout: 180000 });
        try {
            await this.clickHomeBreadcrumb();
        }
        catch {
            // Already on the Modeler home page
        }
        await (0, test_1.expect)(this.modelerPageBanner).toBeVisible({ timeout: 30000 });
    }
}
exports.ModelerHomePage = ModelerHomePage;
