Приведи следующий код к профессиональному уровню с использованием принципов ООП, сделай архитектуру модульной и расширяемой, добавь инкапсуляцию, абстракцию и наследование там, где это уместно, оптимизируй производительность и читаемость, улучшай именования переменных и функций, убери дублирование, применяй паттерны проектирования, обеспечь обработку ошибок и логирование, добавь комментарии и документацию для основных классов и методов.

```lua
if CLIENT then
    local interactKey = KEY_E
    local interactionDistance = 150
    local progressMax = 3 -- секунд удержания
    local progress = 0
    local targetPlayer = nil
    local menuOpen = false
    local buttons = {
        {
            label = "Кнопка 1",
            func = function() print("Кнопка 1 нажата") end
        },
        {
            label = "Кнопка 2",
            func = function() print("Кнопка 2 нажата") end
        },
        {
            label = "Кнопка 3",
            func = function() print("Кнопка 3 нажата") end
        },
    }

    local ButtonPositions = {} -- Для хранения параметров кнопок и hovered состояния
    local function GetClosestPlayer()
        local localPly = LocalPlayer()
        local pos = localPly:GetPos()
        local closest = nil
        local closestDist = interactionDistance
        for _, ply in ipairs(player.GetAll()) do
            if ply ~= localPly and ply:Alive() then
                local dist = pos:Distance(ply:GetPos())
                if dist < closestDist then
                    closest = ply
                    closestDist = dist
                end
            end
        end
        return closest
    end

    local function ScreenPosFrom3D(pos)
        local sp = pos:ToScreen()
        return {
            x = sp.x,
            y = sp.y
        }
    end

    local function DrawProgressBar(pos, ang, fraction)
        cam.Start3D2D(pos, ang, 0.05)
        surface.SetDrawColor(50, 50, 50, 180)
        surface.DrawRect(-50, 0, 100, 10)
        surface.SetDrawColor(100, 200, 100, 255)
        surface.DrawRect(-50, 0, 100 * fraction, 10)
        draw.SimpleText("Взаимодействие...", "DermaDefaultBold", 0, -20, Color(255, 255, 255), TEXT_ALIGN_CENTER)
        cam.End3D2D()
    end

    local function DrawButton(x, y, w, h, label, hovered)
        surface.SetDrawColor(hovered and Color(100, 180, 100) or Color(70, 130, 70))
        surface.DrawRect(x, y, w, h)
        draw.SimpleText(label, "DermaDefaultBold", x + w / 2, y + h / 2, Color(255, 255, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
    end

    local function PointInRect(point, rectX, rectY, w, h)
        return point.x >= rectX and point.x <= rectX + w and point.y >= rectY and point.y <= rectY + h
    end

    hook.Add("Think", "PlayerInteractionThink", function()
        local localPly = LocalPlayer()
        if not localPly:Alive() then
            progress = 0
            targetPlayer = nil
            menuOpen = false
            return
        end

        if menuOpen then return end
        local ply = GetClosestPlayer()
        if not ply then
            progress = 0
            targetPlayer = nil
            return
        end

        if localPly:GetPos():Distance(ply:GetPos()) > interactionDistance then
            progress = 0
            targetPlayer = nil
            return
        end

        if input.IsKeyDown(interactKey) then
            if targetPlayer ~= ply then
                targetPlayer = ply
                progress = 0
            end

            progress = math.min(progress + FrameTime(), progressMax)
            if progress >= progressMax then menuOpen = true end
        else
            progress = 0
            targetPlayer = nil
        end
    end)

    hook.Add("PostDrawTranslucentRenderables", "DrawInteractionUI3D", function()
        if targetPlayer and not menuOpen and IsValid(targetPlayer) then
            local pos = targetPlayer:GetPos() + Vector(0, 0, 85)
            local ang = Angle(0, EyeAngles().y - 90, 90)
            DrawProgressBar(pos, ang, progress / progressMax)
        end
    end)

    hook.Add("PostDrawTranslucentRenderables", "Draw3DMenuWindowAndButtons", function()
        if not menuOpen or not IsValid(targetPlayer) then return end
        local ply = targetPlayer
        -- Позиция поднята выше на 20 единиц по Z относительно предыдущего варианта
        local pos = ply:GetPos() + ply:GetUp() * 60 + ply:GetForward() * 10
        local ang = EyeAngles()
        ang:RotateAroundAxis(ang:Forward(), 90)
        ang:RotateAroundAxis(ang:Right(), 90)
        local w, h = 250, 220 -- увеличенный размер окна
        local padding = 15
        local btnW, btnH = w - padding * 2, 60 -- увеличенный размер кнопок
        cam.Start3D2D(pos, ang, 0.02)
        -- Рисуем фон окна
        surface.SetDrawColor(50, 50, 50, 220)
        surface.DrawRect(-w / 2, -h / 2, w, h)
        local mx, my = input.GetCursorPos()
        local mousePos = {
            x = mx,
            y = my
        }

        ButtonPositions = {}
        for i, btn in ipairs(buttons) do
            local x = -w / 2 + padding
            local y = -h / 2 + padding + (i - 1) * (btnH + padding)
            local btnWorldPos = pos + ang:Right() * (x + btnW / 2) + ang:Up() * (y + btnH / 2)
            local screenPos = ScreenPosFrom3D(btnWorldPos)
            local hovered = PointInRect(mousePos, screenPos.x - btnW / 2, screenPos.y - btnH / 2, btnW, btnH)
            DrawButton(x, y, btnW, btnH, btn.label, hovered)
            ButtonPositions[i] = {
                func = btn.func,
                hovered = hovered
            }
        end

        cam.End3D2D()
    end)

    hook.Add("GUIMousePressed", "Interaction3DMenuClick", function(mc)
        if mc ~= MOUSE_LEFT then return end
        if not menuOpen then return end
        if not IsValid(targetPlayer) then
            menuOpen = false
            return
        end

        for _, btn in ipairs(ButtonPositions) do
            if btn.hovered then
                btn.func()
                menuOpen = false
                targetPlayer = nil
                progress = 0
                return true
            end
        end
    end)
end
```