local uv = vim.loop or vim.uv

local utils = require "sg.utils"
local M = {}

-- Find the root of the repository
local artifact_file = require("plenary.debug_utils").sourced_filepath()
local sg_root = vim.fn.fnamemodify(artifact_file, ":p:h:h:h:h")

local os_uname = vim.loop.os_uname()
local sysname = os_uname.sysname:lower()

local sort_by_time = function(candidates)
  table.sort(candidates, function(a, b)
    return a.stat.mtime.sec > b.stat.mtime.sec
  end)
end

M.find_rust_bin = function(cmd)
  if vim.fn.executable(cmd) == 1 then
    return cmd
  end

  local directories = {
    "/dist/",
    "/target/debug/",
    "/target/release/",
    "/bin/",
  }

  -- On windows, we have `.exe` attached to the files,
  -- but on other systems we don't. We'll still check
  -- for both just in case
  local postfixes = { "" }
  if sysname == "windows_nt" then
    table.insert(postfixes, ".exe")
  end

  local candidates = {}
  for _, suffix in ipairs(postfixes) do
    local potential_command = cmd .. suffix
    for _, dir in ipairs(directories) do
      local path = utils.joinpath(sg_root, dir, potential_command)
      local stat = uv.fs_stat(path)
      if stat then
        table.insert(candidates, { stat = stat, path = path })
      end
    end
  end

  sort_by_time(candidates)
  local result = candidates[1]
  if not result then
    return nil
  end

  return result.path
end

--- I will keep this for now, but don't think that we actually need it.
--- (Mostly I might just copy it to somewhere else later)
---@deprecated
M.find_rust_lib = function(name)
  local ok, lib = pcall(require, name)
  if ok then
    return lib
  end

  local libname = "luaopen_" .. name

  local candidates = {}

  local directories = { "/target/debug/", "/target/release/", "/lib/" }
  local suffixes = { ".so", ".dylib" }
  for _, dir in ipairs(directories) do
    for _, suffix in ipairs(suffixes) do
      local path = utils.joinpath(sg_root, dir, name .. suffix)
      local stat = uv.fs_stat(path)
      if stat then
        table.insert(candidates, { stat = stat, path = path })
      end
    end
  end

  sort_by_time(candidates)
  for _, candidate in ipairs(candidates) do
    local dll = package.loadlib(candidate.path, libname)
    if dll then
      local loaded = dll()
      loaded._library_path = candidate.path
      return loaded
    end
  end

  -- error(string.format("Failed to load %s: You probably did not run `nvim -l build/init.lua`", name))
end

return M
