/**
 * docsLang.jsx — поддержка вкладок JS/Lua в статьях вики.
 *
 * Компоненты:
 *   <DocsLangProvider>  — оборачивает страницу статьи, хранит выбранный язык
 *                         в localStorage 'rublox.docs.lang' ('js' | 'lua').
 *   <DocsLangPicker />  — большой переключатель JS/Lua над статьёй.
 *   <LangTabs js lua /> — вкладка-переключатель внутри статьи. Показывает
 *                         либо js, либо lua, согласно текущему языку.
 *   useDocsLang()       — хук: возвращает {lang, setLang}.
 *
 * Если в статье нет ни одного <LangTabs> — она одинаково выглядит на обоих
 * языках (общая теория, не зависящая от языка скриптов).
 */
import React, { createContext, useContext, useEffect, useState } from 'react';

// ══════════════════════════════════════════════════════════════════
// Простая подсветка синтаксиса для JS и Lua
// ══════════════════════════════════════════════════════════════════

const JS_KEYWORDS = new Set([
    'let', 'const', 'var', 'function', 'return', 'if', 'else', 'for', 'while',
    'do', 'switch', 'case', 'break', 'continue', 'new', 'this', 'class',
    'extends', 'super', 'true', 'false', 'null', 'undefined', 'try', 'catch',
    'finally', 'throw', 'typeof', 'instanceof', 'in', 'of', 'async', 'await',
    'import', 'export', 'from', 'default', 'delete', 'void',
]);
const JS_BUILTINS = new Set([
    'game', 'Math', 'Object', 'Array', 'String', 'Number', 'Boolean', 'JSON',
    'console', 'setTimeout', 'setInterval', 'Promise', 'document', 'window',
]);

const LUA_KEYWORDS = new Set([
    'local', 'function', 'end', 'if', 'then', 'else', 'elseif', 'for', 'while',
    'do', 'repeat', 'until', 'return', 'break', 'and', 'or', 'not', 'true',
    'false', 'nil', 'in', 'goto',
]);
const LUA_BUILTINS = new Set([
    'game', 'workspace', 'script', 'Instance', 'Vector3', 'Vector2', 'Color3',
    'CFrame', 'UDim2', 'UDim', 'BrickColor', 'Enum', 'math', 'string', 'table',
    'task', 'print', 'warn', 'pairs', 'ipairs', 'pcall', 'tostring', 'tonumber',
    'TweenInfo', 'wait', 'tick', 'type', 'require', 'next', 'setmetatable',
    'getmetatable', 'rawget', 'rawset',
]);

function escapeHtml(s) {
    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

/** Возвращает HTML-строку с раскрашенным кодом. lang: 'js' | 'lua'. */
export function highlightCode(text, lang) {
    if (typeof text !== 'string') return escapeHtml(String(text || ''));
    const isLua = lang === 'lua';
    const keywords = isLua ? LUA_KEYWORDS : JS_KEYWORDS;
    const builtins = isLua ? LUA_BUILTINS : JS_BUILTINS;
    // Регулярки для токенов — порядок важен: сначала комменты и строки,
    // потом числа, потом identifier'ы.
    // JS: //... и /*...*/. Lua: --... и --[[...]].
    const commentRe = isLua
        ? /--\[\[[\s\S]*?\]\]|--[^\n]*/g
        : /\/\*[\s\S]*?\*\/|\/\/[^\n]*/g;
    // Строки: одинарные, двойные, в JS ещё бэктики.
    const stringRe = isLua
        ? /"(?:\\.|[^"\\\n])*"|'(?:\\.|[^'\\\n])*'|\[\[[\s\S]*?\]\]/g
        : /"(?:\\.|[^"\\\n])*"|'(?:\\.|[^'\\\n])*'|`(?:\\.|[^`\\])*`/g;
    const numRe = /\b\d+(?:\.\d+)?\b/g;
    const idRe = /[A-Za-zА-Яа-я_$][A-Za-zА-Яа-я0-9_$]*/g;

    // Берём весь текст, делим на токены через одну общую регулярку.
    const tokens = [];
    const combined = new RegExp(
        commentRe.source + '|' + stringRe.source + '|' + numRe.source + '|' + idRe.source,
        'g'
    );
    let lastIndex = 0;
    let match;
    while ((match = combined.exec(text)) !== null) {
        const start = match.index;
        const tok = match[0];
        if (start > lastIndex) {
            tokens.push({ type: 'raw', text: text.slice(lastIndex, start) });
        }
        // Классифицируем
        if (tok.startsWith('--') || tok.startsWith('//') || tok.startsWith('/*')) {
            tokens.push({ type: 'comment', text: tok });
        } else if (/^["'`\[]/.test(tok)) {
            tokens.push({ type: 'string', text: tok });
        } else if (/^\d/.test(tok)) {
            tokens.push({ type: 'number', text: tok });
        } else if (keywords.has(tok)) {
            tokens.push({ type: 'keyword', text: tok });
        } else if (builtins.has(tok)) {
            tokens.push({ type: 'builtin', text: tok });
        } else {
            // Идентификатор — проверим, идёт ли за ним ( → функция
            const rest = text.slice(start + tok.length);
            if (/^\s*\(/.test(rest)) {
                tokens.push({ type: 'fn', text: tok });
            } else {
                tokens.push({ type: 'ident', text: tok });
            }
        }
        lastIndex = start + tok.length;
    }
    if (lastIndex < text.length) {
        tokens.push({ type: 'raw', text: text.slice(lastIndex) });
    }
    return tokens.map(t => {
        const safe = escapeHtml(t.text);
        if (t.type === 'raw' || t.type === 'ident') return safe;
        return `<span class="hl-${t.type}">${safe}</span>`;
    }).join('');
}


// v2 — раньше при первом включении lua-режима сохранялся в LS и юзер
// потом всегда видел Lua-таб по умолчанию. Бамп ключа = сброс на JS
// у всех уже-открытых вкладок.
const LS_KEY = 'rublox.docs.lang.v2';
const LS_KEY_OLD = 'rublox.docs.lang';
const DEFAULT_LANG = 'js';

const DocsLangContext = createContext({
    lang: DEFAULT_LANG,
    setLang: () => {},
});

export function DocsLangProvider({ children }) {
    const [lang, setLangState] = useState(() => {
        try {
            // Очищаем старый ключ — у части юзеров там залип 'lua'
            localStorage.removeItem(LS_KEY_OLD);
            const v = localStorage.getItem(LS_KEY);
            return v === 'lua' ? 'lua' : 'js';
        } catch (_) {
            return DEFAULT_LANG;
        }
    });
    const setLang = (next) => {
        const v = next === 'lua' ? 'lua' : 'js';
        setLangState(v);
        try { localStorage.setItem(LS_KEY, v); } catch (_) {}
    };
    useEffect(() => {
        // Слушаем смену из других вкладок
        const onStorage = (e) => {
            if (e.key === LS_KEY && (e.newValue === 'js' || e.newValue === 'lua')) {
                setLangState(e.newValue);
            }
        };
        window.addEventListener('storage', onStorage);
        return () => window.removeEventListener('storage', onStorage);
    }, []);
    return (
        <DocsLangContext.Provider value={{ lang, setLang }}>
            {children}
        </DocsLangContext.Provider>
    );
}

export function useDocsLang() {
    return useContext(DocsLangContext);
}

/** Большой переключатель над статьёй: «На каком языке смотреть код?» */
export function DocsLangPicker() {
    const { lang, setLang } = useDocsLang();
    return (
        <div className="docsLangPicker">
            <div className="docsLangPicker__label">
                Язык скриптов в этой статье:
            </div>
            <div className="docsLangPicker__tabs">
                <button
                    type="button"
                    className={
                        'docsLangPicker__tab docsLangPicker__tab--js' +
                        (lang === 'js' ? ' is-active' : '')
                    }
                    onClick={() => setLang('js')}
                >
                    JavaScript
                </button>
                <button
                    type="button"
                    className={
                        'docsLangPicker__tab docsLangPicker__tab--lua' +
                        (lang === 'lua' ? ' is-active' : '')
                    }
                    onClick={() => setLang('lua')}
                >
                    Lua
                </button>
            </div>
            <div className="docsLangPicker__hint">
                Не знаешь что выбрать? Смотри статью <b>D0. Скриптинг: JS или Lua?</b>
            </div>
        </div>
    );
}

/**
 * Локальный переключатель вкладок внутри статьи. Если js/lua —
 * прямой контент (children), если на странице нет <DocsLangProvider> —
 * показываем оба заголовками.
 *
 * Использование:
 *   <LangTabs
 *       js={<Code>game.log('Привет')</Code>}
 *       lua={<Code>print('Привет')</Code>}
 *   />
 */
export function LangTabs({ js, lua }) {
    const { lang, setLang } = useDocsLang();
    const hasJs = js !== undefined && js !== null;
    const hasLua = lua !== undefined && lua !== null;
    if (!hasJs && !hasLua) return null;
    // Если есть только один язык — показываем без переключателя
    if (hasJs && !hasLua) return <>{js}</>;
    if (!hasJs && hasLua) return <>{lua}</>;
    return (
        <div className="docsLangTabs">
            <div className="docsLangTabs__head">
                <button
                    type="button"
                    className={'docsLangTabs__tab' + (lang === 'js' ? ' is-active' : '')}
                    onClick={() => setLang('js')}
                >
                    JS
                </button>
                <button
                    type="button"
                    className={'docsLangTabs__tab' + (lang === 'lua' ? ' is-active' : '')}
                    onClick={() => setLang('lua')}
                >
                    Lua
                </button>
            </div>
            <div className="docsLangTabs__body">
                {lang === 'lua' ? lua : js}
            </div>
        </div>
    );
}

export const DOCS_LANG_STYLES = `
.docsLangPicker {
    background: linear-gradient(135deg, #1a1d2e 0%, #14172b 100%);
    border: 1px solid #2a3050;
    border-radius: 10px;
    padding: 14px 18px;
    margin: 16px 0 24px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.docsLangPicker__label {
    font-size: 13px;
    font-weight: 600;
    color: #c8cce0;
}
.docsLangPicker__tabs {
    display: flex;
    gap: 8px;
}
.docsLangPicker__tab {
    flex: 1;
    padding: 10px 16px;
    border-radius: 6px;
    border: 1px solid transparent;
    background: #232842;
    color: #aab0c8;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.15s;
}
.docsLangPicker__tab:hover { background: #2a304f; color: #fff; }
.docsLangPicker__tab--js.is-active {
    background: linear-gradient(135deg, #f7df1e 0%, #d4b500 100%);
    color: #1a1a1c;
    border-color: #d4b500;
}
.docsLangPicker__tab--lua.is-active {
    background: linear-gradient(135deg, #2196f3 0%, #1565c0 100%);
    color: #fff;
    border-color: #1565c0;
}
.docsLangPicker__hint {
    font-size: 12px;
    color: #8a90a8;
    font-style: italic;
}

.docsLangTabs {
    margin: 12px 0;
    border-radius: 10px;
    overflow: hidden;
    border: 1px solid #e0e6f0;
    background: #fff;
}
.docsLangTabs__head {
    display: flex;
    background: #f4f6fb;
    border-bottom: 1px solid #e0e6f0;
}
.docsLangTabs__tab {
    padding: 9px 18px;
    border: none;
    background: transparent;
    color: #64748b;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    letter-spacing: 0.5px;
    border-bottom: 2px solid transparent;
}
.docsLangTabs__tab:hover { color: #1e293b; }
.docsLangTabs__tab.is-active {
    color: #1e3a8a;
    border-bottom-color: #3357ff;
    background: #fff;
}
.docsLangTabs__body {
    padding: 0;
    background: #fff;
}
.docsLangTabs__body > pre,
.docsLangTabs__body > .docCode { margin: 0; border-radius: 0; }

/* Заголовки колонок таблицы (th) — в основных стилях вики не определены.
   Делаем светлыми чтобы не сливались с фоном таблицы. */
.docTable th {
    padding: 9px 14px;
    background: #eef2ff;
    color: #1e3a8a;
    font-size: 13px;
    font-weight: 700;
    text-align: left;
    border-bottom: 1px solid #d4dcef;
    border-right: 1px solid #eef2f7;
}
.docTable th:last-child { border-right: none; }
.docTable thead tr:first-child th:first-child { border-top-left-radius: 12px; }
.docTable thead tr:first-child th:last-child { border-top-right-radius: 12px; }

.langChoiceOverlay {
    position: fixed; inset: 0;
    background: rgba(0,0,0,0.75);
    display: flex; align-items: center; justify-content: center;
    z-index: 10000;
}
.langChoiceDialog {
    background: #1a1d2e;
    border: 1px solid #2a3050;
    border-radius: 14px;
    padding: 28px;
    width: 100%;
    max-width: 520px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.6);
}
.langChoiceTitle {
    font-size: 20px;
    margin: 0 0 8px;
    color: #fff;
}
.langChoiceSub {
    margin: 0 0 20px;
    font-size: 13px;
    color: #aab0c8;
    line-height: 1.5;
}
.langChoiceBtns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    margin-bottom: 14px;
}
.langChoiceBtn {
    padding: 18px 16px;
    border-radius: 10px;
    border: 2px solid transparent;
    text-align: left;
    cursor: pointer;
    transition: all 0.15s;
    color: #fff;
}
.langChoiceBtn--js {
    background: linear-gradient(135deg, #f7df1e 0%, #d4b500 100%);
    color: #1a1a1c;
}
.langChoiceBtn--js:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(247,223,30,0.3); }
.langChoiceBtn--lua {
    background: linear-gradient(135deg, #2196f3 0%, #1565c0 100%);
}
.langChoiceBtn--lua:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(33,150,243,0.4); }
.langChoiceBtn__name {
    font-size: 18px;
    font-weight: 800;
    margin-bottom: 4px;
}
.langChoiceBtn__hint {
    font-size: 12px;
    font-weight: 400;
    opacity: 0.85;
}
.langChoiceCancel {
    width: 100%;
    padding: 10px;
    background: transparent;
    border: 1px solid #2a3050;
    color: #aab0c8;
    border-radius: 8px;
    font-size: 13px;
    cursor: pointer;
}
.langChoiceCancel:hover { background: #232842; color: #fff; }

/* ══════════════════════════════════════════════════════════════════
   Подсветка синтаксиса в код-блоках
   ══════════════════════════════════════════════════════════════════ */
.docCode .hl-keyword  { color: #ff79c6; font-weight: 600; }   /* let/const/local/function */
.docCode .hl-builtin  { color: #8be9fd; }                       /* game / workspace / Math */
.docCode .hl-string   { color: #f1fa8c; }                       /* 'строки' "строки" */
.docCode .hl-number   { color: #bd93f9; }                       /* 42, 3.14 */
.docCode .hl-comment  { color: #6272a4; font-style: italic; }   /* // или -- */
.docCode .hl-fn       { color: #50fa7b; }                       /* myFunc() */

/* ══════════════════════════════════════════════════════════════════
   Баннер «Lua-скрипты для урока»
   ══════════════════════════════════════════════════════════════════ */
.luaLessonBanner {
    background: #eef4ff;
    border: 1px solid #c7d8f5;
    border-radius: 10px;
    padding: 14px 18px;
    margin: 14px 0 22px;
}
.luaLessonBanner--missing {
    background: #fff7e0;
    border-color: #f0d599;
    color: #5a4500;
}
.luaLessonBanner--missing p { margin: 4px 0 0; font-size: 13px; }
.luaLessonBanner__head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.luaLessonBanner__head b { font-size: 14px; color: #1e3a8a; }
.luaLessonBanner__hint { font-size: 12px; color: #475569; font-style: italic; }
.luaLessonBanner__script { margin: 6px 0; }
.luaLessonBanner__script summary {
    cursor: pointer;
    padding: 8px 12px;
    background: #fff;
    border-radius: 6px;
    border: 1px solid #d0dcf0;
    font-family: Consolas, monospace;
    font-size: 13px;
    color: #1e3a8a;
    font-weight: 600;
}
.luaLessonBanner__script summary:hover { background: #f4f8ff; }
.luaLessonBanner__script[open] summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.luaLessonBanner__script pre { margin: 0; border-top-left-radius: 0; border-top-right-radius: 0; }
`;
