"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClusterDetailsPage = void 0;
const test_1 = require("@playwright/test");
const sleep_1 = require("../../utils/sleep");
const clickLocatorWithRetry_1 = require("../../utils/assertionHelpers/clickLocatorWithRetry");
const expectLocatorWithRetry_1 = require("../../utils/assertionHelpers/expectLocatorWithRetry");
const ClientCredentialsDetailsPage_1 = require("./ClientCredentialsDetailsPage");
class ClusterDetailsPage {
    page;
    apiTab;
    createFirstClientButton;
    clientNameTextbox;
    tasklistCheckbox;
    secretsCheckbox;
    optimizeCheckbox;
    operateCheckbox;
    createButton;
    closeModalButton;
    createClientButton;
    settingsTab;
    rbaEnableButton;
    rbaDisableButton;
    dialog;
    deleteButton;
    deleteSubButton;
    createClientCredentialsDialog;
    clientCredentialsDialog;
    clustersLink;
    alertsTab;
    alertsList;
    createFirstAlertButton;
    createNewAlertButton;
    emailRadioButton;
    createAlertsDialog;
    createAlertButton;
    createNewClientButton;
    clientsList;
    envVarsTab;
    zeebeCheckbox;
    apiClientNameTextbox;
    expandButton;
    rbaEnabledMessage;
    authorizationsHeading;
    orchestrationClusterCheckbox;
    clientCredentialsLink;
    reviewUpdateButton;
    updateAvailableDialog;
    updateButton;
    mcpSupportToggle;
    mcpTab;
    mcpTextarea;
    constructor(page) {
        this.page = page;
        this.apiTab = page.getByRole('tab', { name: 'API' });
        this.createFirstClientButton = page.getByRole('button', {
            name: 'Create your first Client',
        });
        this.clientNameTextbox = page.getByRole('textbox', { name: 'Client Name' });
        this.tasklistCheckbox = page
            .getByRole('dialog')
            .locator('label')
            .filter({ hasText: 'Tasklist' });
        this.optimizeCheckbox = page
            .getByRole('dialog')
            .locator('label')
            .filter({ hasText: /^Optimize API$/ });
        this.operateCheckbox = page
            .getByRole('dialog')
            .locator('label')
            .filter({ hasText: 'Operate' });
        this.secretsCheckbox = page
            .getByRole('dialog')
            .locator('label')
            .filter({ hasText: /^Administration API - Resource: Secrets$/ });
        this.createButton = page.getByRole('button', { name: 'Create', exact: true });
        this.createClientButton = page.getByRole('button', {
            name: 'Create new Client',
        });
        this.settingsTab = page.getByRole('tab', { name: 'Settings' });
        this.rbaEnableButton = page.getByRole('button', { name: 'Enable' });
        this.rbaDisableButton = page.getByRole('button', { name: 'Disable' });
        this.dialog = page.getByRole('dialog');
        this.deleteButton = page.getByRole('button', { name: 'Delete' });
        this.deleteSubButton = page.getByRole('button', {
            name: 'danger Delete',
        });
        this.createClientCredentialsDialog = page.getByRole('dialog', {
            name: 'Create new client credentials',
        });
        // Use a content-based locator so the test stays robust if the dialog
        // title is ever renamed in the Console UI.
        this.clientCredentialsDialog = page.getByRole('dialog').filter({
            has: page.getByText('The Client Secret will not be shown again.'),
        });
        this.closeModalButton = this.clientCredentialsDialog.getByLabel('Close');
        this.clustersLink = page
            .getByRole('banner')
            .getByRole('link', { name: 'Clusters' });
        this.alertsTab = page.getByRole('tab', { name: 'Alerts' });
        this.alertsList = page
            .getByRole('row')
            .filter({ hasNotText: 'Delivery method' }); //Filter out header row
        this.createFirstAlertButton = page.getByRole('button', {
            name: 'Create an alert',
        });
        this.createNewAlertButton = page.getByRole('button', {
            name: 'Create new alert',
        });
        this.emailRadioButton = page.getByRole('radio', {
            name: 'Email',
        });
        this.createAlertsDialog = page.getByRole('dialog', {
            name: 'Create process incident alert',
        });
        this.createAlertButton = page.getByRole('button', {
            name: 'Create alert',
            exact: true,
        });
        this.createNewClientButton = page.getByRole('button', {
            name: 'Create new client',
        });
        this.clientsList = page.getByRole('row').filter({ hasNotText: 'Scopes' });
        this.envVarsTab = this.clientCredentialsDialog.getByRole('tab', {
            name: 'Env Vars',
        });
        this.zeebeCheckbox = page
            .getByRole('dialog')
            .locator('label')
            .filter({ hasText: /^Zeebe$/ });
        this.apiClientNameTextbox = page.getByRole('textbox', {
            name: 'Client Name',
        });
        this.expandButton = page.locator('button[class="cds--table-expand__button"]');
        this.rbaEnabledMessage = page.getByText('Authorizations enabled');
        this.authorizationsHeading = this.page.getByRole('heading', {
            name: 'Authorizations',
        });
        this.orchestrationClusterCheckbox = page
            .locator('label')
            .filter({ hasText: /^Orchestration Cluster API$/ });
        this.clientCredentialsLink = (clientCredentials) => page.getByRole('cell', { name: clientCredentials }).locator('a');
        this.reviewUpdateButton = page.getByRole('button', { name: 'Review Update' });
        this.updateAvailableDialog = page
            .locator('.cds--modal-container')
            .filter({ hasText: 'Update available' });
        this.updateButton = this.updateAvailableDialog.getByRole('button', {
            name: 'Update',
        });
        this.mcpSupportToggle = page.getByRole('switch', {
            name: /Enable MCP Support/i,
        });
        this.mcpTab = page.getByRole('tab', { name: 'MCP' });
        this.mcpTextarea = page.getByRole('textbox', { name: 'Copy to clipboard' });
    }
    async clickAPITab() {
        await (0, test_1.expect)(this.apiTab).toBeVisible({ timeout: 60000 });
        await this.apiTab.click({ timeout: 60000 });
    }
    async dismissOopsIfPresent() {
        // The clients list panel sometimes lands in a Carbon "Oops ... something
        // went wrong." state when a background ClustersService request fails on
        // SaaS INT. The panel replaces the create-client button, so any click
        // attempt will time out until the user clicks the inline Reload button.
        const oopsHeading = this.page.getByRole('heading', { name: /Oops/i });
        if (!(await oopsHeading.isVisible({ timeout: 1000 }).catch(() => false))) {
            return;
        }
        const reloadButton = this.page.getByRole('button', {
            name: 'Reload',
            exact: true,
        });
        if (await reloadButton.isVisible({ timeout: 1000 }).catch(() => false)) {
            await reloadButton.click({ timeout: 15000 }).catch(() => { });
        }
        else {
            await this.page.reload();
        }
        await this.page.waitForLoadState('domcontentloaded');
    }
    async clickCreateClientButton() {
        await (0, clickLocatorWithRetry_1.clickLocatorWithRetry)(this.page, this.createFirstClientButton.or(this.createNewClientButton), {
            preAction: async () => {
                await this.dismissOopsIfPresent();
            },
        });
    }
    async clickClientNameTextbox() {
        await this.clientNameTextbox.click({ timeout: 60000 });
    }
    async fillClientNameTextbox(name) {
        await this.clientNameTextbox.fill(name, { timeout: 60000 });
    }
    async clickTasklistCheckbox() {
        await this.tasklistCheckbox.click({ timeout: 60000 });
    }
    async checkSecretsCheckbox() {
        if (!(await this.secretsCheckbox.isChecked())) {
            await this.secretsCheckbox.click();
        }
    }
    async clickOperateCheckbox() {
        await this.operateCheckbox.click({ timeout: 60000 });
    }
    async clickOptimizeCheckbox() {
        await this.optimizeCheckbox.click({ timeout: 60000 });
    }
    async clickCreateButton() {
        await this.createButton.click({ timeout: 60000 });
    }
    async clickCloseModalButton() {
        await this.closeModalButton.click({ timeout: 60000 });
    }
    async clickSettingsTab() {
        await this.settingsTab.click({ timeout: 60000 });
    }
    async enableAuthorizations() {
        await (0, sleep_1.sleep)(5000);
        await (0, test_1.expect)(this.authorizationsHeading).toBeVisible({ timeout: 60000 });
        // Locate all elements with class .cds--toggle__text
        const toggleTextElements = await this.page.$$('.cds--toggle__text');
        // Check if toggleTextElements has at least 2 elements
        if (toggleTextElements.length >= 2) {
            // Get the text content of the second toggle text element
            const toggleText = await toggleTextElements[1].textContent();
            // Check if the text content is 'Disabled'
            if (toggleText === 'Disabled') {
                // Locate all elements with class .cds--toggle__switch
                const toggleSwitchElements = await this.page.$$('.cds--toggle__switch');
                // Check if toggleSwitchElements has at least 2 elements
                if (toggleSwitchElements.length >= 2) {
                    // Click the second toggle switch element
                    await toggleSwitchElements[1].click();
                    if (await this.dialog.isVisible({ timeout: 15000 })) {
                        await this.rbaEnableButton.click({ timeout: 30000 });
                        await (0, test_1.expect)(this.page.getByText('Enabling...')).not.toBeVisible({
                            timeout: 60000,
                        });
                    }
                    console.log('Second toggle switch clicked.');
                }
                else {
                    console.log('Second toggle switch not found or less than 2.');
                }
            }
            else {
                console.log("Second toggle text does not contain 'Disabled'.");
            }
        }
        else {
            console.log('Toggle text elements not found or less than 2.');
        }
    }
    async disableAuthorizations() {
        await (0, test_1.expect)(this.authorizationsHeading).toBeVisible({ timeout: 60000 });
        // Locate all elements with class .cds--toggle__text
        const toggleTextElements = await this.page.$$('.cds--toggle__text');
        // Check if toggleTextElements has at least 2 elements
        if (toggleTextElements.length >= 2) {
            // Get the text content of the second toggle text element
            const toggleText = await toggleTextElements[1].textContent();
            // Check if the text content is 'Enabled'
            if (toggleText === 'Enabled') {
                // Locate all elements with class .cds--toggle__switch
                const toggleSwitchElements = await this.page.$$('.cds--toggle__switch');
                // Check if toggleSwitchElements has at least 2 elements
                if (toggleSwitchElements.length >= 2) {
                    // Click the second toggle switch element
                    await toggleSwitchElements[1].click();
                    console.log('Second toggle switch clicked.');
                }
                else {
                    console.log('Second toggle switch not found or less than 2.');
                }
            }
            else {
                console.log("Second toggle text does not contain 'Enabled'.");
            }
        }
        else {
            console.log('Toggle text elements not found or less than 2.');
        }
    }
    async searchAndClickClientCredentialsLink(name) {
        await (0, test_1.expect)(this.clientsList.first()).toBeVisible({ timeout: 60000 });
        const clientLink = this.clientCredentialsLink(name);
        await (0, test_1.expect)(clientLink).toBeVisible({ timeout: 30000 });
        await clientLink.click();
        const clientCredentialsDetailsPage = new ClientCredentialsDetailsPage_1.ClientCredentialsDetailsPage(this.page);
        await clientCredentialsDetailsPage.isOpen(name);
        return clientCredentialsDetailsPage;
    }
    async deleteAPIClientsIfExist(name) {
        if (name) {
            const row = this.clientsList.filter({ hasText: name });
            const deleteButton = row.getByRole('button', { name: 'Delete' });
            try {
                await (0, test_1.expect)(deleteButton).toBeVisible({ timeout: 10000 });
                await deleteButton.click();
                await (0, test_1.expect)(this.dialog).toBeVisible();
                await this.deleteSubButton.click();
                await (0, test_1.expect)(this.page.getByText('Deleting...')).not.toBeVisible({
                    timeout: 10000,
                });
                await (0, test_1.expect)(row).not.toBeVisible();
            }
            catch (error) {
                console.warn(`No client row found for ${name} or deletion failed: ${error}`);
            }
            return;
        }
        await this.doDelete(this.dialog, 'API clients');
    }
    async clickAlertsTab() {
        await (0, test_1.expect)(this.alertsTab).toBeVisible({ timeout: 40000 });
        await this.alertsTab.click();
    }
    async clickExpandButton() {
        await this.expandButton.click({ timeout: 60000 });
    }
    async clickCreateFirstAlertButton() {
        await (0, test_1.expect)(this.createFirstAlertButton).toBeVisible({ timeout: 40000 });
        await this.createFirstAlertButton.click();
    }
    async clickCreateNewAlertButton() {
        await (0, test_1.expect)(this.createNewAlertButton).toBeVisible({ timeout: 60000 });
        await this.createNewAlertButton.click();
        await (0, test_1.expect)(this.page.getByText('Creating...')).not.toBeVisible({
            timeout: 60000,
        });
    }
    async createAlert(isFirstAlert = true) {
        if (isFirstAlert) {
            await this.clickCreateFirstAlertButton();
        }
        else {
            await this.clickCreateNewAlertButton();
        }
        await (0, test_1.expect)(this.createAlertsDialog).toBeVisible();
        await this.selectEmailRadioButton();
        await this.clickCreateAlertButton();
    }
    async selectEmailRadioButton() {
        await (0, test_1.expect)(this.emailRadioButton).toBeVisible({ timeout: 60000 });
        await this.emailRadioButton.click({ force: true });
    }
    async clickCreateAlertButton() {
        await (0, test_1.expect)(this.createAlertButton).toBeVisible({ timeout: 60000 });
        await this.createAlertButton.click();
        await (0, test_1.expect)(this.page.getByText('Creating...')).not.toBeVisible({
            timeout: 60000,
        });
    }
    async deleteAlerts() {
        await this.doDelete(this.dialog, 'Alerts');
    }
    async doDelete(dialog, text) {
        try {
            await (0, test_1.expect)(this.deleteButton.first()).toBeVisible({
                timeout: 10000,
            });
        }
        catch (error) {
            return; //No items found in the list
        }
        try {
            let deletes = await this.deleteButton.all();
            while (deletes.length > 0) {
                const deleteButton = deletes[0];
                if (await deleteButton.isVisible()) {
                    await deleteButton.click({ timeout: 60000 });
                    await (0, test_1.expect)(dialog).toBeVisible({ timeout: 40000 });
                    await this.deleteSubButton.click();
                    await (0, test_1.expect)(this.page.getByText('Deleting...')).not.toBeVisible({
                        timeout: 60000,
                    });
                }
                await (0, sleep_1.sleep)(3000);
                deletes = await this.deleteButton.all();
            }
            await (0, test_1.expect)(this.deleteButton).not.toBeVisible({
                timeout: 30000,
            });
        }
        catch (error) {
            console.error(`Error during ${text} deletion: `, error);
        }
    }
    async assertComponentsHealth(components = [
        'Zeebe',
        'Tasklist',
        'Operate',
        'Optimize',
        'Admin',
    ]) {
        for (const component of components) {
            await (0, expectLocatorWithRetry_1.expectLocatorWithRetry)(this.page, this.page.getByText(`${component}Healthy`, { exact: true }), {
                visibilityTimeout: 60000,
                totalTimeout: 400000,
                maxRetries: 7,
                preAction: async () => {
                    await this.page.reload();
                },
            });
        }
    }
    async createAPIClientAndReturnVariables(name, setEnvVariables = true, clusterType) {
        await this.createAPIClient(name);
        await this.clickEnvVarsButton();
        const variables = {
            zeebeAuthUrl: await this.clientCredentialsText(/export ZEEBE_AUTHORIZATION_SERVER_URL='([^']+)'/),
            zeebeClientId: await this.clientCredentialsText(/export ZEEBE_CLIENT_ID='([^']+)'/),
            zeebeClientSecret: await this.clientCredentialsText(/export ZEEBE_CLIENT_SECRET='([^']+)'/),
            zeebeUrl: await this.clientCredentialsText(/export ZEEBE_REST_ADDRESS='([^']+)'/),
            tokenAudience: await this.clientCredentialsText(/export ZEEBE_TOKEN_AUDIENCE='([^']+)'/),
            optimizeBaseUrl: await this.clientCredentialsText(/export CAMUNDA_OPTIMIZE_BASE_URL='([^']+)'/),
        };
        if (setEnvVariables) {
            if (clusterType) {
                // Use cluster-specific suffixed env vars
                const suffix = clusterType.toUpperCase().replace(/[\s-]/g, '_');
                process.env[`ZEEBE_API_CLIENT_ID_${suffix}`] = variables.zeebeClientId;
                process.env[`ZEEBE_API_CLIENT_SECRET_${suffix}`] =
                    variables.zeebeClientSecret;
                process.env[`ZEEBE_API_AUTH_URL_${suffix}`] = variables.zeebeAuthUrl;
                process.env[`ZEEBE_API_URL_${suffix}`] = variables.zeebeUrl;
                process.env[`ZEEBE_API_TOKEN_AUDIENCE_${suffix}`] =
                    variables.tokenAudience;
                process.env[`CAMUNDA_OPTIMIZE_BASE_URL_${suffix}`] =
                    variables.optimizeBaseUrl;
                console.log(`[ClusterDetailsPage] Set credentials for cluster type: ${clusterType}`);
            }
            else {
                process.env.ZEEBE_API_CLIENT_ID = variables.zeebeClientId;
                process.env.ZEEBE_API_CLIENT_SECRET = variables.zeebeClientSecret;
                process.env.ZEEBE_API_AUTH_URL = variables.zeebeAuthUrl;
                process.env.ZEEBE_API_URL = variables.zeebeUrl;
                process.env.ZEEBE_API_TOKEN_AUDIENCE = variables.tokenAudience;
                process.env.CAMUNDA_OPTIMIZE_BASE_URL = variables.optimizeBaseUrl;
                process.env.OPTIMIZE_API_TOKEN_AUDIENCE = 'optimize.ultrawombat.com';
            }
        }
        return variables;
    }
    async createAPIClient(name) {
        await this.clickCreateClientButton();
        await (0, test_1.expect)(this.createClientCredentialsDialog).toBeVisible({
            timeout: 30000,
        });
        await this.fillAPIClientName(name);
        await this.checkOrchestrationClusterCheckbox();
        await this.checkOptimizeCheckbox();
        await this.checkSecretsCheckbox();
        await this.clickCreateButton();
        await (0, test_1.expect)(this.clientCredentialsDialog).toBeVisible({
            timeout: 60000,
        });
        await (0, test_1.expect)(this.clientCredentialsDialog
            .getByText('The Client Secret will not be shown again.')
            .first()).toBeVisible();
        try {
            await (0, test_1.expect)(this.clientsList.filter({ hasText: name })).toContainText(/(?=.*Orchestration)(?=.*Optimize)(?=.*Secrets)/, {
                timeout: 10000,
            });
        }
        catch (err) {
            // The clients list panel can land in "Oops ... something went wrong."
            // while the post-create modal is still open. The modal blocks pointer
            // events so we can't click Reload here; the modal's "Client Secret will
            // not be shown again" message above already proves the client exists.
            const oopsVisible = await this.page
                .getByRole('heading', { name: /Oops/i })
                .isVisible({ timeout: 1000 })
                .catch(() => false);
            if (!oopsVisible)
                throw err;
            console.warn(`createAPIClient: clients list panel is in Oops state; skipping row scope assertion for "${name}".`);
        }
    }
    async clickEnvVarsButton() {
        await (0, test_1.expect)(this.envVarsTab).toBeVisible({ timeout: 40000 });
        await this.envVarsTab.click();
    }
    async clientCredentialsText(regex) {
        const innerText = await this.clientCredentialsDialog.innerText();
        const match = innerText.match(regex);
        if (match && match[1]) {
            return match[1];
        }
        else {
            throw new Error(`No client credentials found by the regex expression ${regex}`);
        }
    }
    async checkTasklistCheckbox() {
        if (!(await this.tasklistCheckbox.isChecked())) {
            await this.tasklistCheckbox.click();
        }
    }
    async checkOptimizeCheckbox() {
        if (!(await this.optimizeCheckbox.isChecked())) {
            await this.optimizeCheckbox.click();
        }
    }
    async checkOperateCheckbox() {
        if (!(await this.operateCheckbox.isChecked())) {
            await this.operateCheckbox.click();
        }
    }
    async checkZeebeCheckbox() {
        if (!(await this.zeebeCheckbox.isChecked())) {
            await this.zeebeCheckbox.click();
        }
    }
    async fillAPIClientName(name) {
        const maxRetries = 3;
        for (let attempt = 1; attempt <= maxRetries; attempt++) {
            try {
                await (0, sleep_1.sleep)(1000);
                await (0, test_1.expect)(this.apiClientNameTextbox).toBeVisible({ timeout: 60000 });
                await this.apiClientNameTextbox.click();
                await this.apiClientNameTextbox.fill(name);
                const inputValue = await this.apiClientNameTextbox.inputValue();
                if (inputValue === name) {
                    return;
                }
                console.log(`Attempt ${attempt}: Value input not filled correctly. Expected: "${name}", Got: "${inputValue}"`);
            }
            catch (error) {
                console.log(`Attempt ${attempt}: Error filling value input:`, error);
            }
            if (attempt < maxRetries) {
                await this.apiClientNameTextbox.clear();
            }
        }
        throw new Error(`Failed to fill value input after ${maxRetries} attempts`);
    }
    async assertAlertText(text, timeout = 60000, maxRetries = 10) {
        for (let attempt = 0; attempt < maxRetries; attempt++) {
            try {
                await (0, test_1.expect)(this.alertsList.nth(1)).toContainText(text, { timeout });
                return;
            }
            catch (error) {
                if (attempt < maxRetries - 1) {
                    console.warn(`Attempt ${attempt + 1} failed for asserting ${text}. Retrying...`);
                    await this.page.reload();
                    await (0, sleep_1.sleep)(20000);
                }
                else {
                    throw new Error(`Assertion failed after ${maxRetries} attempts`);
                }
            }
        }
    }
    async checkOrchestrationClusterCheckbox() {
        if (!(await this.orchestrationClusterCheckbox.isChecked())) {
            await this.orchestrationClusterCheckbox.click();
        }
    }
    async clickReviewUpdateButton() {
        await this.reviewUpdateButton.click({ timeout: 60000 });
    }
    async performClusterUpdate() {
        await this.clickReviewUpdateButton();
        await (0, test_1.expect)(this.updateAvailableDialog).toBeVisible({ timeout: 30000 });
        await this.updateButton.click({ timeout: 60000 });
    }
    async checkMcpSupportToggle() {
        if (!(await this.mcpSupportToggle.isVisible())) {
            throw new Error('MCP Support toggle is not visible');
        }
        // Only click if not already enabled to avoid disabling on reruns
        if (!(await this.mcpSupportToggle.isChecked())) {
            await this.mcpSupportToggle.click({ force: true });
        }
        await (0, test_1.expect)(this.mcpSupportToggle).toBeChecked();
    }
    async clickMCPTab() {
        await (0, test_1.expect)(this.mcpTab).toBeVisible({ timeout: 60000 });
        await this.mcpTab.click();
    }
    async getMcpConfigurationText() {
        await (0, test_1.expect)(this.mcpTextarea).toBeVisible({ timeout: 60000 });
        return await this.mcpTextarea.innerText();
    }
    async createMCPClientAndReturnVariables(name, setEnvVariables = true) {
        await this.createAPIClient(name);
        await this.clickMCPTab();
        const mcpConfigText = await this.getMcpConfigurationText();
        const mcpConfig = JSON.parse(mcpConfigText);
        const env = Object.values(mcpConfig.servers)[0].env;
        const credentials = {
            baseURL: env.CAMUNDA_BASE_URL,
            clientID: env.CAMUNDA_CLIENT_ID,
            clientSecret: env.CAMUNDA_CLIENT_SECRET,
            OauthURL: env.CAMUNDA_OAUTH_URL,
            tokenAudience: env.CAMUNDA_TOKEN_AUDIENCE,
        };
        if (setEnvVariables) {
            process.env.MCP_BASE_URL = credentials.baseURL;
            process.env.MCP_CLIENT_ID = credentials.clientID;
            process.env.MCP_CLIENT_SECRET = credentials.clientSecret;
            process.env.MCP_OAUTH_URL = credentials.OauthURL;
            process.env.MCP_TOKEN_AUDIENCE = credentials.tokenAudience;
        }
        return credentials;
    }
}
exports.ClusterDetailsPage = ClusterDetailsPage;
