/**
 * lua-monaco-setup — регистрация Lua-фич в Monaco:
 *  1) Подсветка через встроенный 'lua' language (Monaco поставляется с basic-languages/lua)
 *  2) Автодополнение Roblox-API (Vector3.new, Color3.fromRGB, script.Parent, game.Players, ...)
 *  3) Hover-документация (наведя на Vector3 — описание + пример)
 *  4) Подсветка ошибок через luaparse (на этапе 7, опционально)
 *
 * Регистрируется ОДИН раз глобально через флаг monaco.__rbxLuaRegistered.
 */

const ROBLOX_LUA_API = [
    // === Глобальные функции ===
    { kind: 'function', name: 'print', insertText: 'print($0)', doc: 'Выводит сообщения в Output-панель.\n```lua\nprint("Привет", x, y)\n```' },
    { kind: 'function', name: 'warn', insertText: 'warn($0)', doc: 'Выводит предупреждение (жёлтым).\n```lua\nwarn("Что-то не так")\n```' },
    { kind: 'function', name: 'error', insertText: 'error(${1:"сообщение"})', doc: 'Бросает ошибку, останавливая текущий скрипт.\n```lua\nerror("Здоровье < 0")\n```' },
    { kind: 'function', name: 'wait', insertText: 'wait(${1:1})', doc: 'Приостанавливает скрипт на N секунд (заменяется на `task.wait` в новом коде).' },
    { kind: 'function', name: 'tick', insertText: 'tick()', doc: 'Возвращает количество секунд с эпохи (как `os.time()`, но дробное).' },
    { kind: 'function', name: 'pcall', insertText: 'pcall(${1:fn}, $0)', doc: 'Защищённый вызов. Возвращает `success, result|error`.\n```lua\nlocal ok, err = pcall(function() risky() end)\nif not ok then warn(err) end\n```' },
    { kind: 'function', name: 'xpcall', insertText: 'xpcall(${1:fn}, ${2:handler})', doc: 'Защищённый вызов с кастомным обработчиком ошибки.' },
    { kind: 'function', name: 'tostring', insertText: 'tostring($0)', doc: 'Преобразует значение в строку.' },
    { kind: 'function', name: 'tonumber', insertText: 'tonumber($0)', doc: 'Преобразует строку в число. Возвращает nil если не число.' },
    { kind: 'function', name: 'type', insertText: 'type($0)', doc: 'Возвращает строку с типом: "nil", "number", "string", "boolean", "table", "function", "userdata".' },
    { kind: 'function', name: 'typeof', insertText: 'typeof($0)', doc: 'Расширенная версия type — для Roblox-типов вернёт "Vector3", "CFrame", "Color3", "Instance".' },
    { kind: 'function', name: 'ipairs', insertText: 'ipairs(${1:t})', doc: 'Итератор по числовым ключам массива.\n```lua\nfor i, v in ipairs(arr) do ... end\n```' },
    { kind: 'function', name: 'pairs', insertText: 'pairs(${1:t})', doc: 'Итератор по всем ключам таблицы.\n```lua\nfor k, v in pairs(t) do ... end\n```' },
    { kind: 'function', name: 'next', insertText: 'next(${1:t}, $0)', doc: 'Возвращает следующую пару ключ-значение в таблице.' },
    { kind: 'function', name: 'select', insertText: 'select(${1:1}, $0)', doc: 'select("#", ...) — количество аргументов. select(n, ...) — n-й и далее аргументы.' },
    { kind: 'function', name: 'unpack', insertText: 'unpack(${1:t})', doc: 'Распаковывает массив в значения. (В Lua 5.4 — `table.unpack`)' },
    { kind: 'function', name: 'setmetatable', insertText: 'setmetatable(${1:t}, ${2:mt})', doc: 'Устанавливает metatable для таблицы.' },
    { kind: 'function', name: 'getmetatable', insertText: 'getmetatable($0)', doc: 'Возвращает metatable или nil.' },
    { kind: 'function', name: 'rawget', insertText: 'rawget(${1:t}, ${2:key})', doc: 'Чтение без вызова __index metatable.' },
    { kind: 'function', name: 'rawset', insertText: 'rawset(${1:t}, ${2:key}, ${3:value})', doc: 'Запись без вызова __newindex metatable.' },

    // === task.* ===
    { kind: 'module', name: 'task', insertText: 'task', doc: 'Современный API планировщика Roblox-Lua.\nЗаменяет `wait`, `spawn`, `delay`, `defer` из старого API.' },
    { kind: 'function', name: 'task.wait', insertText: 'task.wait(${1:1})', doc: 'Приостанавливает на N секунд.\nВозвращает фактическое время ожидания.\n```lua\nlocal dt = task.wait(0.5)\n```' },
    { kind: 'function', name: 'task.spawn', insertText: 'task.spawn(${1:function() end})', doc: 'Немедленно запускает функцию как coroutine.\n```lua\ntask.spawn(function() heavy() end)\n```' },
    { kind: 'function', name: 'task.delay', insertText: 'task.delay(${1:1}, ${2:function() end})', doc: 'Отложенный запуск функции через N секунд.\n```lua\ntask.delay(3, function() print("через 3 сек") end)\n```' },
    { kind: 'function', name: 'task.defer', insertText: 'task.defer(${1:function() end})', doc: 'Запуск в следующем кадре (после Heartbeat).' },

    // === Vector3 ===
    { kind: 'class', name: 'Vector3', insertText: 'Vector3', doc: '3D-вектор в Roblox.\nКонструктор: `Vector3.new(x, y, z)`.\nКонстанты: `Vector3.zero`, `Vector3.one`, `Vector3.xAxis`, `Vector3.yAxis`, `Vector3.zAxis`.' },
    { kind: 'function', name: 'Vector3.new', insertText: 'Vector3.new(${1:0}, ${2:0}, ${3:0})', doc: 'Создаёт `Vector3(x, y, z)`.\n```lua\nlocal v = Vector3.new(10, 5, 0)\nprint(v.X, v.Y, v.Z, v.Magnitude)\n```' },
    { kind: 'function', name: 'Vector3.zero', insertText: 'Vector3.zero', doc: '`Vector3(0, 0, 0)`.' },
    { kind: 'function', name: 'Vector3.one', insertText: 'Vector3.one', doc: '`Vector3(1, 1, 1)`.' },
    { kind: 'function', name: 'Vector3.xAxis', insertText: 'Vector3.xAxis', doc: '`Vector3(1, 0, 0)`.' },
    { kind: 'function', name: 'Vector3.yAxis', insertText: 'Vector3.yAxis', doc: '`Vector3(0, 1, 0)`.' },
    { kind: 'function', name: 'Vector3.zAxis', insertText: 'Vector3.zAxis', doc: '`Vector3(0, 0, 1)`.' },

    // === Color3 ===
    { kind: 'class', name: 'Color3', insertText: 'Color3', doc: 'Цвет RGB в Roblox.\nКомпоненты `R`, `G`, `B` в диапазоне [0, 1].' },
    { kind: 'function', name: 'Color3.new', insertText: 'Color3.new(${1:1}, ${2:1}, ${3:1})', doc: 'Создаёт `Color3(r, g, b)`, где компоненты в [0, 1].' },
    { kind: 'function', name: 'Color3.fromRGB', insertText: 'Color3.fromRGB(${1:255}, ${2:255}, ${3:255})', doc: 'Создаёт `Color3` из 0-255 RGB.\n```lua\nlocal red = Color3.fromRGB(255, 0, 0)\n```' },
    { kind: 'function', name: 'Color3.fromHSV', insertText: 'Color3.fromHSV(${1:0}, ${2:1}, ${3:1})', doc: 'Создаёт цвет из HSV-компонентов в [0, 1].' },
    { kind: 'function', name: 'Color3.fromHex', insertText: 'Color3.fromHex(${1:"#FF0000"})', doc: 'Создаёт цвет из hex-строки.' },

    // === CFrame ===
    { kind: 'class', name: 'CFrame', insertText: 'CFrame', doc: 'Coordinate Frame — позиция + поворот в 3D.\nИспользуется для трансформаций Part.CFrame.' },
    { kind: 'function', name: 'CFrame.new', insertText: 'CFrame.new(${1:0}, ${2:0}, ${3:0})', doc: 'Создаёт CFrame в указанной позиции.' },
    { kind: 'function', name: 'CFrame.lookAt', insertText: 'CFrame.lookAt(${1:eye}, ${2:target})', doc: 'CFrame, направленный из eye на target.' },
    { kind: 'function', name: 'CFrame.Angles', insertText: 'CFrame.Angles(${1:0}, ${2:0}, ${3:0})', doc: 'CFrame только с поворотом (в радианах).' },
    { kind: 'function', name: 'CFrame.fromEulerAnglesXYZ', insertText: 'CFrame.fromEulerAnglesXYZ(${1:0}, ${2:0}, ${3:0})', doc: 'CFrame с поворотом по эйлеровым углам.' },

    // === UDim2 / Vector2 ===
    { kind: 'class', name: 'UDim2', insertText: 'UDim2', doc: 'Размер/позиция GUI: процент + пиксели по обеим осям.' },
    { kind: 'function', name: 'UDim2.new', insertText: 'UDim2.new(${1:0}, ${2:0}, ${3:0}, ${4:0})', doc: '`UDim2.new(scaleX, offsetX, scaleY, offsetY)`.\n```lua\nframe.Position = UDim2.new(0.5, 0, 0.5, 0) -- центр экрана\n```' },
    { kind: 'function', name: 'UDim2.fromScale', insertText: 'UDim2.fromScale(${1:0.5}, ${2:0.5})', doc: 'Только процентные размеры.' },
    { kind: 'function', name: 'UDim2.fromOffset', insertText: 'UDim2.fromOffset(${1:100}, ${2:100})', doc: 'Только пиксельные размеры.' },
    { kind: 'class', name: 'Vector2', insertText: 'Vector2', doc: '2D-вектор.' },
    { kind: 'function', name: 'Vector2.new', insertText: 'Vector2.new(${1:0}, ${2:0})', doc: '`Vector2(x, y)`.' },
    { kind: 'class', name: 'UDim', insertText: 'UDim', doc: 'Одномерная UDim (scale + offset).' },
    { kind: 'function', name: 'UDim.new', insertText: 'UDim.new(${1:0}, ${2:0})', doc: '`UDim.new(scale, offset)`.' },

    // === Instance ===
    { kind: 'class', name: 'Instance', insertText: 'Instance', doc: 'Базовый класс всех объектов Roblox.' },
    { kind: 'function', name: 'Instance.new', insertText: 'Instance.new("${1:Part}", ${2:workspace})', doc: 'Создаёт новый объект указанного класса.\n```lua\nlocal part = Instance.new("Part", workspace)\npart.Size = Vector3.new(4, 1, 4)\npart.Position = Vector3.new(0, 10, 0)\n```' },

    // === game / services ===
    { kind: 'variable', name: 'game', insertText: 'game', doc: 'Корень DataModel. `game:GetService("Players")` — доступ к сервисам.' },
    { kind: 'variable', name: 'workspace', insertText: 'workspace', doc: 'Сокращение для `game.Workspace`. Содержит все Part-объекты сцены.' },
    { kind: 'variable', name: 'script', insertText: 'script', doc: 'Текущий скрипт. `script.Parent` — объект-носитель.\n```lua\nlocal part = script.Parent\npart.Touched:Connect(function(hit) ... end)\n```' },

    // === Enum ===
    { kind: 'enum', name: 'Enum', insertText: 'Enum', doc: 'Перечисления Roblox: KeyCode, Material, UserInputType, EasingStyle, EasingDirection, HumanoidStateType.' },
    { kind: 'enum', name: 'Enum.KeyCode', insertText: 'Enum.KeyCode.${1:W}', doc: 'Клавиши клавиатуры: W, A, S, D, Space, LeftShift, Q, E, F, R, T, ..., One, Two, ..., Up, Down.' },
    { kind: 'enum', name: 'Enum.UserInputType', insertText: 'Enum.UserInputType.${1:MouseButton1}', doc: 'Типы ввода: MouseButton1/2/3, Keyboard, Touch, MouseMovement, MouseWheel.' },
    { kind: 'enum', name: 'Enum.Material', insertText: 'Enum.Material.${1:Plastic}', doc: 'Материалы: Plastic, Wood, Metal, Neon, Glass, Sand, Ice, Grass, Concrete.' },
    { kind: 'enum', name: 'Enum.HumanoidStateType', insertText: 'Enum.HumanoidStateType.${1:Running}', doc: 'Состояния Humanoid: Running, Jumping, Freefall, Landed, Dead, Climbing, Swimming, Seated.' },
];

// === Сниппеты быстрого старта (готовые шаблоны) ===
const ROBLOX_LUA_SNIPPETS = [
    {
        label: 'killbrick',
        documentation: 'KillBrick — убивает игрока при касании.',
        insertText: [
            'local part = script.Parent',
            'part.Touched:Connect(function(hit)',
            '\tlocal humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")',
            '\tif humanoid then',
            '\t\thumanoid.Health = 0',
            '\tend',
            'end)',
        ].join('\n'),
    },
    {
        label: 'teleportpad',
        documentation: 'TeleportPad — телепортирует игрока в указанную точку.',
        insertText: [
            'local destination = Vector3.new(${1:0}, ${2:50}, ${3:0})',
            'local pad = script.Parent',
            'pad.Touched:Connect(function(hit)',
            '\tlocal root = hit.Parent:FindFirstChild("HumanoidRootPart")',
            '\tif root then',
            '\t\troot.CFrame = CFrame.new(destination)',
            '\tend',
            'end)',
        ].join('\n'),
    },
    {
        label: 'coin',
        documentation: 'Coin — даёт игроку монету при касании, потом исчезает.',
        insertText: [
            'local coin = script.Parent',
            'local collected = false',
            'coin.Touched:Connect(function(hit)',
            '\tif collected then return end',
            '\tif hit.Parent:FindFirstChildOfClass("Humanoid") then',
            '\t\tcollected = true',
            '\t\tprint("Монета собрана!")',
            '\t\tcoin:Destroy()',
            '\tend',
            'end)',
        ].join('\n'),
    },
    {
        label: 'heartbeat',
        documentation: 'RunService.Heartbeat — кадровый callback.',
        insertText: [
            'local RunService = game:GetService("RunService")',
            'RunService.Heartbeat:Connect(function(dt)',
            '\t${0:-- код, выполняется каждый кадр}',
            'end)',
        ].join('\n'),
    },
    {
        label: 'playeradded',
        documentation: 'PlayerAdded — реакция на захождение игрока.',
        insertText: [
            'local Players = game:GetService("Players")',
            'Players.PlayerAdded:Connect(function(player)',
            '\tprint("Игрок зашёл:", player.Name)',
            '\t${0:}',
            'end)',
        ].join('\n'),
    },
    {
        label: 'spinpart',
        documentation: 'SpinPart — вращающаяся платформа.',
        insertText: [
            'local RunService = game:GetService("RunService")',
            'local part = script.Parent',
            'local speed = ${1:2} -- радиан/сек',
            'RunService.Heartbeat:Connect(function(dt)',
            '\tpart.CFrame = part.CFrame * CFrame.Angles(0, speed * dt, 0)',
            'end)',
        ].join('\n'),
    },
];

export function registerLuaInMonaco(monaco) {
    if (monaco.__rbxLuaRegistered) return;
    monaco.__rbxLuaRegistered = true;

    // 1. CompletionProvider — автодополнение
    monaco.languages.registerCompletionItemProvider('lua', {
        triggerCharacters: ['.', ':', '"', "'"],
        provideCompletionItems: (model, position) => {
            const word = model.getWordUntilPosition(position);
            const range = {
                startLineNumber: position.lineNumber,
                endLineNumber: position.lineNumber,
                startColumn: word.startColumn,
                endColumn: word.endColumn,
            };
            const suggestions = [];
            const kindMap = {
                'function': monaco.languages.CompletionItemKind.Function,
                'class': monaco.languages.CompletionItemKind.Class,
                'module': monaco.languages.CompletionItemKind.Module,
                'enum': monaco.languages.CompletionItemKind.Enum,
                'variable': monaco.languages.CompletionItemKind.Variable,
            };
            for (const item of ROBLOX_LUA_API) {
                suggestions.push({
                    label: item.name,
                    kind: kindMap[item.kind] || monaco.languages.CompletionItemKind.Text,
                    insertText: item.insertText,
                    insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                    documentation: { value: item.doc, isTrusted: true },
                    range,
                });
            }
            for (const snip of ROBLOX_LUA_SNIPPETS) {
                suggestions.push({
                    label: snip.label,
                    kind: monaco.languages.CompletionItemKind.Snippet,
                    insertText: snip.insertText,
                    insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
                    documentation: { value: snip.documentation, isTrusted: true },
                    detail: 'Сниппет Roblox-Lua',
                    range,
                });
            }
            return { suggestions };
        },
    });

    // 2. HoverProvider — подсказки при наведении
    const lookupTable = new Map();
    for (const item of ROBLOX_LUA_API) lookupTable.set(item.name, item);
    monaco.languages.registerHoverProvider('lua', {
        provideHover: (model, position) => {
            const word = model.getWordAtPosition(position);
            if (!word) return null;
            // Пробуем найти точное совпадение или с префиксом (Vector3.new)
            let found = lookupTable.get(word.word);
            if (!found) {
                // Возможно курсор на середине A.B — попробуем собрать всю цепочку
                const line = model.getLineContent(position.lineNumber);
                // Ищем имя.имя.имя на позиции
                const left = line.slice(0, word.endColumn - 1);
                const m = left.match(/[A-Za-z_][\w.]*$/);
                if (m) found = lookupTable.get(m[0]);
            }
            if (!found) return null;
            return {
                range: new monaco.Range(
                    position.lineNumber, word.startColumn,
                    position.lineNumber, word.endColumn,
                ),
                contents: [
                    { value: `**${found.name}**` },
                    { value: found.doc },
                ],
            };
        },
    });
}
