window.IntecKosmosReviewsAddCatalogDefault ??= class
{
    /**
     * @param {HTMLDivElement} root
     * @param {string} path
     * @param {{files: {empty: string, count: string}, consent: {show: boolean, required: boolean, inputName: string}, mailing: {show: boolean, required: boolean, inputName: string}}} messages
     * @param {{url: string, siteId: string, template: string, parameters: string}} params
     */
    static init(root, path, messages, params)
    {
        const form = root.querySelector('form');
        const opener = root.querySelector('[data-role="form-opener"]');
        const wrapper = root.querySelector('[data-role="form-wrapper"]');
        const marks = root.querySelector('[data-role="form-marks"]');
        const captcha = root.querySelector('[data-role="form-captcha"]');
        const files = root.querySelectorAll('[data-role="form-file"]');

        if (opener !== null && wrapper !== null)
            IntecKosmosReviewsAddCatalogDefault.initOpener(opener, wrapper);

        if (marks !== null)
            IntecKosmosReviewsAddCatalogDefault.initRating(marks);

        if (captcha !== null)
            IntecKosmosReviewsAddCatalogDefault.initCaptcha(captcha, path);

        if (files.length > 0)
            files.forEach(file => IntecKosmosReviewsAddCatalogDefault.initFiles(file, messages.files));

        if (messages.consent?.show || messages.mailing?.show)
            IntecKosmosReviewsAddCatalogDefault.initCheckboxes(root, form, messages);

        if (form !== null)
            IntecKosmosReviewsAddCatalogDefault.initAjax(root, form, params);
    }

    /**
     * @param {HTMLButtonElement} opener
     * @param {HTMLDivElement} wrapper
     */
    static initOpener(opener, wrapper)
    {
        opener.addEventListener('click', () => {
            if (wrapper.getAttribute('data-expanded') === 'true')
                wrapper.setAttribute('data-expanded', 'false');
            else
                wrapper.setAttribute('data-expanded', 'true');
        });
    }
    
    /**
     * @param {HTMLDivElement} root
     */
    static initRating(root)
    {
        /** @var {HTMLInputElement} input */
        const input = root.querySelector('input[type="hidden"]');
        /** @var {NodeListOf<SVGElement>} marks */
        const marks = root.querySelectorAll('svg[data-role="form-mark"]');
        /** @var {HTMLSpanElement} description */
        const description = root.querySelector('[data-role="form-mark-description"]');

        if (marks.length === 0)
            return;

        /**
         * @param {number} current
         */
        const activate = (current) => {
            marks.forEach((mark, index) => {
                if (index <= current) {
                    mark.setAttribute('data-state', 'active');

                    if (index === current)
                        description.innerHTML = mark.getAttribute('data-name');
                } else
                    mark.setAttribute('data-state', 'disabled');
            })
        };

        const reset = () => {
            let passed = false;

            marks.forEach((mark) => {
                mark.setAttribute('data-state', passed ? 'disabled' : 'active');

                if (mark.getAttribute('data-value') === input.getAttribute('value')) {
                    passed = true;
                    description.innerHTML = mark.getAttribute('data-name');
                }
            });
        };

        marks.forEach((mark, index) => {
            mark.addEventListener('mouseenter', () => {
                activate(index);
            });
            mark.addEventListener('mouseleave', () => {
                reset();
            });
            mark.addEventListener('click', () => {
                input.setAttribute('value', mark.getAttribute('data-value'));
            });
        });

        reset();
    }

    /**
     * @param {HTMLDivElement} root
     * @param {string} path
     */
    static initCaptcha(root, path)
    {
        const request = new XMLHttpRequest();
        const awaiting = false;
        /** @var {HTMLButtonElement} button */
        const button = root.querySelector('button')

        if (button === null)
            return;

        button.addEventListener('click', () => {
            if (awaiting)
                return;

            /** @var {SVGElement} svg */
            const svg = button.querySelector('svg');

            if (svg !== null)
                svg.classList.add('fx-rotate');

            request.open('POST', path + '/ajax.php');
            request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            request.addEventListener('readystatechange', () => {
                if (request.readyState === 4) {
                    if (request.status === 200) {
                        root.querySelector('img')?.setAttribute('src', '/bitrix/tools/captcha.php?captcha_sid=' + request.response);
                        root.querySelector('input[type="hidden"]')?.setAttribute('value', request.response);
                    }

                    if (svg !== null)
                        svg.classList.remove('fx-rotate');
                }
            });
            request.send();
        });
    }

    /**
     * @param {HTMLSpanElement} root
     * @param {{empty: string, count: string}} messages
     */
    static initFiles(root, messages)
    {
        /** @var {HTMLInputElement} input */
        const input = root.querySelector('input[type="file"]');
        const description = root.querySelector('[data-role="form-file-count"]');

        root.addEventListener('click', () => input.click());
        input.addEventListener('change', () => {
            if (input.files.length > 0)
                description.innerHTML = `${messages.count} ${input.files.length}`;
            else
                description.innerHTML = messages.empty;
        });
    }

    /**
     * @param {HTMLDivElement} root
     * @param {HTMLFormElement} form
     * @param {{show: boolean, required: boolean, inputName: string}} consent
     * @param {{show: boolean, required: boolean, inputName: string}} mailing
     */
    static initCheckboxes(root, form, {consent, mailing})
    {
        if (!form)
            return;

        const submitButton = form.querySelector('button[type="submit"]');
        if (!submitButton)
            return;

        const $ = application.libraries.load('$');
        const consentRequired = consent?.show && consent?.required;
        const mailingRequired = mailing?.show && mailing?.required;

        // Если нет обязательных чекбоксов, выходим
        if (!consentRequired && !mailingRequired)
            return;

        // Функция для поиска чекбоксов
        const findCheckboxes = () => {
            let consentElement = null;
            let mailingElement = null;

            if (consent?.show && consent?.inputName) {
                consentElement = form.querySelector('input[name="' + consent.inputName + '"]') ||
                                 root.querySelector('input[name="' + consent.inputName + '"]');
            }

            if (mailing?.show && mailing?.inputName) {
                mailingElement = form.querySelector('input[name="' + mailing.inputName + '"]') ||
                                 root.querySelector('input[name="' + mailing.inputName + '"]');
            }

            return { consentElement, mailingElement };
        };

        // Функция обновления состояния кнопки
        const updateSubmitButton = () => {
            const { consentElement, mailingElement } = findCheckboxes();
            let canSubmit = true;

            if (consentRequired && consentElement) {
                canSubmit = canSubmit && consentElement.checked;
            }

            if (mailingRequired && mailingElement) {
                canSubmit = canSubmit && mailingElement.checked;
            }

            submitButton.disabled = !canSubmit;
        };

        // Обработчик изменений на форме
        $(form).on('change', (event) => {
            if (event.target && event.target.type === 'checkbox') {
                const { consentElement, mailingElement } = findCheckboxes();
                if (event.target === consentElement || event.target === mailingElement) {
                    updateSubmitButton();
                }
            }
        });

        // Проверка при отправке формы
        $(form).on('submit', (event) => {
            const { consentElement, mailingElement } = findCheckboxes();
            let canSubmit = true;

            if (consentRequired && consentElement) {
                canSubmit = canSubmit && consentElement.checked;
            }

            if (mailingRequired && mailingElement) {
                canSubmit = canSubmit && mailingElement.checked;
            }

            if (!canSubmit) {
                event.preventDefault();
                return false;
            }
        });

        // Первоначальная проверка с задержкой для загрузки компонента
        setTimeout(updateSubmitButton, 200);
        setTimeout(updateSubmitButton, 1000);
    }

    /**
     * @returns {string}
     */
    static getCsrfToken()
    {
        if (typeof BX !== 'undefined' && typeof BX.bitrix_sessid === 'function')
            return BX.bitrix_sessid();

        if (typeof application !== 'undefined' && application.options?.site?.csrf)
            return application.options.site.csrf;

        return '';
    }

    /**
     * @param {HTMLDivElement} root
     * @param {HTMLFormElement} form
     * @param {{url: string, siteId: string, template: string, parameters: string}} request
     */
    static initAjax(root, form, request)
    {
        const axios = application.libraries.load('axios');

        form.addEventListener('submit', event => {
            event.preventDefault();
            form.setAttribute('data-awaiting', 'true');

            const data = new FormData(form);
            const csrf = IntecKosmosReviewsAddCatalogDefault.getCsrfToken();

            data.set('siteId', request.siteId);
            data.set('template', request.template);
            data.set('parameters', request.parameters);

            if (csrf !== '')
                data.set('sessid', csrf);

            const headers = {
                'Content-Type': 'multipart/form-data',
                'Bx-Ajax': true
            };

            if (csrf !== '')
                headers['X-Bitrix-Csrf-Token'] = csrf;

            axios.post(
                request.url,
                data,
                {
                    headers: headers,
                    responseType: 'json'
                }
            ).then(response => {
                const parent = root.parentNode;

                parent.innerHTML = response.data.form;

                const scripts = parent.querySelectorAll('script');

                scripts.forEach(script => {
                    eval(script.innerHTML);
                    script.remove();
                });
            }).finally(() => {
                form.removeAttribute('data-awaiting');
            });
        });
    }
};