-- Kotlin LSP = fwcd kotlin-language-server (installed via Mason).
--
-- NOTE: the JetBrains `kotlin-lsp` (intellij-server) was tried but it imports
-- Android Gradle modules with an EMPTY set of source sets, so it resolves
-- nothing for Android (hover/definition/references all return empty). fwcd
-- resolves the Gradle compile classpath itself and DOES navigate Android
-- projects, so we use it here. (kotlin-lsp remains fine for plain Kotlin/JVM.)
--
-- CPU/Memory notes for Android projects:
--   - Formatting disabled in LSP capabilities — ktfmt in-process spawns a SECOND
--     Kotlin compiler, doubling memory (OOMs even at 4GB). Formatting is handled
--     externally by null-ls running ktfmt as a separate process.
--   - Linting enabled — runs on the same compiler already loaded for completions,
--     so no extra memory cost. Provides error diagnostics (red squiggles).
--   - Semantic tokens disabled — extra compilation passes, not worth the CPU.
--   - 500ms debounce reduces compilation frequency during typing.
--   - Persistent tmpdir so the SQLite compilation cache survives across sessions.
local bin = vim.fn.expand("~/.local/share/nvim/mason/bin/kotlin-language-server")

if vim.fn.executable(bin) == 0 then
    vim.notify("kotlin-language-server not found — run :MasonInstall kotlin-language-server",
        vim.log.levels.WARN)
    return
end

-- Build capabilities, then strip formatting to prevent ktfmt OOMs.
local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp")
local capabilities = status_ok and cmp_nvim_lsp.default_capabilities() or vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.formatting = nil
capabilities.textDocument.rangeFormatting = nil
capabilities.textDocument.onTypeFormatting = nil

-- 1. Configuration
vim.lsp.config('kotlin_language_server', {
    cmd = { bin },
    filetypes = { "kotlin" },

    -- Kotlin/Android projects are rooted at a Gradle build file or git repo.
    -- vim.lsp.config expects callback form: function(bufnr, on_dir).
    root_dir = function(bufnr, on_dir)
        local fname = vim.api.nvim_buf_get_name(bufnr)
        local root = vim.fs.root(fname, {
            "settings.gradle.kts",
            "settings.gradle",
            "build.gradle.kts",
            "build.gradle",
            "pom.xml",
            ".git",
        })
        on_dir(root or vim.fs.dirname(fname))
    end,

    capabilities = capabilities,

    -- Strip formatting from the server's advertised capabilities.
    -- client-side capabilities only prevent the server from expecting format
    -- requests; server-side capabilities are what vim.lsp.buf.format() actually
    -- checks. Without this, format-on-save routes through the LSP's ktfmt →
    -- second Kotlin compiler → OOM.
    on_attach = function(client)
        client.server_capabilities.documentFormattingProvider = false
        client.server_capabilities.documentRangeFormattingProvider = false
    end,

    -- 6GB heap — Android classpath is large (163 deps + 320 source files).
    -- Persistent tmpdir so the compilation cache survives across sessions.
    -- Use Android Studio's JBR 21 — optimised GC/JIT for Kotlin workloads.
    cmd_env = {
        KOTLIN_LANGUAGE_SERVER_OPTS = "-Xmx6G -Xms512m -Djava.io.tmpdir=/home/prabhat/.cache/kotlin-ls-fwcd",
        JAVA_HOME = "/opt/android-studio/jbr",
    },

    init_options = {
        debounceTextChanges = 500,
    },

    settings = {
        kotlin = {
            linting = { enabled = true },
            completion = { enabled = true },
            semanticTokens = { enabled = false },
        },
    },
})

-- 2. Enable the server
vim.lsp.enable('kotlin_language_server')
