import './styles/help.scss';

document.addEventListener('DOMContentLoaded', () => {
    initSuggest();
    initFeedback();
    initAssistant();
});

function initSuggest(): void {
    const input = document.querySelector<HTMLInputElement>('#help-search-q');
    const list = document.querySelector<HTMLUListElement>('#help-suggest');
    const suggestUrl = input?.dataset.suggestUrl;
    if (!input || !list || !suggestUrl) {
        return;
    }

    let timer: number | undefined;

    const hide = () => {
        list.hidden = true;
        list.innerHTML = '';
    };

    const render = (items: Array<{ title: string; url: string }>) => {
        if (!items.length) {
            hide();
            return;
        }
        list.innerHTML = items
            .map(
                (item) =>
                    `<li><a href="${item.url}">${item.title.replace(/</g, '&lt;')}</a></li>`
            )
            .join('');
        list.hidden = false;
    };

    input.addEventListener('input', () => {
        window.clearTimeout(timer);
        const q = input.value.trim();
        if (q.length < 2) {
            hide();
            return;
        }
        timer = window.setTimeout(async () => {
            try {
                const res = await fetch(`${suggestUrl}?q=${encodeURIComponent(q)}`, {
                    headers: { Accept: 'application/json' },
                });
                if (!res.ok) {
                    hide();
                    return;
                }
                const data = await res.json();
                render(data.suggestions || []);
            } catch {
                hide();
            }
        }, 220);
    });

    input.addEventListener('keydown', (event) => {
        if (event.key === 'Escape') {
            hide();
        }
    });

    document.addEventListener('click', (event) => {
        if (!(event.target instanceof Node)) {
            return;
        }
        if (!list.contains(event.target) && event.target !== input) {
            hide();
        }
    });
}

function initFeedback(): void {
    const root = document.querySelector<HTMLElement>('.help-feedback');
    if (!root) {
        return;
    }

    const url = root.dataset.feedbackUrl;
    const csrf = root.dataset.csrf;
    if (!url || !csrf) {
        return;
    }

    const actions = root.querySelector<HTMLElement>('.help-feedback__actions');
    const commentWrap = root.querySelector<HTMLElement>('.help-feedback__comment');
    const comment = root.querySelector<HTMLTextAreaElement>('#help-feedback-comment');
    const thanks = root.querySelector<HTMLElement>('.help-feedback__thanks');
    let pendingHelpful: '1' | '0' | null = null;

    const send = async (helpful: '1' | '0', text = '') => {
        const body = new URLSearchParams();
        body.set('_token', csrf);
        body.set('helpful', helpful);
        if (text) {
            body.set('comment', text);
        }
        const res = await fetch(url, {
            method: 'POST',
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: body.toString(),
        });
        if (!res.ok) {
            return;
        }
        if (actions) {
            actions.hidden = true;
        }
        if (commentWrap) {
            commentWrap.hidden = true;
        }
        if (thanks) {
            thanks.hidden = false;
        }
    };

    root.querySelectorAll<HTMLButtonElement>('[data-helpful]').forEach((btn) => {
        btn.addEventListener('click', () => {
            const value = btn.dataset.helpful === '1' ? '1' : '0';
            pendingHelpful = value;
            if (value === '1') {
                void send('1');
                return;
            }
            if (commentWrap) {
                commentWrap.hidden = false;
                comment?.focus();
            }
        });
    });

    root.querySelector<HTMLButtonElement>('[data-feedback-submit]')?.addEventListener('click', () => {
        if (pendingHelpful !== '0') {
            return;
        }
        void send('0', comment?.value.trim() || '');
    });
}

function initAssistant(): void {
    const openBtn = document.querySelector<HTMLButtonElement>('#help-assistant-open');
    const dialog = document.querySelector<HTMLElement>('#help-assistant-dialog');
    const closeBtn = document.querySelector<HTMLButtonElement>('#help-assistant-close');
    const form = document.querySelector<HTMLFormElement>('#help-assistant-form');
    const sendBtn = document.querySelector<HTMLButtonElement>('#help-assistant-send');
    const input = document.querySelector<HTMLTextAreaElement>('#help-assistant-question');
    const messages = document.querySelector<HTMLElement>('#help-assistant-messages');
    const examples = document.querySelector<HTMLElement>('#help-assistant-examples');
    if (!openBtn || !dialog || !closeBtn || !form || !sendBtn || !input || !messages) {
        return;
    }

    const url = dialog.dataset.assistantUrl;
    const csrf = dialog.dataset.csrf;
    const sourcesLabel = dialog.dataset.labelSources || 'Quellen';
    const errorLabel = dialog.dataset.labelError || 'Die Anfrage konnte nicht verarbeitet werden.';
    if (!url || !csrf) {
        return;
    }

    const open = () => {
        dialog.hidden = false;
        openBtn.setAttribute('aria-expanded', 'true');
        input.focus();
    };
    const close = () => {
        dialog.hidden = true;
        openBtn.setAttribute('aria-expanded', 'false');
        openBtn.focus();
    };

    openBtn.addEventListener('click', () => {
        if (dialog.hidden) {
            open();
        } else {
            close();
        }
    });
    closeBtn.addEventListener('click', close);
    dialog.addEventListener('keydown', (event) => {
        if (event.key === 'Escape') {
            close();
        }
    });

    document.querySelectorAll<HTMLButtonElement>('.help-assistant-example').forEach((btn) => {
        btn.addEventListener('click', () => {
            input.value = btn.textContent?.trim() || '';
            void ask();
        });
    });

    const appendMessage = (
        role: 'user' | 'bot',
        answer: string,
        sources: Array<{ title: string; url: string }> = []
    ) => {
        const row = document.createElement('div');
        row.className = `help-assistant__msg help-assistant__msg--${role}`;
        const bubble = document.createElement('div');
        bubble.className = 'help-assistant__bubble';
        const p = document.createElement('p');
        p.textContent = answer;
        bubble.appendChild(p);

        if (sources.length) {
            const sourcesWrap = document.createElement('div');
            sourcesWrap.className = 'help-assistant__sources';
            const label = document.createElement('span');
            label.className = 'help-assistant__sources-label';
            label.textContent = sourcesLabel;
            sourcesWrap.appendChild(label);
            sources.forEach((source) => {
                const a = document.createElement('a');
                a.href = source.url;
                a.textContent = source.title;
                sourcesWrap.appendChild(a);
            });
            bubble.appendChild(sourcesWrap);
        }

        row.appendChild(bubble);
        messages.appendChild(row);
        messages.scrollTop = messages.scrollHeight;
        return row;
    };

    const showTyping = () => {
        const row = document.createElement('div');
        row.className = 'help-assistant__msg help-assistant__msg--bot';
        row.dataset.typing = '1';
        const bubble = document.createElement('div');
        bubble.className = 'help-assistant__bubble';
        bubble.innerHTML =
            '<div class="help-assistant__typing" aria-hidden="true"><span></span><span></span><span></span></div>';
        row.appendChild(bubble);
        messages.appendChild(row);
        messages.scrollTop = messages.scrollHeight;
        return row;
    };

    const ask = async () => {
        const question = input.value.trim();
        if (!question) {
            return;
        }

        appendMessage('user', question);
        input.value = '';
        if (examples) {
            examples.hidden = true;
        }

        const typing = showTyping();
        const body = new URLSearchParams();
        body.set('_token', csrf);
        body.set('question', question);
        sendBtn.disabled = true;

        try {
            const res = await fetch(url, {
                method: 'POST',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: body.toString(),
            });
            const data = await res.json();
            typing.remove();
            if (!res.ok || !data.ok) {
                appendMessage('bot', errorLabel);
                return;
            }
            appendMessage('bot', data.answer || '', data.sources || []);
        } catch {
            typing.remove();
            appendMessage('bot', errorLabel);
        } finally {
            sendBtn.disabled = false;
            input.focus();
        }
    };

    form.addEventListener('submit', (event) => {
        event.preventDefault();
        void ask();
    });

    input.addEventListener('keydown', (event) => {
        if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault();
            void ask();
        }
    });
}
