"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CardBlockFormService = void 0;
const test_1 = require("@playwright/test");
const logger_1 = require("../../../utils/logger");
const timeouts_1 = require("../../../timeouts");
const FormDataFilterUtils_1 = require("../../shared/form/FormDataFilterUtils");
const FormFlowService_1 = require("../../shared/form/FormFlowService");
class CardBlockFormService {
    constructor(deps) {
        this.deps = deps;
    }
    createFormFlow(blockKey) {
        return new FormFlowService_1.FormFlowService({
            getRole: () => this.deps.getRole(),
            findModalConfig: (modalWindowKey) => {
                try {
                    return this.deps.findBlockModalWindowConfig(blockKey, modalWindowKey);
                }
                catch {
                    return undefined;
                }
            },
            openModal: (modalWindowKey) => this.deps.openBlockModalWindow(blockKey, modalWindowKey),
            getModalFormLocators: (modalWindowKey) => this.deps.getBlockModalWindowFormLocators(blockKey, modalWindowKey),
            getModalButtons: (modalWindowKey) => this.deps.getBlockModalWindowButtons(blockKey, modalWindowKey),
            getSaveButtonKey: (modalWindowKey) => this.deps.findBlockModalWindowConfig(blockKey, modalWindowKey).saveButtonKey,
            performSave: (button, stepName) => this.deps.performModalTerminalActionToCloseModalWindow(button, stepName),
            formHelperFillFormFields: (data, locators, context) => this.deps.formHelperFillFormFields(data, locators, context),
            verifyTableRow: (rowKey, expectedRowData, isFirstRow, onRowFound) => {
                const tableLabel = this.deps.getBlockTableLabel(blockKey);
                return this.deps.verifyTableRowInBlock(rowKey, expectedRowData, tableLabel, isFirstRow, onRowFound);
            },
        }, 'CardBlockFormService');
    }
    // Вспомогательные private методы
    // ----------------------------------------------------------------------------------------------
    filterFormFields(formFields, modalConfig) {
        return (0, FormDataFilterUtils_1.filterFormFieldsData)(formFields, modalConfig, `${this.constructor.name}.filterFormFields`);
    }
    // Вспомогательный метод для определения текущего состояния редактируемости блока
    async getCurrentBlockState(editButton, saveButton, cancelButton) {
        try {
            const isSaveVisible = await saveButton.isVisible();
            // Если Save видна - значит в режиме редактирования
            if (isSaveVisible) {
                return 'editable';
            }
            // Дополнительная проверка через Cancel или Edit
            if (cancelButton && await cancelButton.isVisible().catch(() => false)) {
                return 'editable';
            }
            const isEditVisible = await editButton.isVisible();
            if (!isEditVisible) {
                return 'editable';
            }
            return 'notEditable';
        }
        catch (error) {
            logger_1.logger.warn(`Ошибка при определении состояния блока: ${error}`);
            return 'notEditable';
        }
    }
    async verifyBlockButtonsState(editButton, saveButton, cancelButton, expectedState = 'view') {
        if (expectedState === 'edit') {
            // Состояние режима редактирования
            await test_1.expect.soft(editButton).toBeHidden({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            await test_1.expect.soft(saveButton).toBeVisible({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            if (cancelButton) {
                await test_1.expect.soft(cancelButton).toBeVisible({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            }
        }
        else {
            // Обычное состояние (режим просмотра)
            await test_1.expect.soft(editButton).toBeVisible({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            await test_1.expect.soft(saveButton).toBeHidden({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            if (cancelButton) {
                await test_1.expect.soft(cancelButton).toBeHidden({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
            }
        }
    }
    async fillBlockForm(blockKey, filteredFields, blockFormLocators) {
        const { filteredTextFieldsData, filteredComboboxFieldsData, filteredFileFieldsData, filteredRadioButtonsData, filteredCheckboxesData, filteredToggleButtonsData, filteredDaDataFieldsData, filteredMultiComboboxFieldsData } = filteredFields;
        await this.deps.formHelperFillFormFields({
            textFieldsData: filteredTextFieldsData,
            comboboxFieldsData: filteredComboboxFieldsData,
            radioButtonsData: filteredRadioButtonsData,
            fileFieldsData: filteredFileFieldsData,
            daDataFieldsData: filteredDaDataFieldsData,
            checkboxesData: filteredCheckboxesData,
            toggleButtonsData: filteredToggleButtonsData,
            multiComboboxFieldsData: filteredMultiComboboxFieldsData
        }, blockFormLocators, `блоке ${blockKey}`);
    }
    // --------------------------------------------------------------------------------------------------------
    // Публичные методы для использования
    // --------------------------------------------------------------------------------------------------------
    async switchBlockEditableState(blockKey, targetState, buttonKeys, logContext = 'BaseCard.switchBlockEditableState') {
        const role = this.deps.getRole();
        this.deps.validateBlockParams(blockKey, role);
        const blockButtons = this.deps.getBlockButtons(blockKey);
        if (!blockButtons) {
            throw new Error(`Кнопки блока ${blockKey} не найдены`);
        }
        const editButtonKey = buttonKeys?.Edit || 'Edit';
        const saveButtonKey = buttonKeys?.Save || 'Save';
        const cancelButtonKey = buttonKeys?.Cancel || 'Cancel';
        const editButton = blockButtons[editButtonKey];
        const saveButton = blockButtons[saveButtonKey];
        const cancelButton = blockButtons[cancelButtonKey];
        if (!editButton) {
            throw new Error(`Кнопка редактирования "${editButtonKey}" не найдена в блоке ${blockKey}`);
        }
        if (!saveButton) {
            throw new Error(`Кнопка сохранения "${saveButtonKey}" не найдена в блоке ${blockKey}`);
        }
        logger_1.logger.debug(`Переключение блока ${blockKey} в состояние ${targetState} для роли ${role}`, `${logContext}`);
        await test_1.test.step(`Переключение блока ${blockKey} в состояние ${targetState}`, async () => {
            // Проверяем текущее состояние
            const currentState = await this.getCurrentBlockState(editButton, saveButton, cancelButton);
            logger_1.logger.debug(`Текущее состояние блока ${blockKey}: ${currentState}`, logContext);
            if (currentState === targetState) {
                logger_1.logger.debug(`Блок ${blockKey} уже находится в состоянии ${targetState}, переключение не требуется`, logContext);
                return;
            }
            // Выполняем переключение
            if (targetState === 'editable') {
                // Переход в режим редактирования
                await editButton.click();
                // Проверяем результат
                await this.verifyBlockButtonsState(editButton, saveButton, cancelButton, 'edit');
                logger_1.logger.debug(`Блок ${blockKey} переключен в режим редактирования`, logContext);
            }
            else {
                // Переход в режим просмотра
                if (cancelButton) {
                    await cancelButton.click();
                    logger_1.logger.debug(`Блок ${blockKey} переключен в режим просмотра через кнопку Cancel`, logContext);
                }
                else {
                    await this.deps.executeWithErrorCheck(`сохранении блока ${blockKey}`, async () => {
                        await saveButton.click();
                    });
                    logger_1.logger.debug(`Блок ${blockKey} переключен в режим просмотра через кнопку Save`, logContext);
                }
                // Проверяем результат
                await this.verifyBlockButtonsState(editButton, saveButton, cancelButton, 'view');
            }
        });
        logger_1.logger.info(`Блок ${blockKey} успешно переключен в состояние ${targetState}`, `${logContext}`);
    }
    async checkFormFieldsState(blockConfig, blockFormLocators, mode) {
        const shouldBeDisabled = mode === 'notEditable';
        const fieldConfigs = [
            { locators: blockFormLocators.textFieldsLocators, config: blockConfig.textFields },
            { locators: blockFormLocators.comboboxFieldsLocators, config: blockConfig.comboboxFields },
            { locators: blockFormLocators.toggleButtonsLocators, config: blockConfig.toggleButtons },
            { locators: blockFormLocators.multiComboboxFieldsLocators, config: blockConfig.multiComboboxFields },
            { locators: blockFormLocators.radioButtonsLocators, config: blockConfig.radioButtons },
            { locators: blockFormLocators.checkboxesLocators, config: blockConfig.checkboxes }
        ];
        for (const { locators, config } of fieldConfigs) {
            if (!locators || !config)
                continue;
            for (const fieldConfig of config) {
                const field = locators[fieldConfig.name];
                if (field) {
                    if (shouldBeDisabled) {
                        await test_1.expect.soft(field).toBeDisabled({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
                    }
                    else {
                        await test_1.expect.soft(field).toBeEnabled({ timeout: (0, timeouts_1.getTimeouts)().EXPECT });
                    }
                }
            }
        }
    }
    /**
     * Открывает модальное окно блока, заполняет форму и сохраняет.
     * @param blockKey — ключ блока
     * @param modalWindowKey — ключ модального окна из конфигурации блока
     * @param formFields — данные для заполнения полей формы
     */
    async fillBlockModalForm(blockKey, modalWindowKey, formFields, _logContext = 'BaseCard.fillBlockModalForm') {
        if (!blockKey.trim()) {
            throw new Error('blockKey обязателен');
        }
        this.deps.validateBlockParams(blockKey, this.deps.getRole());
        await this.createFormFlow(blockKey).fillModalForm(modalWindowKey, formFields);
    }
    /**
     * Заполняет поля уже открытой модальной формы блока (без open/save).
     */
    async fillOpenBlockModalFormFields(blockKey, modalWindowKey, formFields, _logContext = 'BaseCard.fillOpenBlockModalFormFields') {
        if (!blockKey.trim()) {
            throw new Error('blockKey обязателен');
        }
        this.deps.validateBlockParams(blockKey, this.deps.getRole());
        await this.createFormFlow(blockKey).fillOpenModalFormFields(modalWindowKey, formFields);
    }
    /**
     * Заполняет поля инлайн-формы блока по ключу конфигурации.
     * @param blockKey — ключ блока
     * @param inlineFormKey — ключ инлайн-формы
     * @param formFields — данные полей формы
     * @param logContext — контекст для логирования
     */
    async fillInlineBlockForm(blockKey, inlineFormKey, formFields, logContext = 'BaseCard.fillInlineBlockForm') {
        if (!blockKey.trim()) {
            throw new Error('blockKey обязателен');
        }
        if (!inlineFormKey.trim()) {
            throw new Error('inlineFormKey обязателен');
        }
        const role = this.deps.getRole();
        this.deps.validateBlockParams(blockKey, role);
        const blockConfig = this.deps.findBlockInlineFormConfig(blockKey, inlineFormKey);
        const blockFormLocators = this.deps.getBlockFormWithFieldsLocators(blockKey, inlineFormKey);
        logger_1.logger.debug(`Заполнение инлайн-формы ${inlineFormKey} блока ${blockKey} для роли ${role}`, `${logContext}`);
        await test_1.test.step(`Заполнение инлайн-формы ${inlineFormKey} блока ${blockKey}`, async () => {
            const filteredFields = this.filterFormFields(formFields, blockConfig);
            logger_1.logger.debug(`Поля формы ${inlineFormKey} блока ${blockKey} отфильтрованы`, logContext);
            await this.fillBlockForm(blockKey, filteredFields, blockFormLocators);
            logger_1.logger.debug(`Инлайн-форма ${inlineFormKey} блока ${blockKey} заполнена`, logContext);
        });
        logger_1.logger.info(`Заполнение инлайн-формы ${inlineFormKey} блока ${blockKey} завершено успешно`, `${logContext}`);
    }
    /**
     * Проверяет значения полей инлайн-формы блока по ключу конфигурации.
     * @param blockKey — ключ блока
     * @param inlineFormKey — ключ инлайн-формы
     * @param expectedFieldsValues — ожидаемые значения полей
     * @param logContext — контекст для логирования
     */
    async checkInlineBlockFormValues(blockKey, inlineFormKey, expectedFieldsValues, logContext = 'BaseCard.checkInlineBlockFormValues') {
        const role = this.deps.getRole();
        this.deps.validateBlockParams(blockKey, role);
        logger_1.logger.debug(`Проверка значений полей инлайн-формы ${inlineFormKey} блока ${blockKey} для роли ${role}`, logContext);
        await test_1.test.step(`Проверка значений полей инлайн-формы ${inlineFormKey} блока ${blockKey}`, async () => {
            const blockFormLocators = this.deps.getBlockFormWithFieldsLocators(blockKey, inlineFormKey);
            await this.deps.formHelperVerifyFormFieldsValues(expectedFieldsValues, blockFormLocators, `инлайн-формы ${inlineFormKey} блока ${blockKey}`);
        });
        logger_1.logger.info(`Проверка значений полей блока ${blockKey} завершена успешно`, logContext);
    }
}
exports.CardBlockFormService = CardBlockFormService;
