import { useLocation } from '@docusaurus/router';
import Link from '@docusaurus/Link';
import Layout from '@theme/Layout';
import React, { useCallback, useEffect, useRef, useState } from 'react';

import { chatUrl } from '@docuservix-search/config';

import styles from './styles.module.css';

interface Source {
    file: string;
    heading: string;
    anchor: string;
    score: number;
}

interface Message {
    role: 'user' | 'assistant';
    content: string;
    sources?: Source[];
}

function stripNumericPrefixes(p: string): string {
    return p
        .split('/')
        .map((seg) => seg.replace(/^\d+-/, ''))
        .join('/');
}

function sourceToUrl(file: string, anchor: string): string {
    let p = file.replace(/^docs\//, '').replace(/\.md$/, '');

    p = stripNumericPrefixes(p);

    return `/docs/${p}${anchor ? `#${anchor}` : ''}`;
}

function sourceToPath(file: string): string {
    const p = file.replace(/^docs\//, '').replace(/\.md$/, '');

    return stripNumericPrefixes(p);
}

function useQuery(): string {
    const location = useLocation();
    const params = new URLSearchParams(location.search);

    return params.get('q') ?? '';
}

export default function ChatPage(): JSX.Element {
    const urlQuery = useQuery();

    const [messages, setMessages] = useState<Message[]>([]);
    const [input, setInput] = useState('');
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);

    const messagesEndRef = useRef<HTMLDivElement>(null);
    const initialSentRef = useRef(false);

    const sendMessage = useCallback(async (content: string, history: Message[]) => {
        if (!content.trim()) return;

        const userMessage: Message = { role: 'user', content };
        const newHistory = [...history, userMessage];

        setMessages(newHistory);
        setInput('');
        setLoading(true);
        setError(null);

        try {
            const res = await fetch(chatUrl, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ messages: newHistory }),
            });

            if (!res.ok) {
                throw new Error(`HTTP ${res.status}`);
            }

            const data: { answer: string; sources?: Source[] } = await res.json();

            setMessages((prev) => [
                ...prev,
                { role: 'assistant', content: data.answer, sources: data.sources },
            ]);
        } catch (err) {
            setError(err instanceof Error ? err.message : 'Ошибка при обращении к серверу');
        } finally {
            setLoading(false);
        }
    }, []);

    useEffect(() => {
        if (urlQuery && !initialSentRef.current) {
            initialSentRef.current = true;
            sendMessage(urlQuery, []);
        }
    }, [urlQuery, sendMessage]);

    useEffect(() => {
        messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
    }, [messages, loading]);

    const handleSend = () => {
        if (!loading && input.trim()) {
            sendMessage(input, messages);
        }
    };

    const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            handleSend();
        }
    };

    return (
        <Layout title="Чат">
            <div className={styles.page}>
                {urlQuery && (
                    <div className={styles.header}>
                        <Link
                            to={`/search?q=${encodeURIComponent(urlQuery)}`}
                            className={styles.backLink}
                        >
                            ← Назад к поиску
                        </Link>
                    </div>
                )}

                <div className={styles.messages}>
                    {messages.length === 0 && !loading && (
                        <div className={styles.empty}>Задайте вопрос...</div>
                    )}

                    {messages.map((msg, i) => (
                        <div
                            key={i}
                            className={`${styles.messageRow} ${msg.role === 'user' ? styles.messageRowUser : styles.messageRowAssistant}`}
                        >
                            <div
                                className={`${styles.bubble} ${msg.role === 'user' ? styles.userBubble : styles.assistantBubble}`}
                            >
                                <div className={styles.bubbleContent}>{msg.content}</div>

                                {msg.sources && msg.sources.length > 0 && (
                                    <div className={styles.sources}>
                                        <div className={styles.sourcesLabel}>Источники:</div>
                                        {msg.sources.map((src, j) => (
                                            <Link
                                                key={j}
                                                to={sourceToUrl(src.file, src.anchor)}
                                                className={styles.sourceLink}
                                            >
                                                {src.heading || sourceToPath(src.file)}
                                            </Link>
                                        ))}
                                    </div>
                                )}
                            </div>
                        </div>
                    ))}

                    {loading && (
                        <div className={`${styles.messageRow} ${styles.messageRowAssistant}`}>
                            <div
                                className={`${styles.bubble} ${styles.assistantBubble} ${styles.loadingBubble}`}
                            >
                                <span className={styles.loadingDot} />
                                <span className={styles.loadingDot} />
                                <span className={styles.loadingDot} />
                            </div>
                        </div>
                    )}

                    {error && (
                        <div className={styles.errorRow}>
                            <div className={styles.errorText}>{error}</div>
                        </div>
                    )}

                    <div ref={messagesEndRef} />
                </div>

                <div className={styles.inputRow}>
                    <textarea
                        className={styles.input}
                        value={input}
                        onChange={(e) => setInput(e.target.value)}
                        onKeyDown={handleKeyDown}
                        placeholder="Введите сообщение... (Enter — отправить, Shift+Enter — перенос)"
                        rows={2}
                        disabled={loading}
                    />
                    <button
                        className={styles.sendBtn}
                        onClick={handleSend}
                        disabled={loading || !input.trim()}
                    >
                        Отправить
                    </button>
                </div>
            </div>
        </Layout>
    );
}
