document.addEventListener( "DOMContentLoaded", function () {

    // Функция перевода
    function __( str ) {
        return _( str, "ai.mod.php" );
    }


    const ai_page = document.querySelector( `#ai` );
    const header_el = ai_page.querySelector( `:scope > .header` );
    const chat = ai_page.querySelector( `.chat` );
    const prompt_el = ai_page.querySelector( `.side [name="prompt"]` );
    const plan_el   = ai_page.querySelector( `.side [name="plan"]` );
    let row_gap = 0;
    const user_panel = ai_page.querySelector( `:scope > .user` );
    const textarea = user_panel.querySelector( `textarea` );

    // Берем чат из localStorage в виде json-строки
    const chat_str = localStorage.getItem( "ai_chat" );
    let chat_arr;
    if ( chat_str ) {
        chat_arr = JSON.parse( chat_str );
    } else {
        chat_arr = [];
        localStorage.setItem( "ai_chat", JSON.stringify( chat_arr ) );
    }

    const chat_html = [];
    chat_arr.forEach( function( msg ) {
        chat_html.push( wrap_msg( msg ) );
    } );
    chat.innerHTML = chat_html.join( "" );

    // Удалить сообщение из чата
    chat.querySelectorAll( `.controls .del` ).forEach( function ( del ) {
        const msg_el = del.closest( `.msg` );
        const id_msg = Number( msg_el.getAttribute( "data-id" ) );
        del.addEventListener( "click", function() {
            msg_el.remove();
            // Обновляем массив и localStorage
            chat_arr = chat_arr.filter( msg => msg["id"] !== id_msg );
            localStorage.setItem( "ai_chat", JSON.stringify( chat_arr ) );
        } );
    } );

    function wrap_msg( msg ) {
        const controls = `<div class=controls><div class=role>${msg["role"]}</div><div class=del></div></div>`;
        const html = `
<div class='msg ${msg["role"]}' data-id=${msg["id"]}>
    ${controls}
    <div class=content>${escape_html( msg["content"] )}</div>
    ${controls}
</div>
`;
        return html;
    }

    function escape_html(str) {
        return str.replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
    }

    document.body.addEventListener( "ready", function( event ) { // Дать отработать рендерингу
        chat.style.scrollBehavior = "auto"; // Для быстрой промотки. Откл. анимацию.
        chat.scrollTop = chat.scrollHeight;
        chat.style.scrollBehavior = '';
        textarea.focus();
    } );

    // Получаем вычисленное значение row-gap (пиксели)
    row_gap = parseFloat( window.getComputedStyle( chat ).row_gap );

    // Настройки доступа к ИИ
    const endpoint_el = ai_page.querySelector( `input[name=endpoint]` );
    const model_el    = ai_page.querySelector( `input[name=model]` );
    const key_el      = ai_page.querySelector( `input[name=password]` );

    let endpoint = localStorage.getItem( "ai_endpoint" );
    if ( endpoint === null ) {
        endpoint = "http://127.0.0.1:1234/v1/chat/completions";
        localStorage.setItem( "ai_endpoint", endpoint );
    }
    endpoint_el.value = endpoint;

    let model = localStorage.getItem( "ai_model" );
    if ( model === null ) {
        model = "qwen/qwen3-coder-30b";
        localStorage.setItem( "ai_model", model );
    }
    model_el.value = model;

    let api_key = localStorage.getItem( "ai_api_key" );
    key_el.value = api_key;

    header_el.querySelector( `.button.save` ).addEventListener( "click", function () {
        endpoint = endpoint_el.value.trim();
        localStorage.setItem( "ai_endpoint", endpoint );
        model = model_el.value.trim();
        localStorage.setItem( "ai_model", model );
        api_key = key_el.value.trim();
        localStorage.setItem( "ai_api_key", api_key );
        notify_answer( { "notify": {
            "notify_html": __( "saved" ),
        } } );
    } );

    user_panel.querySelector( `.button.copy.demo` ).addEventListener( "click", function () {
        const data = { fn: "ai_get_cms_files", mod: "demo_for_ai.mod.php" };
        api( data, function( answer ) {
            if ( ! answer.result ) {
                return;
            }

            const r = copy_to_clipboard( answer.result.content );
            if ( r ) {
                const msg = __( "copyed" ) + ": " + data.mod + "<br>"
                 + __( "files" ) + `: ${answer.result.files_count}<br>`
                 + __( "lines" ) + `: ${answer.result.lines_count}<br>`
                 + __( "size_in_chars" ) + `: ${answer.result.size_in_chars}`;
                notify_answer( { "result": {
                    "notify_html": msg,
                } } );
            } else {
                notify_answer( { "error": {
                    "notify_html": __( "copy_error" ),
                } } );
            }
            textarea.focus();
        } );
    } );

    user_panel.querySelector( `.settings.button` ).addEventListener( "click", function () {
        ai_page.classList.toggle( "settings" );
    } );
    
    user_panel.querySelector( `.clear.button` ).addEventListener( "click", function () {
        chat_arr = [];
        localStorage.setItem( "ai_chat", JSON.stringify( chat_arr ) );
        chat.innerHTML = "";
        textarea.focus();
    } );

    textarea.addEventListener( "keydown", function ( event ) {
        if ( event.code === "Enter" && event.ctrlKey ) {
            user_panel.querySelector( `.send.button` ).click();
        }
    } );

    const controller = new AbortController(); // Для остановки запроса
    let requestStarted = false;
    user_panel.querySelector( `.send.button` ).addEventListener( "click", function () {
        textarea.focus(); // Потому что чуть ниже выход

        const content = textarea.value;
        if ( content.trim() === "" ) {
            return;
        }

        if ( ! endpoint || ! model ) {
            notify_answer( { "notify": {
                "notify_html": __( "ai_conf_error" ),
            } } );
            return;
        }
        
        // Отмотан ли чат в конец
        const atBottom = ( chat.scrollTop + chat.clientHeight ) >= chat.scrollHeight;

        const msg = {
            "id": new Date().getTime(),
            "role": "user",
            "content": content,
        };
        chat_arr.push( msg );

        localStorage.setItem( "ai_chat", JSON.stringify( chat_arr ) );
        chat.insertAdjacentHTML( "beforeend", wrap_msg( msg ) );
        textarea.value = "";
        
        // Если был отмотан в конец, то докручиваем
        if ( atBottom ) {
            chat.scrollTop = chat.scrollHeight;
        }

        // Промпт и план
        const system_msg = {
            "id": 0,
            "role": "system",
            "content": prompt_el.value + "\n\n" + plan_el.value,
        };

        const request = {
            "model": model,
            "messages": [ system_msg ].concat( chat_arr ),
        }
        const headers = {
            "Content-Type": "application/json",
        };
        if ( api_key ) {
            headers["Authorization"] = `Bearer ${api_key}`;
        }

        user_panel.classList.add( "think" );

        fetch( endpoint, {
            method: "POST",
            headers: headers,
            body: JSON.stringify( request ),
            signal: controller.signal,
        } ).then( response => {
            requestStarted = false;
            if ( ! response.ok ) {
                notify_answer( { "error": {
                    "notify_html": "Network error: " + response.status,
                } } );
                return Promise.reject( new Error( "Network error: " + response.status ) );
            }
            return response.json();
        } ).then( data => {
            user_panel.classList.remove( "think" );

            // Сохраняем ответ
            if ( data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content ) {
                const content = data.choices[0].message.content;
                const msg = {
                    "id": new Date().getTime(),
                    "role": "assistant",
                    "content": content,
                };

                chat_arr.push( msg );
                localStorage.setItem( "ai_chat", JSON.stringify( chat_arr ) );

                // Отмотан ли чат в конец
                const atBottom = (chat.scrollTop + chat.clientHeight) >= chat.scrollHeight;
                const oldScrollHeight = chat.scrollHeight;

                chat.insertAdjacentHTML( "beforeend", wrap_msg( msg ) );

                // Если был отмотан в конец, то докручиваем
                if ( atBottom ) {
                    const diffScrollHeight = chat.scrollHeight - oldScrollHeight;
                    const diffScrollTop = Math.min(chat.clientHeight, diffScrollHeight + row_gap );
                    chat.scrollTop += diffScrollTop;
                }
            }
        } ).catch( err => {
            if (err.name === 'AbortError') {
                console.log('Запрос отменён');
            }
            // Ошибка запроса к ИИ
            notify_answer( { "error": {
                "notify_html": err.message,
            } } );
            user_panel.classList.remove( "think" );
        } );
        
        setTimeout( () => {
            if ( ! controller.signal.aborted ) {
                requestStarted = true;
            }
        }, 1000 );
    } );

    user_panel.querySelector( `.stop.button` ).addEventListener( "click", function () {
        if ( requestStarted ) {
            if ( ! controller.signal.aborted ) {
                controller.abort();
            }
        }
    } );

    //#region rpompt и plan
    // Закрытие выпдающего списка
    document.body.addEventListener( "click", function( event ) {
        ai_page.querySelectorAll( `.select.widget` ).forEach( function( select ) {
            select.classList.remove( "open" );
        } );
    } );

    const select = ai_page.querySelector( `.select.widget` );
    const selected = select.querySelector( `.selected` );
    const value = selected.querySelector( `.value` );
    const input = select.querySelector( `input` );
    const options = select.querySelector( `.options .scrollable` );
    
    // Промпты
    let last_preset = localStorage.getItem( "ai_last_preset" );
    const presets_str = localStorage.getItem( "ai_presets" );
    let presets;
    if ( presets_str ) {
        presets = JSON.parse( presets_str );
    } else {
        presets = {};
        localStorage.setItem( "ai_presets", JSON.stringify( presets ) );
    }
    
    for ( let preset in presets ) {
        options.insertAdjacentHTML( "beforeend", `<div class=option><span class=preset>${preset}</span><span class=del></span></div>` );
        if ( preset === last_preset ) {
            last_preset = options.lastChild;
        }
    }

    // Открыть/закрыть список
    selected.addEventListener( "click", function( event ) {
        event.stopPropagation(); // Иначе сразу закрывается
        select.classList.toggle( "open" );
        input.focus();
    } );

    // Предотвратить закрытие при кликах в инпуте
    input.addEventListener( "click", function( event ) {
        event.stopPropagation();
    } );

    // Новый пресет (забирает к себе промпт и план)
    input.addEventListener( "keydown", function ( event ) {
        if ( event.code === "Enter" ) {
            const preset = input.value;
            input.value = "";
            value.innerText = preset;
            presets[preset] = {
                prompt: prompt_el.value,
                plan: plan_el.value,
            };
            options.insertAdjacentHTML( "beforeend", `<div class=option><span class=preset>${preset}</span><span class=del></span></div>` );
            options.lastChild.addEventListener( "click", option_click );
            localStorage.setItem( "ai_presets", JSON.stringify( presets ) );
            localStorage.setItem( "ai_last_preset", preset );
            select.classList.remove( "open" );
        }
    } );

    // Сохранение промпта
    prompt_el.addEventListener( "input", function ( event ) {
        const preset = value.innerText;
        if ( preset ) {
            presets[preset]["prompt"] = prompt_el.value;
            localStorage.setItem( "ai_presets", JSON.stringify( presets ) );
        }
    } );

    // Сохранение плана
    plan_el.addEventListener( "input", function ( event ) {
        const preset = value.innerText;
        if ( preset ) {
            presets[preset]["plan"] = plan_el.value;
            localStorage.setItem( "ai_presets", JSON.stringify( presets ) );
        }
    } );

    // Клики по опциям
    options.querySelectorAll( `.option` ).forEach( function ( option ) {
        option.addEventListener( "click", option_click );
        option.querySelector( `.del` ).addEventListener( "click", del_click );
    } );
    function option_click ( event ) {
        const preset = event.currentTarget.firstChild.innerText;
        value.innerText = preset;
        prompt_el.value = presets[preset]["prompt"];
        plan_el.value = presets[preset]["plan"];
        localStorage.setItem( "ai_last_preset", preset );
    }
    if ( last_preset ) {
        last_preset.click();
    }
    function del_click( event ) {
        event.stopPropagation();
        const preset = event.currentTarget.previousElementSibling.innerText;
        const option = event.currentTarget.parentElement;
        if ( value.innerText === preset ) {
            value.innerText = "";
            prompt_el.value = "";
            plan_el.value = "";
        }
        option.remove();
        delete presets[preset];
        localStorage.setItem( "ai_presets", JSON.stringify( presets ) );
    }

    //#endregion rpompt и plan

});