"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clickLocatorWithRetry = void 0;
const RETRY_DELAY_MS = 2000;
const isPageClosedError = (err) => {
    if (!(err instanceof Error))
        return false;
    const msg = err.message;
    return (msg.includes('Target page, context or browser has been closed') ||
        msg.includes('page has been closed') ||
        msg.includes('Target closed') ||
        msg.includes('frame was detached') ||
        msg.includes('Frame was detached'));
};
const clickLocatorWithRetry = async (page, locator, options) => {
    const { totalTimeout = 60000, visibilityTimeout = 10000, maxRetries = 3, retryDelayMs = RETRY_DELAY_MS, } = options || {};
    let attempt = 0;
    const startTime = Date.now();
    while (Date.now() - startTime < totalTimeout && attempt < maxRetries) {
        attempt++;
        try {
            if (page.isClosed()) {
                throw new Error('clickLocatorWithRetry: page is closed, aborting retries');
            }
            if (options?.preAction) {
                try {
                    await options.preAction();
                }
                catch (preErr) {
                    if (isPageClosedError(preErr)) {
                        throw preErr;
                    }
                    console.warn(`clickLocatorWithRetry: preAction (attempt ${attempt}) threw and will be retried:`, preErr instanceof Error ? preErr.message : preErr);
                }
            }
            await locator.waitFor({ state: 'visible', timeout: visibilityTimeout });
            await locator.scrollIntoViewIfNeeded({ timeout: visibilityTimeout });
            await locator.waitFor({ state: 'attached', timeout: visibilityTimeout });
            // Trial click to verify the element is clickable before the real click
            await locator.click({ trial: true, timeout: visibilityTimeout });
            await locator.click({ timeout: visibilityTimeout });
            return;
        }
        catch (err) {
            if (isPageClosedError(err)) {
                throw err;
            }
            console.log(`Attempt ${attempt} failed for ${locator}, retrying... Error: ${err}`);
            if (options?.postAction) {
                // Swallow transient errors from the recovery action (e.g.
                // `page.reload()` throwing ERR_CONNECTION_REFUSED while the
                // upstream is restarting). Retry the click on the next loop.
                try {
                    await options.postAction();
                }
                catch (postErr) {
                    if (isPageClosedError(postErr)) {
                        throw postErr;
                    }
                    console.warn(`clickLocatorWithRetry: postAction (attempt ${attempt}) threw and will be retried:`, postErr instanceof Error ? postErr.message : postErr);
                }
            }
            await page.waitForTimeout(retryDelayMs);
        }
    }
    throw new Error(`Failed to click locator ${locator} after ${attempt} attempts.`);
};
exports.clickLocatorWithRetry = clickLocatorWithRetry;
