"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AppsPage = void 0;
const test_1 = require("@playwright/test");
const sleep_1 = require("../../utils/sleep");
const UtilitiesPage_1 = require("../8.8/UtilitiesPage");
class AppsPage {
    page;
    modelerLink;
    tasklistLink;
    identityLink;
    operateLink;
    optimizeButton;
    identityButton;
    tasklistButton;
    operateButton;
    operateListItem;
    identityListItem;
    optimizeListItem;
    tasklistListItem;
    appSwitcherButton;
    optimizeLink;
    consoleLink;
    camundaComponentsButton;
    camundaAppsButton;
    constructor(page) {
        this.page = page;
        this.modelerLink = page.getByRole('link', { name: 'Modeler', exact: true });
        this.appSwitcherButton = page.getByLabel('App Switcher');
        this.tasklistLink = page.getByRole('link', { name: 'Tasklist', exact: true });
        this.identityLink = page.getByRole('link', { name: /^(Admin|Identity)$/ });
        this.operateLink = page.getByRole('link', { name: 'Operate', exact: true });
        this.optimizeLink = page.getByRole('link', { name: 'Optimize', exact: true });
        this.consoleLink = page.getByRole('link', { name: 'Console', exact: true });
        this.camundaComponentsButton = page.getByLabel('Camunda components');
        this.camundaAppsButton = page.getByLabel('Camunda apps');
        this.tasklistListItem = this.page
            .getByRole('listitem')
            .filter({ hasText: 'Tasklist' });
        this.optimizeListItem = this.page
            .getByRole('listitem')
            .filter({ hasText: 'Optimize' });
        this.operateListItem = this.page
            .getByRole('listitem')
            .filter({ hasText: 'Operate' });
        this.identityListItem = this.page
            .getByRole('listitem')
            .filter({ hasText: /Admin|Identity/ }); // Identity Should be removed after https://github.com/camunda/camunda/issues/46447 is fixed
        this.operateButton = page.getByRole('button', {
            name: 'Operate',
            exact: true,
        });
        this.optimizeButton = page.getByRole('button', {
            name: 'Optimize',
            exact: true,
        });
        this.tasklistButton = page.getByRole('button', {
            name: 'Tasklist',
            exact: true,
        });
        this.identityButton = page.getByRole('button', {
            name: /^(Admin|Identity)$/, // Identity Should be removed after https://github.com/camunda/camunda/issues/46447 is fixed
        });
    }
    async clickCluster(component, name) {
        const cluster = component.getByRole('link', { name: name, exact: true });
        await (0, test_1.expect)(cluster).toBeVisible({ timeout: 60000 });
        await cluster.click();
    }
    async clickModeler() {
        const maxRetries = 5;
        const modelerBanner = this.page.getByRole('banner', {
            name: 'Camunda Modeler',
        });
        const modelerDiagramDropdown = this.page.locator('[data-test="diagram-dropdown"]');
        // If the click is already done and we are sitting on Modeler, return
        // immediately — observed in failing runs where the banner role lookup
        // never resolves because partial app.js 429s prevent the accessible
        // name from being set, even though the project list rendered.
        if (this.page.url().includes('modeler.')) {
            return;
        }
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                await this.clickCamundaApps();
                await (0, test_1.expect)(this.modelerLink).toBeVisible({ timeout: 30000 });
                await this.modelerLink.click({ timeout: 30000 });
                // Primary success signal: the browser actually landed on the
                // Modeler hostname. Some Modeler renders never expose the banner
                // accessible name when modeler asset requests get 429-throttled
                // by SaaS infra, but the URL transition is reliable.
                await this.page.waitForURL((url) => url.hostname.includes('modeler.'), {
                    timeout: 90000,
                });
                // Best-effort: also wait briefly for the banner or the project
                // dropdown so the caller's next interaction has a stable DOM.
                // Tolerate this timing out — the URL is already correct.
                await Promise.race([
                    modelerBanner.waitFor({ state: 'visible', timeout: 30000 }),
                    modelerDiagramDropdown.waitFor({ state: 'visible', timeout: 30000 }),
                ]).catch(() => { });
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                if (this.page.url().includes('modeler.')) {
                    // Click registered and navigation actually happened — accept it
                    // even though banner/dropdown took too long to settle.
                    return;
                }
                if (!this.page.isClosed()) {
                    await this.page
                        .waitForLoadState('domcontentloaded', { timeout: 20000 })
                        .catch(() => { });
                    await this.page.reload({ waitUntil: 'domcontentloaded' });
                }
                await (0, sleep_1.sleep)(5000);
            }
        }
        throw new Error(`Failed to click the modeler link after ${maxRetries} attempts.`);
    }
    async clickTasklist(clusterName) {
        const maxRetries = 5;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    //Single cluster
                    if (await this.tasklistLink.isVisible({ timeout: 5000 })) {
                        await this.tasklistLink.click({ timeout: 10000 });
                    }
                    else {
                        //Multiple clusters
                        await this.doClickClusterInTasklist(clusterName);
                    }
                }
                else {
                    await this.clickCamundaApps();
                    await (0, UtilitiesPage_1.waitForLoadingToFinish)(this.page);
                    if (await this.tasklistLink.isVisible({ timeout: 5000 })) {
                        await this.tasklistLink.click({ timeout: 10000 });
                    }
                    else {
                        await this.doClickClusterInTasklist(clusterName);
                    }
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await this.page.waitForLoadState('domcontentloaded');
                if (!this.page.isClosed()) {
                    await this.page.reload();
                }
                await (0, sleep_1.sleep)(20000);
            }
        }
        throw new Error(`Failed to click the tasklist link after ${maxRetries} attempts.`);
    }
    async clickIdentity(clusterName) {
        const maxRetries = 5;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                await this.clickCamundaApps();
                await (0, sleep_1.sleep)(3000);
                if (await this.identityLink.isVisible({ timeout: 5000 })) {
                    await this.identityLink.click({ timeout: 10000 });
                }
                else {
                    //Multiple clusters
                    await this.doClickClusterInIdentity(clusterName);
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await (0, UtilitiesPage_1.waitForLoadingToFinish)(this.page);
                if (!this.page.isClosed()) {
                    await this.page.reload({ waitUntil: 'domcontentloaded' });
                }
                await (0, sleep_1.sleep)(20000);
            }
        }
        throw new Error(`Failed to click the Identity link after ${maxRetries} attempts.`);
    }
    async doClickClusterInOperate(clusterName) {
        if (await this.operateListItem
            .getByRole('button', {
            expanded: true,
        })
            .isHidden({ timeout: 5000 })) {
            await this.operateButton.click({ timeout: 10000 });
        }
        await this.clickCluster(this.operateListItem, clusterName);
    }
    async doClickClusterInTasklist(clusterName) {
        if (await this.tasklistListItem
            .getByRole('button', {
            expanded: true,
        })
            .isHidden({ timeout: 5000 })) {
            await this.tasklistButton.click({ timeout: 10000 });
        }
        await this.clickCluster(this.tasklistListItem, clusterName);
    }
    async doClickClusterInIdentity(clusterName) {
        if (await this.identityListItem
            .getByRole('button', {
            expanded: true,
        })
            .isHidden({ timeout: 5000 })) {
            await this.identityButton.click({ timeout: 30000 });
        }
        await this.clickCluster(this.identityListItem, clusterName);
    }
    async doClickClusterInOptimize(clusterName) {
        if (await this.optimizeListItem
            .getByRole('button', {
            expanded: true,
        })
            .isHidden({ timeout: 5000 })) {
            await this.optimizeButton.click({ timeout: 10000 });
        }
        await this.clickCluster(this.optimizeListItem, clusterName);
    }
    async clickOperate(clusterName) {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    if (await this.operateLink.isVisible({ timeout: 5000 })) {
                        //Single Cluster
                        await this.operateLink.click({ timeout: 10000 });
                    }
                    else {
                        //Multiple Cluster
                        await this.doClickClusterInOperate(clusterName);
                    }
                }
                else {
                    await this.clickCamundaApps();
                    if (await this.operateLink.isVisible({ timeout: 5000 })) {
                        await this.operateLink.click({ timeout: 10000 });
                    }
                    else {
                        await this.doClickClusterInOperate(clusterName);
                    }
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await this.page.waitForLoadState('domcontentloaded');
                if (!this.page.isClosed()) {
                    await this.page.reload();
                }
                await (0, sleep_1.sleep)(20000);
            }
        }
        throw new Error(`Failed to click the operate link after ${maxRetries} attempts.`);
    }
    async clickOptimize(clusterName) {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    if (await this.optimizeLink.isVisible({ timeout: 10000 })) {
                        //Single cluster
                        await this.optimizeLink.click({ timeout: 10000 });
                    }
                    else {
                        //Multiple clusters
                        await this.doClickClusterInOptimize(clusterName);
                    }
                }
                else {
                    await this.clickCamundaApps();
                    if (await this.optimizeLink.isVisible({ timeout: 5000 })) {
                        await this.optimizeLink.click({ timeout: 10000 });
                    }
                    else {
                        await this.doClickClusterInOptimize(clusterName);
                    }
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await this.page.waitForLoadState('domcontentloaded');
                if (!this.page.isClosed()) {
                    await this.page.reload();
                }
                await (0, sleep_1.sleep)(20000);
            }
        }
        throw new Error(`Failed to click the optimize link after ${maxRetries} attempts.`);
    }
    async clickCamundaApps(maxRetries = 3) {
        await (0, sleep_1.sleep)(2000);
        const appButtons = [
            this.camundaComponentsButton,
            this.camundaAppsButton,
            this.appSwitcherButton,
        ];
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                await this.dismissBlockingModal();
                for (const appButton of appButtons) {
                    if (await appButton.isVisible({ timeout: 5000 }).catch(() => false)) {
                        await appButton.click({ timeout: 30000 });
                        return;
                    }
                }
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed while opening app switcher: ${error}`);
            }
            await this.dismissBlockingModal();
            await (0, sleep_1.sleep)(2000);
        }
        throw new Error(`Failed to open app switcher after ${maxRetries} attempts.`);
    }
    async dismissBlockingModal() {
        const visibleModal = this.page.locator('.cds--modal.is-visible').first();
        if (!(await visibleModal.isVisible().catch(() => false))) {
            return;
        }
        await this.page.keyboard.press('Escape').catch(() => { });
        await this.page
            .getByRole('button', { name: 'Close' })
            .last()
            .click({ timeout: 3000, force: true })
            .catch(() => { });
        await this.page
            .getByRole('button', { name: 'Got it - Dismiss' })
            .last()
            .click({ timeout: 3000, force: true })
            .catch(() => { });
        await this.page
            .getByRole('button', { name: 'Skip customization' })
            .last()
            .click({ timeout: 3000, force: true })
            .catch(() => { });
    }
    async clickConsoleLink() {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                if (retries === 0) {
                    await (0, test_1.expect)(this.consoleLink).toBeVisible({ timeout: 30000 });
                    await this.consoleLink.click();
                }
                else {
                    await this.clickCamundaApps();
                    await (0, test_1.expect)(this.consoleLink).toBeVisible({ timeout: 30000 });
                    await this.consoleLink.click();
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to click the console link after ${maxRetries} attempts.`);
    }
    async assertOperatePresent(shouldBeVisible = true) {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                const isVisible = await this.operateLink.isVisible({ timeout: 5000 });
                if (shouldBeVisible) {
                    if (isVisible) {
                        // Single Cluster
                        await (0, test_1.expect)(this.operateLink).toBeVisible();
                    }
                    else if (await this.operateListItem
                        .getByRole('button', { expanded: true })
                        .isHidden({ timeout: 5000 })) {
                        // Multiple Cluster
                        await (0, test_1.expect)(this.operateButton).toBeVisible();
                    }
                }
                else {
                    await (0, test_1.expect)(this.operateLink).not.toBeVisible();
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to assert the operate link visibility after ${maxRetries} attempts.`);
    }
    async assertTasklistPresent(shouldBeVisible = true) {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                const isVisible = await this.tasklistLink.isVisible({ timeout: 5000 });
                if (shouldBeVisible) {
                    if (isVisible) {
                        // Single Cluster
                        await (0, test_1.expect)(this.tasklistLink).toBeVisible();
                    }
                    else if (await this.tasklistListItem
                        .getByRole('button', { expanded: true })
                        .isHidden({ timeout: 5000 })) {
                        // Multiple Cluster
                        await (0, test_1.expect)(this.tasklistButton).toBeVisible();
                    }
                }
                else {
                    await (0, test_1.expect)(this.tasklistLink).not.toBeVisible();
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to assert the tasklist link visibility after ${maxRetries} attempts.`);
    }
    async assertOptimizePresent(shouldBeVisible = true) {
        const maxRetries = 3;
        for (let retries = 0; retries < maxRetries; retries++) {
            try {
                const isVisible = await this.optimizeLink.isVisible({ timeout: 5000 });
                if (shouldBeVisible) {
                    if (isVisible) {
                        // Single Cluster
                        await (0, test_1.expect)(this.optimizeLink).toBeVisible();
                    }
                    else if (await this.optimizeListItem
                        .getByRole('button', { expanded: true })
                        .isHidden({ timeout: 5000 })) {
                        // Multiple Cluster
                        await (0, test_1.expect)(this.optimizeButton).toBeVisible();
                    }
                }
                else {
                    await (0, test_1.expect)(this.optimizeLink).not.toBeVisible();
                }
                return;
            }
            catch (error) {
                console.warn(`Click attempt ${retries + 1} failed: ${error}`);
                await new Promise((resolve) => setTimeout(resolve, 10000));
            }
        }
        throw new Error(`Failed to assert the optimize link visibility after ${maxRetries} attempts.`);
    }
}
exports.AppsPage = AppsPage;
