"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.waitForLoadingToFinish = exports.assertTestUsesCorrectOrganizationFromModeler = exports.expectCountToBeOneOf = exports.createAPIClient = exports.modelAndRunConnectorsTimerEventDiagram = exports.modelAndRunConnectorsDocHandlingDiagram = exports.deleteCluster = exports.deleteAllUserGroups = exports.assertTestUsesCorrectOrganization = exports.clickInvitationLinkInEmail = exports.assertLatestAlertEmail = exports.enableAuthorizations = exports.disableRBA = exports.runMultipleProcesses = exports.modelDiagramFromFile = exports.runProcess = exports.completeTaskWithRetry = exports.assertPageTextWithRetry = exports.assertLocatorVisibleWithRetry = exports.modelRestConnector = exports.loginWithRetry = exports.forceLogoutIfNeeded = void 0;
const test_1 = require("@playwright/test");
const ModelerHomePage_1 = require("./ModelerHomePage");
const HomePage_1 = require("./HomePage");
const sleep_1 = require("../../utils/sleep");
const randomSleep_1 = require("../../utils/randomSleep");
const SettingsPage_1 = require("./SettingsPage");
const fileUpload_1 = require("../../utils/fileUpload");
async function forceLogoutIfNeeded(page) {
    const settingsPage = new SettingsPage_1.SettingsPage(page);
    const loginMessage = page.getByText('Log in to continue to Camunda.');
    try {
        await Promise.race([
            settingsPage.openSettingsButton.waitFor({
                state: 'visible',
                timeout: 30000,
            }),
            loginMessage.waitFor({
                state: 'visible',
                timeout: 30000,
            }),
        ]);
    }
    catch {
        // Neither appeared within 30s - continue without logout
    }
    if (await settingsPage.openSettingsButton.isVisible({ timeout: 1000 })) {
        await settingsPage.clickOpenSettingsButton();
        await settingsPage.clickLogoutButton();
    }
}
exports.forceLogoutIfNeeded = forceLogoutIfNeeded;
async function loginWithRetry(page, loginPage, testUser, timeout, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            await page.goto('/');
            await (0, sleep_1.sleep)(timeout);
            await loginPage.loginWithTestUser(testUser);
            return;
        }
        catch (error) {
            if (attempt < maxRetries - 1) {
                console.warn(`Attempt ${attempt + 1} failed for logging in. Retrying...`);
                await (0, randomSleep_1.randomSleep)(10000, 20000);
            }
            else {
                console.error(error);
                throw new Error(`Login failed after ${maxRetries} attempts`);
            }
        }
    }
}
exports.loginWithRetry = loginWithRetry;
async function modelRestConnector(modelerCreatePage, connectorSettingsPage, processName, url, auth, resultExpression, resultVariable = '', basicAuthCredentials = {
    username: '',
    password: '',
}) {
    await (0, test_1.expect)(modelerCreatePage.generalPanel).toBeVisible({
        timeout: 120000,
    });
    await modelerCreatePage.enterDiagramName(processName);
    await (0, sleep_1.sleep)(15000);
    await modelerCreatePage.clickAppendElementButton();
    await modelerCreatePage.clickAppendTaskButton();
    await modelerCreatePage.clickChangeTypeButton();
    await modelerCreatePage.clickRestConnectorOption();
    await connectorSettingsPage.clickAuthenticationTab();
    await connectorSettingsPage.clickHTTPEndpointTab();
    if (auth == 'bearer') {
        await connectorSettingsPage.selectAuthenticationType('bearer');
        await (0, test_1.expect)(connectorSettingsPage.bearerTokenInput).toBeVisible({
            timeout: 60000,
        });
        await connectorSettingsPage.clickBearerTokenInput();
        await connectorSettingsPage.fillBearerTokenInput('thisisabearertoken');
        await (0, test_1.expect)(connectorSettingsPage.methodTypeDropdown).toBeVisible({
            timeout: 30000,
        });
        await connectorSettingsPage.selectMethodType('POST');
    }
    else if (auth == 'basic') {
        await connectorSettingsPage.selectAuthenticationType('basic');
        await (0, test_1.expect)(connectorSettingsPage.usernameInput).toBeVisible({
            timeout: 60000,
        });
        await connectorSettingsPage.clickUsernameInput();
        (0, test_1.expect)(basicAuthCredentials['username'].length).toBeGreaterThan(0);
        (0, test_1.expect)(basicAuthCredentials['password'].length).toBeGreaterThan(0);
        await connectorSettingsPage.fillUsernameInput(basicAuthCredentials['username']);
        await connectorSettingsPage.clickPasswordInput();
        await connectorSettingsPage.fillPasswordInput(basicAuthCredentials['password']);
        await connectorSettingsPage.selectMethodType('POST');
    }
    await connectorSettingsPage.clickUrlInput();
    await connectorSettingsPage.fillUrlInput(url);
    await connectorSettingsPage.clickOutputMappingTab();
    if (resultVariable.length > 0) {
        await (0, test_1.expect)(connectorSettingsPage.resultVariableInput).toBeVisible({
            timeout: 60000,
        });
        await connectorSettingsPage.clickResultVariableInput();
        await connectorSettingsPage.fillResultVariableInput('result');
        await (0, sleep_1.sleep)(5000);
    }
    await connectorSettingsPage.clickResultExpressionInput();
    await connectorSettingsPage.fillResultExpressionInput(resultExpression);
    await (0, sleep_1.sleep)(5000);
    await modelerCreatePage.clickAppendElementButton();
    await modelerCreatePage.clickAppendEndEventButton();
    await (0, sleep_1.sleep)(20000);
}
exports.modelRestConnector = modelRestConnector;
async function assertLocatorVisibleWithRetry(page, locator, text, timeout = 60000, notVisible, maxRetries = 6, clickLocator) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            if (clickLocator) {
                await (0, test_1.expect)(clickLocator).toBeVisible({
                    timeout: 30000,
                });
                await clickLocator.click();
            }
            if (notVisible == true) {
                await (0, sleep_1.sleep)(10000);
                await (0, test_1.expect)(locator.first()).not.toBeVisible({
                    timeout: timeout,
                });
            }
            else {
                await (0, test_1.expect)(locator).toBeVisible({
                    timeout: timeout,
                });
            }
            return;
        }
        catch (error) {
            if (attempt < maxRetries - 1) {
                console.warn(`Attempt ${attempt + 1} failed for asserting ${text}. Retrying...`);
                await page.reload();
                await (0, sleep_1.sleep)(10000);
            }
            else {
                throw new Error(`Assertion of ${text} failed after ${maxRetries} attempts`);
            }
        }
    }
}
exports.assertLocatorVisibleWithRetry = assertLocatorVisibleWithRetry;
async function assertPageTextWithRetry(page, text, notVisible = false, timeout = 60000, maxRetries = 10) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            if (notVisible) {
                await (0, sleep_1.sleep)(10000);
                await (0, test_1.expect)(page.getByText(text, { exact: true }).first()).not.toBeVisible({
                    timeout: timeout,
                });
            }
            else {
                await (0, test_1.expect)(page.getByText(text, { exact: true }).first()).toBeVisible({
                    timeout: timeout,
                });
            }
            return;
        }
        catch (error) {
            if (attempt < maxRetries - 1) {
                console.warn(`Attempt ${attempt + 1} failed for asserting ${text}. Retrying...`);
                await page.reload();
                await (0, sleep_1.sleep)(5000);
            }
            else {
                throw new Error(`Assertion of ${text} failed after ${maxRetries} attempts`);
            }
        }
    }
}
exports.assertPageTextWithRetry = assertPageTextWithRetry;
async function completeTaskWithRetry(taskPanelPage, taskDetailsPage, taskName, taskPriority, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
            await taskPanelPage.openTask(taskName);
            await (0, test_1.expect)(taskDetailsPage.detailsInfo.getByText(taskName, { exact: true })).toBeVisible();
            if (!(await taskDetailsPage.assignedToMeText.isVisible())) {
                await taskDetailsPage.clickAssignToMeButton();
            }
            await (0, test_1.expect)(taskDetailsPage.detailsPanel.getByText(taskPriority)).toBeVisible();
            await taskDetailsPage.clickCompleteTaskButton();
            await (0, test_1.expect)(taskPanelPage.availableTasks.getByText(taskName, { exact: true }).first()).not.toBeVisible({ timeout: 30000 });
            return;
        }
        catch (error) {
            if (attempt < maxRetries - 1) {
                console.warn(`Attempt ${attempt + 1} failed for completing task ${taskName}. Retrying...`);
                await (0, sleep_1.sleep)(2000);
            }
            else {
                throw new Error(`Failed to complete task ${taskName} after ${maxRetries} attempts: ${error}`);
            }
        }
    }
}
exports.completeTaskWithRetry = completeTaskWithRetry;
async function runProcess(clusterName, page, modelerHomePage, modelerCreatePage, processName, processId = '', uploadFromFile = '') {
    if (uploadFromFile.length > 0) {
        await modelDiagramFromFile(page, modelerHomePage, modelerCreatePage, processName, uploadFromFile);
    }
    else {
        await modelerHomePage.clickDiagramTypeDropdown();
        await modelerHomePage.clickBpmnTemplateOption();
        await modelerCreatePage.modelCamundaUserTaskDiagram(processName, processId);
    }
    await modelerCreatePage.runProcessInstance(clusterName);
    await (0, test_1.expect)(modelerCreatePage.viewProcessInstanceLink).toBeVisible({
        timeout: 60000,
    });
    await (0, test_1.expect)(modelerCreatePage.viewProcessInstanceLink).toBeHidden({
        timeout: 60000,
    });
}
exports.runProcess = runProcess;
async function modelDiagramFromFile(page, modelerHomePage, modelerCreatePage, processName, fileName = '', nrOfRenamedUserTasks = 0, taskName = '') {
    await modelerHomePage.clickDiagramTypeDropdown();
    await modelerHomePage.clickUploadFilesButton();
    await (0, fileUpload_1.uploadFile)(page, fileName + '.bpmn');
    await modelerHomePage.clickProcessDiagram(fileName);
    await modelerCreatePage.clickDiagramBreadcrumb();
    await modelerCreatePage.clickEditDiagramNameButton();
    await modelerCreatePage.enterDiagramName(processName);
    await (0, sleep_1.sleep)(1000);
    await modelerCreatePage.clickGeneralPropertiesPanel();
    await modelerCreatePage.clickNameInput();
    await modelerCreatePage.fillNamedInput(processName);
    await modelerCreatePage.clickIdInput();
    await modelerCreatePage.fillIdInput(processName);
    if (nrOfRenamedUserTasks > 0) {
        for (let i = 1; i <= nrOfRenamedUserTasks; i++) {
            await modelerCreatePage.clickUserTask('process' + i);
            await modelerCreatePage.clickNameInput();
            await modelerCreatePage.fillNamedInput(taskName + i);
            await modelerCreatePage.clickIdInput();
            await modelerCreatePage.fillIdInput(taskName + i);
            await modelerCreatePage.clickCanvas();
        }
    }
    await (0, sleep_1.sleep)(10000);
}
exports.modelDiagramFromFile = modelDiagramFromFile;
async function runMultipleProcesses(clusterName, page, modelerHomePage, modelerCreatePage, options) {
    const { processName = 'Camunda_User_Task', numberOfProcesses = 2, uploadFromFile = '', } = options || {};
    for (let i = 1; i <= numberOfProcesses; i++) {
        await runProcess(clusterName, page, modelerHomePage, modelerCreatePage, processName + i, processName + i, uploadFromFile);
        await modelerHomePage.clickProjectBreadcrumb();
    }
}
exports.runMultipleProcesses = runMultipleProcesses;
async function disableRBA(clusterName, homePage, clusterPage, clusterDetailsPage, appsPage) {
    await appsPage.clickCamundaApps();
    await appsPage.clickConsoleLink();
    await (0, test_1.expect)(homePage.clusterTab).toBeVisible({ timeout: 120000 });
    await homePage.clickClusters();
    await clusterPage.clickClusterLink(clusterName);
    await (0, test_1.expect)(clusterDetailsPage.settingsTab).toBeVisible({
        timeout: 90000,
    });
    await clusterDetailsPage.clickSettingsTab();
    await clusterDetailsPage.disableAuthorizations();
    await homePage.clickClusters();
    await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
    await clusterPage.clickClusterLink(clusterName);
    await (0, test_1.expect)(clusterDetailsPage.rbaEnabledMessage.first()).not.toBeVisible({
        timeout: 30000,
    });
    await clusterDetailsPage.assertComponentsHealth();
}
exports.disableRBA = disableRBA;
async function enableAuthorizations(clusterName, homePage, clusterPage, clusterDetailsPage, appsPage) {
    await appsPage.clickCamundaApps();
    await appsPage.clickConsoleLink();
    await (0, test_1.expect)(homePage.clusterTab).toBeVisible({ timeout: 120000 });
    await homePage.clickClusters();
    await clusterPage.clickClusterLink(clusterName);
    await (0, test_1.expect)(clusterDetailsPage.settingsTab).toBeVisible({
        timeout: 90000,
    });
    await clusterDetailsPage.clickSettingsTab();
    await clusterDetailsPage.enableAuthorizations();
    await homePage.clickClusters();
    await clusterPage.assertClusterHealthyStatusWithRetry(clusterName);
    await clusterPage.clickClusterLink(clusterName);
    await clusterDetailsPage.assertComponentsHealth();
}
exports.enableAuthorizations = enableAuthorizations;
async function assertLatestAlertEmail(id, mailSlurp, processName, alertText) {
    const maxRetries = 3;
    for (let retries = 0; retries < maxRetries; retries++) {
        try {
            const email = await mailSlurp.waitForLatestEmail(id, 120000);
            if (email && email.body) {
                (0, test_1.expect)(email.body).toContain(processName);
                (0, test_1.expect)(email.body).toContain(alertText);
                return email.body;
            }
            else {
                throw new Error('Email or email body is null or undefined.');
            }
        }
        catch (error) {
            console.warn(`Click attempt ${retries + 1} failed: ${error}`);
        }
    }
    throw new Error(`Failed to get latest alert (${processName}) email for ${id} after ${maxRetries} attempts.`);
}
exports.assertLatestAlertEmail = assertLatestAlertEmail;
async function clickInvitationLinkInEmail(page, id, mailSlurp) {
    const email = await mailSlurp.waitForLatestEmail(id, 120000);
    if (email && email.body) {
        const confirmationLinkMatch = email.body.match(/href="([^"]*)/);
        if (confirmationLinkMatch) {
            await page.goto(confirmationLinkMatch[1]);
        }
        else {
            throw new Error('Confirmation link not found in email body.');
        }
    }
    else {
        throw new Error('Email or email body is null or undefined.');
    }
}
exports.clickInvitationLinkInEmail = clickInvitationLinkInEmail;
async function assertTestUsesCorrectOrganization(page) {
    const homePage = new HomePage_1.HomePage(page);
    if (page.url().includes('?code=') || page.url().includes('&state=')) {
        console.log('OAuth callback detected, waiting for redirect...');
        await page.waitForURL((url) => !url.toString().includes('?code='), {
            timeout: 30000,
        });
        await (0, sleep_1.sleep)(5000);
    }
    if (page.url().includes('modeler')) {
        const modelerHomePage = new ModelerHomePage_1.ModelerHomePage(page);
        await modelerHomePage.clickMessageBanner();
        await (0, test_1.expect)(homePage.modelerBanner).toBeVisible({ timeout: 30000 });
    }
    else {
        await (0, test_1.expect)(homePage.consoleBanner).toBeVisible({ timeout: 30000 });
    }
    await (0, test_1.expect)(homePage.openOrganizationButton).toBeVisible({ timeout: 180000 });
    try {
        await (0, test_1.expect)(page.url()).toContain(process.env.ORG_ID);
    }
    catch (error) {
        // If the first check fails, check by org name
        try {
            await homePage.clickOpenOrganizationButton();
            await page
                .getByRole('treeitem', { name: process.env.ORG_NAME, exact: true })
                .click({ timeout: 30000 });
        }
        catch (reloadError) {
            await page
                .getByRole('button', { name: process.env.ORG_NAME })
                .click({ timeout: 30000 });
        }
        await (0, test_1.expect)(page
            .locator('[class="cds--header__global"]')
            .getByTitle(process.env.ORG_NAME, { exact: true })
            .first()).toBeVisible({
            timeout: 30000,
        });
        await (0, test_1.expect)(page.url()).toContain(process.env.ORG_ID);
        await (0, sleep_1.sleep)(5000);
    }
}
exports.assertTestUsesCorrectOrganization = assertTestUsesCorrectOrganization;
async function deleteAllUserGroups(homePage, organizationPage, appsPage) {
    await appsPage.clickCamundaApps();
    await appsPage.clickConsoleLink();
    await (0, test_1.expect)(homePage.organizationTab).toBeVisible({ timeout: 120000 });
    await homePage.clickOrganization();
    await organizationPage.clickGroupsTab();
    await organizationPage.deleteAllGroups();
}
exports.deleteAllUserGroups = deleteAllUserGroups;
async function deleteCluster(clusterName, homePage, clusterPage, appsPage) {
    await appsPage.clickCamundaApps();
    await appsPage.clickConsoleLink();
    await homePage.clickClusters();
    await clusterPage.deleteCluster(clusterName);
}
exports.deleteCluster = deleteCluster;
async function modelAndRunConnectorsDocHandlingDiagram(modelerCreatePage, modelerHomePage, processName, page, connectorMarketplacePage, clusterName, zeebeUrl, zeebeClientId, zeebeClientSecret) {
    await modelerHomePage.clickCrossComponentProjectFolder();
    await modelerHomePage.clickDiagramTypeDropdown();
    await modelerHomePage.clickUploadFilesButton();
    await (0, fileUpload_1.uploadFile)(page, 'Connectors Document Handling.bpmn');
    await modelerHomePage.clickProcessDiagram('Connectors Document Handling');
    await modelerCreatePage.clickDiagramBreadcrumb();
    await modelerCreatePage.clickEditDiagramNameButton();
    await modelerCreatePage.enterDiagramName(processName);
    await modelerCreatePage.clickGeneralPropertiesPanel();
    await modelerCreatePage.clickNameInput();
    await modelerCreatePage.fillNamedInput(processName);
    await modelerCreatePage.clickIdInput();
    await modelerCreatePage.fillIdInput(processName);
    await (0, sleep_1.sleep)(10000);
    await modelerCreatePage.clickSecondPlacedElement();
    await modelerCreatePage.clickChangeTypeButton();
    await (0, test_1.expect)(modelerCreatePage.marketPlaceButton).toBeVisible({
        timeout: 120000,
    });
    await modelerCreatePage.clickMarketPlaceButton();
    await connectorMarketplacePage.clickSearchForConnectorTextbox();
    await connectorMarketplacePage.fillSearchForConnectorTextbox('REST Connector');
    await connectorMarketplacePage.downloadConnectorToProject();
    await (0, sleep_1.sleep)(5000);
    await page.reload();
    await (0, sleep_1.sleep)(5000);
    await modelerCreatePage.fillStartEventVariablesForDocHandling(zeebeUrl, zeebeClientId, zeebeClientSecret);
    await modelerCreatePage.runProcessInstance(clusterName);
}
exports.modelAndRunConnectorsDocHandlingDiagram = modelAndRunConnectorsDocHandlingDiagram;
async function modelAndRunConnectorsTimerEventDiagram(modelerCreatePage, modelerHomePage, processName, page, connectorMarketplacePage, clusterName, connectorTemplatePage) {
    await modelerHomePage.clickCrossComponentProjectFolder();
    await modelerHomePage.clickDiagramTypeDropdown();
    await modelerHomePage.clickUploadFilesButton();
    await (0, fileUpload_1.uploadFile)(page, 'Rest Connector Timer Event.bpmn');
    await modelerHomePage.clickProcessDiagram('Rest Connector Timer Event');
    await modelerCreatePage.clickDiagramBreadcrumb();
    await modelerCreatePage.clickEditDiagramNameButton();
    await modelerCreatePage.enterDiagramName(processName);
    await modelerCreatePage.clickEighthPlacedElement();
    await modelerCreatePage.clickChangeTypeButton();
    await (0, test_1.expect)(modelerCreatePage.marketPlaceButton).toBeVisible({
        timeout: 120000,
    });
    await modelerCreatePage.clickMarketPlaceButton();
    await connectorMarketplacePage.clickSearchForConnectorTextbox();
    await connectorMarketplacePage.fillSearchForConnectorTextbox('REST Connector');
    await (0, sleep_1.sleep)(10000);
    await (0, test_1.expect)(page.getByText('REST ConnectorBy CamundaConnect, interact, and synchronize processes')).toBeVisible({
        timeout: 60000,
    });
    await connectorMarketplacePage.downloadConnectorToProject();
    await modelerHomePage.clickProjectBreadcrumb();
    await modelerHomePage.clickProcessDiagram('REST Outbound Connector');
    await connectorTemplatePage.publishConnector();
    await modelerHomePage.clickProjectBreadcrumb();
    await modelerHomePage.clickProcessDiagram(processName);
    await (0, sleep_1.sleep)(5000);
    await page.reload();
    await (0, sleep_1.sleep)(5000);
    await modelerCreatePage.runProcessInstance(clusterName);
}
exports.modelAndRunConnectorsTimerEventDiagram = modelAndRunConnectorsTimerEventDiagram;
async function createAPIClient(apiClientName, homePage, clusterDetailsPage, clusterName, clusterPage) {
    await homePage.closeInformationDialog();
    await homePage.clickClusters();
    await clusterPage.clickClusterLink(clusterName);
    await clusterDetailsPage.clickAPITab();
    await clusterDetailsPage.createAPIClientAndReturnVariables(apiClientName);
    await clusterDetailsPage.clickCloseModalButton();
}
exports.createAPIClient = createAPIClient;
async function expectCountToBeOneOf(locator, count1, count2) {
    try {
        await Promise.race([
            (0, test_1.expect)(locator).toHaveCount(count1),
            (0, test_1.expect)(locator).toHaveCount(count2),
        ]);
    }
    catch {
        const actual = await locator.count();
        throw new Error(`Expected count to be either ${count1} or ${count2}, but was ${actual}`);
    }
}
exports.expectCountToBeOneOf = expectCountToBeOneOf;
async function assertTestUsesCorrectOrganizationFromModeler(page) {
    const homePage = new HomePage_1.HomePage(page);
    await (0, test_1.expect)(homePage.openOrganizationButton).toBeVisible({ timeout: 180000 });
    if (page.url().includes('modeler')) {
        await (0, test_1.expect)(homePage.modelerBanner).toBeVisible({ timeout: 60000 });
    }
    else {
        await homePage.closeInformationDialog();
        await (0, test_1.expect)(homePage.consoleBanner).toBeVisible({ timeout: 60000 });
    }
    try {
        await (0, sleep_1.sleep)(20000);
        await (0, test_1.expect)(page.getByTitle(process.env.ORG_NAME)).toBeVisible({
            timeout: 30000,
        });
    }
    catch (error) {
        // If the first check fails, check by org name
        try {
            await homePage.clickOpenOrganizationButton();
            await page
                .getByRole('treeitem', { name: process.env.ORG_NAME, exact: true })
                .click({ timeout: 30000 });
        }
        catch (reloadError) {
            await page
                .getByRole('button', { name: process.env.ORG_NAME })
                .click({ timeout: 30000 });
        }
    }
}
exports.assertTestUsesCorrectOrganizationFromModeler = assertTestUsesCorrectOrganizationFromModeler;
async function waitForLoadingToFinish(page, timeout = 20000) {
    await page.waitForLoadState('load', { timeout }).catch((error) => {
        console.log(error);
    });
}
exports.waitForLoadingToFinish = waitForLoadingToFinish;
