"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BasePage = void 0;
const test_1 = require("@playwright/test");
const logger_1 = require("../../utils/logger");
const timeouts_1 = require("../../timeouts");
const notification_messages_1 = require("../../notification.messages");
const BasePage_locators_1 = require("./BasePage.locators");
const FormHelper_1 = require("./helpers/FormHelper/FormHelper");
const RowActionsHelper_1 = require("./helpers/RowActionsHelper/RowActionsHelper");
const CertificateHelper_1 = require("./helpers/CertificateHelper");
const TextUtils_1 = require("./utils/TextUtils");
const allure_utils_1 = require("../../utils/allure-utils");
class BasePage {
    constructor(page) {
        this.page = page;
        const locators = (0, BasePage_locators_1.createBasePageLocators)(page);
        this.ModalWindowBody = locators.ModalWindowBody;
        this.modalDialog = locators.ModalDialog;
        this.commonModalWindowButtons = locators.commonModalWindowButtons;
        this.orgCoreTextFields = locators.orgCoreTextFields;
        this.userCoreTextFields = locators.userCoreTextFields;
        // Инициализация helpers
        this.formHelper = new FormHelper_1.FormHelper(page);
        this.rowActionsHelper = new RowActionsHelper_1.RowActionsHelper(page, this.formHelper, () => this.tryFindErrorMessage(), () => this.confirmAction(), this.ModalWindowBody);
        this.certificateHelper = new CertificateHelper_1.CertificateHelper(page);
        this.textUtils = new TextUtils_1.TextUtils();
    }
    /**
     * Устанавливает роль пользователя для Page-объекта.
     * Рекомендуется вызывать из фикстур перед использованием страницы/карточки.
     */
    setRole(role) {
        this.role = role;
    }
    /**
     * Возвращает установленную роль или кидает понятную ошибку, если роль не задана.
     */
    getRoleOrThrow() {
        if (!this.role) {
            throw new Error(`Роль не установлена для ${this.constructor.name}. Вызовите setRole(role) в фикстуре перед использованием методов, зависящих от роли.`);
        }
        return this.role;
    }
    /**
     * Получить общие локаторы модальных окон
     * @returns Record с общими локаторами кнопок модальных окон
     */
    getCommonModalWindowButtons() {
        return this.commonModalWindowButtons;
    }
    /** Возвращает общий локатор модального диалога для использования в локаторах страниц */
    getModalDialog() {
        return this.modalDialog;
    }
    /**
     * Получить общие локаторы полей данных о организации
     * @returns Record с общими локаторами кнопок модальных окон
     */
    getOrgCoreTextFields() {
        return this.orgCoreTextFields;
    }
    /**
     * Получить общие локаторы полей данных пользователя
     * @returns Record с общими локаторами кнопок модальных окон
     */
    getUserCoreTextFields() {
        return this.userCoreTextFields;
    }
    /**
     * Переход на страницу с обработкой ошибок
     * @param path - путь к странице
     */
    async goto(path) {
        try {
            await this.page.goto(path);
            logger_1.logger.debug(`Успешный переход на страницу: ${path}`, `${this.constructor.name}.goto`);
        }
        catch (error) {
            logger_1.logger.error(`Ошибка при переходе на ${path}: ${error}`, `${this.constructor.name}.goto`);
            throw error;
        }
    }
    /**
     * Обновление страницы
     */
    async reloadPage() {
        await test_1.test.step(`Обновление страницы`, async () => {
            try {
                await this.page.reload();
                logger_1.logger.debug(`Страница обновлена`, `${this.constructor.name}.reloadPage`);
            }
            catch (error) {
                logger_1.logger.error(`Ошибка при обновлении страницы: ${error}`, `${this.constructor.name}.reloadPage`);
                throw error;
            }
        });
    }
    /**
   * Прокрутка к элементу
   */
    async scrollToElement(locator) {
        await locator.waitFor({ state: 'visible', timeout: timeouts_1.TIMEOUTS.NAVIGATION });
        await locator.scrollIntoViewIfNeeded({ timeout: timeouts_1.TIMEOUTS.ACTION });
    }
    /**
     * Приватный метод для обработки ошибок, всплывших на UI
     * @returns Список видимых ошибок
     */
    async findVisibleErrors() {
        const errorMessages = Object.values(notification_messages_1.ERROR_MESSAGES);
        const visibilityResults = await Promise.all(errorMessages.map(async (errorMessage) => ({
            message: errorMessage,
            visible: await this.page.getByText(errorMessage).isVisible(),
        })));
        return visibilityResults
            .filter(r => r.visible)
            .map(r => r.message);
    }
    /**
     * Поиск ошибок на UI
     * Применяется для обработки ошибки на пограничных действиях в других методах
     * @returns Массив обнаруженных ошибок или void
     */
    async tryFindErrorMessage() {
        const visibleErrors = await this.findVisibleErrors();
        if (visibleErrors.length > 0) {
            return visibleErrors;
        }
    }
    /**
     * Проверяет на отсутствие ошибок
     * Например, после перехода на страницу
     */
    async assertNoErrorMessages() {
        await test_1.test.step('Проверка отсутствия ошибок', async () => {
            const visibleErrors = await this.findVisibleErrors();
            if (visibleErrors.length > 0) {
                throw new Error(`Обнаружены уведомления об ошибках на странице: "${visibleErrors.join('"; "')}". URL: ${this.page.url()}`);
            }
            logger_1.logger.debug(`Уведомления об ошибках отсутствуют`, `${this.constructor.name}.assertNoErrorMessages`);
        });
    }
    /**
     * Выполняет терминальное действие в модальном окне: нажатие кнопки (Сохранить, Закрыть и т.п.),
     * ожидание скрытия модального окна и проверка отсутствия сообщений об ошибках.
     * @param terminalButton - локатор кнопки терминального действия (Сохранить, Закрыть и т.д.)
     * @param modalWindowBody - локатор тела модального окна
     * @param stepName - название шага в отчёте (по умолчанию "Терминальное действие модального окна")
     * @returns true если модальное окно успешно закрыто, false в случае ошибки
     */
    async performModalTerminalActionToCloseModalWindow(terminalButton, modalWindowBody, stepName = 'Терминальное действие модального окна') {
        logger_1.logger.debug(stepName, `${this.constructor.name}.performModalTerminalActionToCloseModalWindow`);
        try {
            await test_1.test.step(stepName, async () => {
                await terminalButton.click();
                await this.assertNoErrorMessages();
                await modalWindowBody.waitFor({ state: 'hidden', timeout: timeouts_1.TIMEOUTS.MODAL_WINDOW_WAIT });
            });
            logger_1.logger.info(`Модальное окно успешно закрыто: ${stepName}`, `${this.constructor.name}.performModalTerminalAction`);
        }
        catch (error) {
            logger_1.logger.error(`Ошибка при выполнении терминального действия "${stepName}": ${error}`, `${this.constructor.name}.performModalTerminalAction`);
            let errors;
            errors = await this.tryFindErrorMessage();
            if (errors) {
                await (0, allure_utils_1.screenshotOnFailure)(this.page);
                throw new Error(`Обнаружены уведомления об ошибках на странице: "${errors.join('"; "')}". URL: ${this.page.url()}`);
            }
            await (0, allure_utils_1.screenshotOnFailure)(this.page);
            throw new Error('Модальное окно не было закрыто.');
        }
    }
    /**
     * Подтверждение действия в всплывающем диалоге.
     */
    async confirmAction() {
        const confirmButton = this.page.getByRole('dialog').getByRole('button', { name: 'Подтвердить' });
        await test_1.test.step('Подтверждение действия', async () => {
            if (await confirmButton.isVisible({ timeout: timeouts_1.TIMEOUTS.ACTION })) {
                await this.performModalTerminalActionToCloseModalWindow(confirmButton, this.ModalWindowBody, 'Подтверждение действия');
            }
        });
    }
    async checkPageTitle(title) {
        await test_1.test.step(`Проверка заголовка страницы "${title}"`, async () => {
            await this.page.waitForLoadState('networkidle', { timeout: timeouts_1.TIMEOUTS.PAGE_LOAD });
            await (0, test_1.expect)(this.page).toHaveTitle(title);
        });
    }
    async checkSuccessMessage(message) {
        await test_1.test.step(`Проверка сообщения об успешном выполнении "${message}"`, async () => {
            const successMessage = notification_messages_1.SUCCESS_MESSAGES[message];
            if (!successMessage) {
                throw new Error(`Сообщение об успешном выполнении "${message}" не найдено в константе SUCCESS_MESSAGES`);
            }
            await (0, test_1.expect)(this.page.getByText(successMessage).first()).toBeVisible();
        });
    }
    // =========================
    // Методы работы с действиями над строкой
    // =========================
    /**
     * Публичные обертки для методов RowActionsHelper
     */
    async openRowActionsMenuBase(menuButtonLocator) {
        return this.rowActionsHelper.openRowActionsMenuBase(menuButtonLocator);
    }
    async closeRowActionsMenuBase() {
        return this.rowActionsHelper.closeRowActionsMenuBase();
    }
    async clickRowActionBase(actionKey, rowActionsConfig, rowActionButtons = null, rowActionMenuItems = null) {
        return this.rowActionsHelper.clickRowActionBase(actionKey, rowActionsConfig, rowActionButtons, rowActionMenuItems);
    }
    async checkRowActionsBase(rowActionsConfig, rowActionButtons = null, rowActionMenuItems = null) {
        return this.rowActionsHelper.checkRowActionsBase(rowActionsConfig, rowActionButtons, rowActionMenuItems);
    }
    async editRowBase(rowActionsConfig, rowActionButtons = null, rowActionMenuItems = null, modalWindowBody) {
        return this.rowActionsHelper.editRowBase(rowActionsConfig, rowActionButtons, rowActionMenuItems, modalWindowBody);
    }
    async viewRowBase(rowActionsConfig, rowActionButtons = null, rowActionMenuItems = null, modalWindowBody) {
        return this.rowActionsHelper.viewRowBase(rowActionsConfig, rowActionButtons, rowActionMenuItems, modalWindowBody);
    }
    async deleteRowBase(rowActionsConfig, rowActionButtons = null, rowActionMenuItems = null, confirmDelete = true) {
        return this.rowActionsHelper.deleteRowBase(rowActionsConfig, rowActionButtons, rowActionMenuItems, confirmDelete);
    }
    async editRowAndVerifyBase(editRowFn, formFields, getModalFormLocators, getModalWindowButtons, saveButtonKey, verifyFn) {
        return this.rowActionsHelper.editRowAndVerifyBase(editRowFn, formFields, getModalFormLocators, getModalWindowButtons, saveButtonKey, (btn, body, name) => this.performModalTerminalActionToCloseModalWindow(btn, body, name), verifyFn);
    }
    async viewRowAndVerifyBase(viewRowFn, expectedData, getModalWindowInputs, getModalWindowButtons) {
        return this.rowActionsHelper.viewRowAndVerifyBase(viewRowFn, expectedData, getModalWindowInputs, getModalWindowButtons, (btn, body, name) => this.performModalTerminalActionToCloseModalWindow(btn, body, name));
    }
    async deleteRowAndVerifyBase(findRowFn, deleteRowFn, findRowSilentFn, rowData) {
        return this.rowActionsHelper.deleteRowAndVerifyBase(findRowFn, deleteRowFn, findRowSilentFn, rowData);
    }
}
exports.BasePage = BasePage;
