"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModelerHomePage = void 0;
const test_1 = require("@playwright/test");
const expectLocatorWithRetry_1 = require("../../utils/assertionHelpers/expectLocatorWithRetry");
class ModelerHomePage {
    page;
    defaultFolderName = 'Cross Component Test Project';
    modelerPageBanner;
    createNewProjectButton;
    projectNameInput;
    chooseBpmnTemplateButton;
    diagramTypeDropdown;
    bpmnTemplateOption;
    formTemplateOption;
    projectBreadcrumb;
    openOrganizationsButton;
    manageButton;
    crossComponentProjectFolder;
    homeBreadcrumb;
    formNameInput;
    rows;
    licenseKeyTagNonProduction;
    licenseKeyTagNonCommercial;
    licenseKeyTagProduction;
    licenseKeyTagCommercial;
    uploadFilesButton;
    messageBanner;
    closeButton;
    modalCloseButton;
    constructor(page) {
        this.page = page;
        this.modelerPageBanner = page
            .locator('a')
            .filter({ hasText: 'Camunda logoModeler' });
        this.createNewProjectButton = page
            .getByRole('button', {
            name: 'Create new project',
        })
            .or(page.getByRole('button', {
            name: 'New project',
        }));
        this.projectNameInput = page.locator('[data-test="editable-input"]');
        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.projectBreadcrumb = page.locator('[data-test="breadcrumb-project"]');
        this.openOrganizationsButton = page.getByLabel('Open Organizations');
        this.manageButton = page.getByRole('button', { name: 'Manage' });
        this.crossComponentProjectFolder = page
            .getByTitle(this.defaultFolderName, {
            exact: true,
        })
            .first();
        this.homeBreadcrumb = page.locator('[data-test="breadcrumb-home"]');
        this.formNameInput = page.locator('[data-test="editable-input"]');
        this.rows = page.getByRole('row');
        this.licenseKeyTagNonProduction = page
            .getByText('Non-production license')
            .first();
        this.licenseKeyTagNonCommercial = page.getByText('Non-commercial license');
        this.licenseKeyTagProduction = page.getByText('Production license').first();
        this.licenseKeyTagCommercial = page.getByText('Commercial license');
        this.uploadFilesButton = page.getByRole('menuitem', { name: 'Upload files' });
        this.messageBanner = page.locator('[data-test="close-top-banner"]');
        this.closeButton = page.getByRole('button', { name: 'Got it - Dismiss' });
        this.modalCloseButton = page.locator('.cds--modal.is-visible .cds--modal-close');
    }
    async clickCreateNewProjectButton() {
        await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.createNewProjectButton, {
            totalTimeout: 30000,
        });
        // Modals (WhatsNew, "BPMN conditional events", etc.) render lazily after
        // page load and intercept clicks on the button underneath. Dismiss them.
        await this.closeButton
            .waitFor({ state: 'visible', timeout: 5000 })
            .then(() => this.closeButton.click())
            .catch(() => { });
        await this.modalCloseButton
            .waitFor({ state: 'visible', timeout: 2000 })
            .then(() => this.modalCloseButton.click())
            .catch(() => { });
        await this.createNewProjectButton.click();
    }
    async enterNewProjectName(name) {
        await (0, test_1.expect)(this.projectNameInput).toBeVisible({ timeout: 10000 });
        await this.projectNameInput.click({ timeout: 60000 });
        await this.projectNameInput.fill(name);
        await this.projectNameInput.press('Enter');
    }
    // Wait for the Modeler project workspace to become interactive. The caller
    // arrives here via goToModeler(), which has already loaded and authenticated
    // the app shell (banner visible). The nav banner mounts before the project
    // list, which renders after an API round-trip, so gate on an actionable
    // element — the "Create new project" button or an existing project folder —
    // rather than the banner, which otherwise lets the caller proceed against a
    // half-loaded shell and time out clicking "Create new project".
    //
    // Deliberately does NOT reload: a raw page.reload() drops the authenticated
    // SPA state (goToModeler handles the OAuth redirect flow; reload does not),
    // which lands on a blank page and makes the workspace element unreachable for
    // the rest of the timeout. Transient upstream 50x is already absorbed by
    // goToModeler's gateway-error re-navigation before we get here.
    async waitForModelerReady(timeoutMs = 120000) {
        // .first(): when the project folder already exists on the shared cluster,
        // both the create-project button and the folder are present, so the .or()
        // resolves to multiple elements — waitFor() requires a single match.
        await this.createNewProjectButton
            .or(this.crossComponentProjectFolder)
            .first()
            .waitFor({ state: 'visible', timeout: timeoutMs });
    }
    async createCrossComponentProjectFolder() {
        // After a fresh user login (e.g. lisa, bart) the Modeler pod may still be
        // initialising or returning transient 503s. Poll until the app shell banner
        // is visible before interacting with the project list.
        const maxAttempts = 3;
        const retryWaitMs = 5000;
        for (let attempt = 0; attempt < maxAttempts; attempt++) {
            try {
                await this.waitForModelerReady();
                await this.clickMessageBanner();
                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);
                await (0, test_1.expect)(this.page.getByRole('heading', { name: this.defaultFolderName })).toBeVisible({ timeout: 10000 });
                return;
            }
            catch (error) {
                if (attempt < maxAttempts - 1) {
                    console.log(`createCrossComponentProjectFolder attempt ${attempt + 1} failed. Reloading and retrying...`);
                    await this.page.reload({ waitUntil: 'domcontentloaded' });
                    await this.page.waitForTimeout(retryWaitMs);
                }
                else {
                    throw error;
                }
            }
        }
    }
    async clickCrossComponentProjectFolder() {
        let attempts = 0;
        const maxAttempts = 3;
        const timeout = 60000;
        while (attempts < maxAttempts) {
            try {
                await this.clickMessageBanner();
                await (0, test_1.expect)(this.crossComponentProjectFolder).toBeVisible({ timeout });
                // The WhatsNew modal renders lazily after page load and intercepts clicks.
                // Explicitly wait for it to appear (up to 5s), dismiss it, then click.
                await this.closeButton
                    .waitFor({ state: 'visible', timeout: 5000 })
                    .then(() => this.closeButton.click())
                    .catch(() => { });
                await this.modalCloseButton
                    .waitFor({ state: 'visible', timeout: 2000 })
                    .then(() => this.modalCloseButton.click())
                    .catch(() => { });
                await this.crossComponentProjectFolder.click();
                await this.clickMessageBanner();
                return;
            }
            catch (error) {
                attempts++;
                if (attempts < maxAttempts) {
                    console.log(`Attempt ${attempts} failed. Reloading page and retrying...`);
                    await this.page.reload();
                    await this.page.waitForLoadState('networkidle');
                }
                else {
                    throw new Error('Failed to click crossComponentProjectFolder after 3 attempts.');
                }
            }
        }
    }
    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 clickHomeBreadcrumb() {
        try {
            await this.homeBreadcrumb.click();
        }
        catch (error) {
            await this.page.getByText('Home', { exact: true }).first().click();
        }
    }
    async clickChooseBpmnTemplateButton() {
        await this.chooseBpmnTemplateButton.click();
    }
    async clickDiagramTypeDropdown() {
        await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.diagramTypeDropdown, {
            postAction: async () => {
                await this.page.reload();
            },
        });
        await this.diagramTypeDropdown.click();
    }
    async clickBpmnTemplateOption() {
        await (0, test_1.expect)(this.bpmnTemplateOption).toBeVisible({ timeout: 60000 });
        await this.bpmnTemplateOption.click({ timeout: 60000 });
    }
    async clickFormOption() {
        await this.formTemplateOption.click();
    }
    async enterFormName(name) {
        await (0, test_1.expect)(this.formNameInput).toBeVisible({ timeout: 10000 });
        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 clickOpenOrganizationsButton() {
        await this.openOrganizationsButton.click({ timeout: 30000 });
    }
    async clickManageButton() {
        await this.manageButton.click({ timeout: 30000 });
    }
    async clickUploadFilesButton() {
        await this.uploadFilesButton.click({ timeout: 60000 });
    }
    async clickMessageBanner() {
        try {
            const banner = this.messageBanner
                .or(this.closeButton)
                .or(this.modalCloseButton);
            await banner.waitFor({ state: 'visible', timeout: 5000 });
            await banner.click();
        }
        catch {
            console.log('No banner or close button found to click');
        }
    }
}
exports.ModelerHomePage = ModelerHomePage;
