local M = {}

local modes = {
  n     = { "NORMAL", "StatuslineModeNormal" },
  i     = { "INSERT", "StatuslineModeInsert" },
  v     = { "VISUAL", "StatuslineModeVisual" },
  V     = { "V-LINE", "StatuslineModeVisual" },
  [""] = { "V-BLOCK", "StatuslineModeVisual" },
  R     = { "REPLACE", "StatuslineModeReplace" },
  c     = { "COMMAND", "StatuslineModeCommand" },
}

local function mode()
  local m = vim.fn.mode()
  local entry = modes[m] or { m, "StatusLine" }
  return string.format("%%#%s# %s %%#StatusLine#", entry[2], entry[1])
end

----------------------------------------------------------------------
-- Git branch (buffer-lokal, gecached, kein redraw-spam)
----------------------------------------------------------------------

local function update_git_branch(bufnr)
  bufnr = bufnr or 0

  -- nur in echten Dateien
  if vim.bo[bufnr].buftype ~= "" then
    vim.b[bufnr].git_branch = ""
    return
  end

  -- kein Git → nichts tun
  if vim.fn.executable("git") ~= 1 then
    vim.b[bufnr].git_branch = ""
    return
  end

  local branch = vim.fn.systemlist(
    "git rev-parse --abbrev-ref HEAD 2>/dev/null"
  )[1]

  if branch and branch ~= "" then
    vim.b[bufnr].git_branch = "  " .. branch .. " "
  else
    vim.b[bufnr].git_branch = ""
  end
end

----------------------------------------------------------------------
-- Autocmd: Git nur bei Bedarf aktualisieren
----------------------------------------------------------------------

vim.api.nvim_create_autocmd(
  { "BufEnter", "FocusGained" },
  {
    callback = function(args)
      update_git_branch(args.buf)
    end,
  }
)

----------------------------------------------------------------------
-- Statusline-Sektionen (reine Darstellung, keine IO)
----------------------------------------------------------------------

-- Git-Branch (buffer-lokal, gecached, kein redraw-spam)

local function git()
  return vim.b.git_branch or ""
end

-- Git-Diff (buffer-lokal, kein redraw-spam)

local function git_diff()
  local gsd = vim.b.gitsigns_status_dict
  if not gsd then return "" end

  local parts = {}
  if gsd.added and gsd.added > 0 then table.insert(parts, "+" .. gsd.added) end
  if gsd.changed and gsd.changed > 0 then table.insert(parts, "~" .. gsd.changed) end
  if gsd.removed and gsd.removed > 0 then table.insert(parts, "-" .. gsd.removed) end

  if #parts > 0 then
    return " " .. table.concat(parts, " ") .. " "
  end

  return ""
end

----------------------------------------------------------------------
-- Dateiname mit Modifikationsstatus
----------------------------------------------------------------------

local function filename()
  local name = vim.fn.expand("%:.")
  if name == "" then
    name = "[No Name]"
  end

  if vim.bo.modified then
    name = name .. " [+]"
  end

  return " " .. name .. " "
end

------------------------------------------------------------------------
-- Treesitter-Aktivität (buffer-lokal, kein redraw-spam)
------------------------------------------------------------------------

local function treesitter()
  local ok = vim.treesitter.highlighter.active[vim.api.nvim_get_current_buf()]
  if ok then
    return " 🌳 "
  end
  return ""
end

------------------------------------------------------------------------
-- Diagnostik-Counts (buffer-lokal, kein redraw-spam)
------------------------------------------------------------------------

local function diagnostics()
  local counts = {
    error = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }),
    warn  = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN }),
    info  = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO }),
    hint  = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT }),
  }

  local parts = {}

  if counts.error > 0 then table.insert(parts, "  " .. counts.error) end
  if counts.warn > 0 then table.insert(parts, "  " .. counts.warn) end
  if counts.info > 0 then table.insert(parts, "  " .. counts.info) end
  if counts.hint > 0 then table.insert(parts, "  " .. counts.hint) end

  if #parts > 0 then
    return " " .. table.concat(parts, " ") .. " "
  end

  return ""
end

------------------------------------------------------------------------
-- Filetype & Encoding (buffer-lokal, kein redraw-spam)
------------------------------------------------------------------------

local function fileinfo()
  local ft = vim.bo.filetype ~= "" and vim.bo.filetype or "none"
  local enc = vim.bo.fileencoding ~= "" and vim.bo.fileencoding or vim.o.encoding
  return string.format(" %s  %s ", ft, enc)
end

------------------------------------------------------------------------
-- Cursor-Position (kein redraw-spam)
------------------------------------------------------------------------

local function position()
  return string.format(" %d:%d ", vim.fn.line("."), vim.fn.col("."))
end

-------------------------------------------------------------------------
-- Copilot-Status (buffer-lokal, kein redraw-spam)
-------------------------------------------------------------------------

local function copilot()
  if vim.fn.exists("*copilot#Enabled") == 0 then
    return ""
  end

  if vim.fn["copilot#Enabled"]() == 0 then
    return "  OFF "
  end

  if vim.b.copilot_suggestion and vim.b.copilot_suggestion.is_visible then
    return "  SUG "
  end

  if vim.b.copilot_suggestion_auto_trigger == false then
    return "  MAN "
  end

  return "  ON "
end

----------------------------------------------------------------------
-- Öffentliche Statusline-Funktion
----------------------------------------------------------------------

function M.statusline()
  return table.concat({
    -- LEFT: Mode & Context
    mode(),
    "%#PmenuSel#",
    git(),
    git_diff(),
    "%#StatusLine#",
    filename(),

    "%=",

    -- RIGHT: Feedback & Meta
    copilot(),
    diagnostics(),
    treesitter(),
    fileinfo(),
    " %p%% ",
    position(),
  })
end

return M
