"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const cucumber_1 = require("@cucumber/cucumber");
const promises_1 = __importDefault(require("node:fs/promises"));
const test_1 = require("@playwright/test");
const locator_1 = require("../runtime/locator");
const screenshots_1 = require("../runtime/screenshots");
const ui_controls_1 = require("../runtime/ui-controls");
const visibility_1 = require("../runtime/visibility");
(0, cucumber_1.Then)('I should see text {string}', async function (text) {
    await (0, test_1.expect)(this.page.getByText(text)).toBeVisible();
});
(0, cucumber_1.Then)('I should see text {string} at index {int}', async function (text, index) {
    await (0, test_1.expect)(this.page.getByText(text).nth(index)).toBeVisible();
});
(0, cucumber_1.Then)('I should not see text {string}', async function (text) {
    await (0, test_1.expect)(this.page.getByText(text)).not.toBeVisible();
});
(0, cucumber_1.Then)('I should not see text {string} at index {int}', async function (text, index) {
    await (0, test_1.expect)(this.page.getByText(text).nth(index)).not.toBeVisible();
});
(0, cucumber_1.Then)('{string} should be visible', async function (name) {
    await (0, test_1.expect)((0, locator_1.locatorByLabelOrText)(this.page, name, this.config.selectors)).toBeVisible();
});
(0, cucumber_1.Then)('{string} at index {int} should be visible', async function (name, index) {
    await (0, test_1.expect)((0, locator_1.atIndex)((0, locator_1.locatorByLabelOrText)(this.page, name, this.config.selectors), index)).toBeVisible();
});
(0, cucumber_1.Then)('{string} should be enabled', async function (name) {
    await (0, test_1.expect)((0, locator_1.locatorByLabelOrText)(this.page, name, this.config.selectors)).toBeEnabled();
});
(0, cucumber_1.Then)('{string} at index {int} should be enabled', async function (name, index) {
    await (0, test_1.expect)((0, locator_1.atIndex)((0, locator_1.locatorByLabelOrText)(this.page, name, this.config.selectors), index)).toBeEnabled();
});
(0, cucumber_1.Then)('the {string} button should be enabled', async function (name) {
    await (0, test_1.expect)((0, locator_1.buttonByName)(this.page, name, this.config.selectors).first()).toBeEnabled();
});
(0, cucumber_1.Then)('the {string} button at index {int} should be enabled', async function (name, index) {
    await (0, test_1.expect)((0, locator_1.atIndex)((0, locator_1.buttonByName)(this.page, name, this.config.selectors), index)).toBeEnabled();
});
(0, cucumber_1.Then)('{string} should have value {string}', async function (name, expected) {
    await (0, test_1.expect)(await (0, ui_controls_1.readFieldValue)(this.page, name, this.config.selectors)).toBe(expected);
});
(0, cucumber_1.Then)('{string} should contain value {string}', async function (name, expected) {
    const actual = await (0, ui_controls_1.readFieldValue)(this.page, name, this.config.selectors);
    if (actual.includes(expected)) {
        return;
    }
    throw new Error(`Field "${name}" should contain value "${expected}" but found "${actual}".`);
});
(0, cucumber_1.Then)('{string} at index {int} should have value {string}', async function (name, index, expected) {
    await (0, test_1.expect)(await (0, ui_controls_1.readFieldValue)(this.page, name, this.config.selectors, index)).toBe(expected);
});
(0, cucumber_1.Then)('{string} at index {int} should contain value {string}', async function (name, index, expected) {
    const actual = await (0, ui_controls_1.readFieldValue)(this.page, name, this.config.selectors, index);
    if (actual.includes(expected)) {
        return;
    }
    throw new Error(`Field "${name}" at index ${index} should contain value "${expected}" but found "${actual}".`);
});
(0, cucumber_1.Then)('{string} should be read only', async function (name) {
    await (0, test_1.expect)(await (0, ui_controls_1.isFieldReadOnly)(this.page, name, this.config.selectors)).toBe(true);
});
(0, cucumber_1.Then)('{string} at index {int} should be read only', async function (name, index) {
    await (0, test_1.expect)(await (0, ui_controls_1.isFieldReadOnly)(this.page, name, this.config.selectors, index)).toBe(true);
});
(0, cucumber_1.Then)('the {string} tab should be active', async function (name) {
    await (0, test_1.expect)(await (0, ui_controls_1.isTabActive)(this.page, name, this.config.selectors)).toBe(true);
});
(0, cucumber_1.Then)('the {string} tab at index {int} should be active', async function (name, index) {
    await (0, test_1.expect)(await (0, ui_controls_1.isTabActive)(this.page, name, this.config.selectors, index)).toBe(true);
});
(0, cucumber_1.Then)('the dropdown {string} should contain exactly:', async function (name, dataTable) {
    await (0, ui_controls_1.assertDropdownOptions)(this.page, name, flattenDataTable(dataTable), 'exact', this.config.selectors);
});
(0, cucumber_1.Then)('the dropdown {string} should contain values:', async function (name, dataTable) {
    await (0, ui_controls_1.assertDropdownOptions)(this.page, name, flattenDataTable(dataTable), 'values', this.config.selectors);
});
(0, cucumber_1.Then)('the dropdown {string} at index {int} should contain exactly:', async function (name, index, dataTable) {
    await (0, ui_controls_1.assertDropdownOptions)(this.page, name, flattenDataTable(dataTable), 'exact', this.config.selectors, index);
});
(0, cucumber_1.Then)('the dropdown {string} at index {int} should contain values:', async function (name, index, dataTable) {
    await (0, ui_controls_1.assertDropdownOptions)(this.page, name, flattenDataTable(dataTable), 'values', this.config.selectors, index);
});
(0, cucumber_1.Given)(/^User check if element "([^"]*)" is "([^"]*)"(?: at index "([^"]*)")?$/, async function (field, visibility, index) {
    if (!this.page) {
        throw new Error('Cannot check element visibility before the Playwright page has been created.');
    }
    await (0, visibility_1.assertElementVisibility)(this.page, field, visibility, index, this.config.selectors);
});
(0, cucumber_1.Then)('the screen should match screenshot {string}', async function (screenshotPath) {
    const page = requirePage(this);
    await runScreenshotComparison(this, () => (0, screenshots_1.compareScreenScreenshot)(page, screenshotPath, screenshotOptions(this)));
});
(0, cucumber_1.Then)('element {string} should match screenshot {string}', async function (target, screenshotPath) {
    const page = requirePage(this);
    await runScreenshotComparison(this, () => (0, screenshots_1.compareElementScreenshot)(page, target, screenshotPath, screenshotOptions(this)));
});
(0, cucumber_1.Then)('element {string} at index {int} should match screenshot {string}', async function (target, index, screenshotPath) {
    const page = requirePage(this);
    await runScreenshotComparison(this, () => (0, screenshots_1.compareElementScreenshot)(page, target, screenshotPath, screenshotOptions(this, { index })));
});
(0, cucumber_1.Then)('element {string} should match screenshot {string} masking {string}', async function (target, screenshotPath, maskTargets) {
    const page = requirePage(this);
    await runScreenshotComparison(this, () => (0, screenshots_1.compareElementScreenshot)(page, target, screenshotPath, screenshotOptions(this, { mask: parseMaskTargets(maskTargets) })));
});
(0, cucumber_1.Then)('element {string} at index {int} should match screenshot {string} masking {string}', async function (target, index, screenshotPath, maskTargets) {
    const page = requirePage(this);
    await runScreenshotComparison(this, () => (0, screenshots_1.compareElementScreenshot)(page, target, screenshotPath, screenshotOptions(this, {
        index,
        mask: parseMaskTargets(maskTargets)
    })));
});
async function runScreenshotComparison(world, compare) {
    try {
        const result = await compare();
        await attachScreenshotArtifact(world, result.actualPath, 'Actual screenshot');
        if (result.diffPath) {
            await attachScreenshotArtifact(world, result.diffPath, 'Diff screenshot');
        }
    }
    catch (error) {
        if (error instanceof screenshots_1.ScreenshotComparisonError) {
            if (error.actualPath) {
                await attachScreenshotArtifact(world, error.actualPath, 'Actual screenshot');
            }
            if (error.diffPath) {
                await attachScreenshotArtifact(world, error.diffPath, 'Diff screenshot');
            }
        }
        throw error;
    }
}
async function attachScreenshotArtifact(world, filePath, label) {
    try {
        const payload = await promises_1.default.readFile(filePath);
        await world.attach(payload, 'image/png');
        await world.attach(`${label}: ${filePath}`, 'text/plain');
    }
    catch {
        // Best-effort attachment only; the comparison error should stay primary.
    }
}
function flattenDataTable(dataTable) {
    return dataTable.raw().flat().map((value) => value.trim()).filter(Boolean);
}
function requirePage(world) {
    if (!world.page) {
        throw new Error('Cannot compare screenshots before the Playwright page has been created.');
    }
    return world.page;
}
function screenshotOptions(world, overrides = {}) {
    return {
        expectedDir: world.config.screenshots.expectedDir,
        actualDir: world.config.screenshots.actualDir,
        diffDir: world.config.screenshots.diffDir,
        selectors: world.config.selectors,
        threshold: world.config.screenshots.threshold,
        maxDiffPixels: world.config.screenshots.maxDiffPixels,
        ...overrides
    };
}
function parseMaskTargets(value) {
    return value
        .split(',')
        .map((part) => part.trim())
        .filter(Boolean);
}
