-- Basics
vim.g.mapleader = " "

-- Yank to system clipboard
vim.keymap.set("n", "y", '"+y', { desc = "Yank to clipboard" })
vim.keymap.set("v", "y", '"+y', { desc = "Yank to clipboard" })
vim.keymap.set("n", "Y", '"+Y', { desc = "Yank line to clipboard" })

-- Also make delete operations use system clipboard
vim.keymap.set("n", "d", '"+d', { desc = "Delete to clipboard" })
vim.keymap.set("v", "d", '"+d', { desc = "Delete to clipboard" })
vim.keymap.set("n", "D", '"+D', { desc = "Delete line to clipboard" })

-- Paste from system clipboard
vim.keymap.set("n", "p", '"+p', { desc = "Paste from clipboard" })
vim.keymap.set("v", "p", '"+p', { desc = "Paste from clipboard" })

-- Treesitter
require("nvim-treesitter.configs").setup({
	ensure_installed = { "lua", "nix", "python", "javascript", "rust", "rasi" },
	sync_install = false,
	auto_install = true,
	highlight = {
		enable = true,
		additional_vim_regex_highlighting = false,
	},

	parser_install_dir = vim.fn.stdpath("data") .. "/treesitter",
})
vim.opt.runtimepath:append(vim.fn.stdpath("data") .. "/treesitter")

-- Linting
require("lint").linters_by_ft = {}
vim.api.nvim_create_autocmd({ "BufWritePost" }, {
	callback = function()
		require("lint").try_lint()
	end,
})

-- Mason Setup
require("mason").setup({
	ui = {
		icons = {
			package_installed = "✓",
			package_pending = "➜",
			package_uninstalled = "✗",
		},
	},
})

require("mason-lspconfig").setup({
	ensure_installed = {
		"lua_ls",
		"nil_ls",
		"rust_analyzer",
		"pylsp",
		"stylelint-lsp",
	},
	automatic_installation = true,
})

-- LSP Config
local cmp = require("cmp")
cmp.setup({
	snippet = {
		expand = function(args)
			require("luasnip").lsp_expand(args.body)
		end,
	},
	mapping = cmp.mapping.preset.insert({
		["<C-b>"] = cmp.mapping.scroll_docs(-4),
		["<C-f>"] = cmp.mapping.scroll_docs(4),
		["<C-Space>"] = cmp.mapping.complete(),
		["<C-e>"] = cmp.mapping.abort(),
		["<CR>"] = cmp.mapping.confirm({ select = true }),
	}),
	sources = cmp.config.sources({
		{ name = "nvim_lsp" },
		{ name = "luasnip" },
	}, {
		{ name = "buffer" },
		{ name = "path" },
	}),
})

local lspconfig = require("lspconfig")
local capabilities = require("cmp_nvim_lsp").default_capabilities()
vim.keymap.set("n", "gd", vim.lsp.buf.definition, {})
vim.keymap.set("n", "K", vim.lsp.buf.hover, {})
vim.keymap.set("n", "<leader>rn", vim.lsp.buf.rename, {})
vim.keymap.set("n", "<leader>ca", vim.lsp.buf.code_action, {})

-- Setup language servers
lspconfig.lua_ls.setup({
	capabilities = capabilities,
	settings = {
		Lua = {
			runtime = { version = "LuaJIT" },
			diagnostics = { globals = { "vim" } },
			workspace = { library = vim.api.nvim_get_runtime_file("", true) },
			telemetry = { enable = false },
		},
	},
})

lspconfig.nil_ls.setup({ capabilities = capabilities })
lspconfig.rust_analyzer.setup({ capabilities = capabilities })
lspconfig.pylsp.setup({ capabilities = capabilities })
lspconfig.stylelint_lsp.setup({
		cmd = { "stylelint-lsp", "--stdio" },
		filetypes = { "css", "scss", "rasi" },
		capabilities = vim.lsp.protocol.make_client_capabilities(),
})

-- Conform
require("conform").setup({
	formatters_by_ft = {
		lua = { "stylua" },
		nix = { "nixfmt" },
		python = { "black" },
		rust = { "rustfmt" },
		rasi = { "prettierd" },
	},
	format_on_save = {
		timeout_ms = 500,
		lsp_fallback = true,
	},
})

-- Yazi
require("yazi").setup({
	open_for_directories = true,
})

vim.keymap.set("n", "<leader>fy", function()
	require("yazi").yazi(nil, vim.loop.cwd())
end, { desc = "Open Yazi file manager" })

vim.keymap.set("n", "<leader>fd", function()
	require("yazi").yazi(nil, vim.fn.expand("%:p:h"))
end, { desc = "Open Yazi in current file directory" })

-- Telescope
require("telescope").setup()

local telescope = require("telescope.builtin")
vim.keymap.set("n", "<leader>ff", telescope.find_files, { desc = "Telescope find files" })
vim.keymap.set("n", "<leader>fg", telescope.live_grep, { desc = "Telescope live grep" })
vim.keymap.set("n", "<leader>fb", telescope.buffers, { desc = "Telescope buffers" })
vim.keymap.set("n", "<leader>fh", telescope.help_tags, { desc = "Telescope help tags" })

-- Styling
require("catppuccin").setup({
	flavour = "mocha",
	transparent_background = true,
	term_colors = true,
	integration = {
		treesitter = true,
		mason = true,
		lsp_trouble = true,
		which_key = true,
		cmp = true,
		gitsigns = true,
		telescope = true,
		nvimtree = true,
		dashboard = true,
		notify = true,
		indent_blankline = true,
		toggleterm = true, -- Important for transparent terminals
	},
})

vim.cmd.colorscheme("catppuccin")
vim.opt.number = true
vim.opt.cursorline = true
vim.opt.showmode = false
vim.opt.syntax = "enable"
vim.opt.hlsearch = true
vim.opt.incsearch = true
vim.opt.tabstop = 4
vim.opt.termguicolors = true

local colors = require("catppuccin.palettes").get_palette("mocha")
vim.api.nvim_set_hl(0, "LineNr", { fg = colors.text, bg = "NONE" })
vim.api.nvim_set_hl(0, "CursorLineNr", { fg = colors.pink, bg = "NONE", bold = true })

-- ToggleTerm setup
require("toggleterm").setup({
	size = 20,
	open_mapping = [[<c-\>]],
	direction = "float",
	float_opts = {
		border = "single",
		width = 200,
		height = 40,
	},
})

vim.keymap.set("n", "<leader>h", function()
	require("toggleterm").toggle(1, 10, vim.loop.cwd(), "horizontal")
end, { desc = "Toggle terminal (horizontal)" })

vim.keymap.set("n", "<leader>v", function()
	require("toggleterm").toggle(2, 60, vim.loop.cwd(), "vertical")
end, { desc = "Toggle terminal (vertical)" })

vim.keymap.set("n", "<leader>ft", function()
	require("toggleterm").toggle(3, 20, vim.loop.cwd(), "float")
end, { desc = "Toggle terminal (float)" })

vim.keymap.set("t", "<C-t>", "<Cmd>ToggleTerm<CR>", { desc = "Toggle terminal" })
vim.keymap.set("t", "<C-v>", "<C-\\><C-n>v", { desc = "Exit terminal and enter visual mode" })

-- Statusline
require("lualine").setup({
	options = {
		theme = "catppuccin",
		component_separators = { left = "|", right = "|" },
		section_separators = { left = "", right = "" },
	},
})

-- Dashboard
local alpha = require("alpha")
local dashboard = require("alpha.themes.dashboard")

dashboard.section.header.val = {
	"⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣯⣿⠿⣟⣷⣯⣛⢿⣿⣿⣾⣟⣿⣿⣿⣿⣿⣿⣿⣿⣿",
	"⣿⣿⣿⣿⣿⣿⣿⡿⣵⣿⡿⣴⣽⡟⣳⢿⢽⣽⣕⣽⢿⡿⣿⣟⣿⣿⣿⣿⣿⣿⣿",
	"⣿⣿⣿⣷⣿⣿⢟⣫⣿⢟⢟⣾⣾⣿⣿⣞⢳⣻⢞⣎⠿⢞⣊⣿⣞⣿⣿⣿⣿⣿⢽",
	"⣿⣿⣿⣿⣿⣏⢯⣿⣏⣏⠔⢇⣿⢢⢆⢀⢆⣧⣼⢻⢰⡧⢻⣝⣏⡸⣧⣾⣿⣿⣿",
	"⣿⣿⣿⣿⡟⣻⣿⣿⡾⡿⡼⢸⡝⣝⡳⢢⣧⢳⣳⢷⡇⣗⢺⡺⣿⡧⣿⣿⣿⢿⢿",
	"⣿⡿⣿⣼⡼⣿⣿⡗⡧⣧⠁⡝⣧⣳⠅⡾⠈⣎⢮⣧⣿⣿⣗⣷⣻⢷⣏⣼⢏⣺⣿",
	"⣿⣿⣿⣻⣿⣿⣿⢧⣿⢹⠉⢷⢿⣧⣲⡏⡀⡈⢆⠳⣿⡿⢿⣿⣱⢿⢫⣷⣝⣿⣿",
	"⣿⣿⣿⡯⡟⣿⣿⢽⣡⠟⢿⣮⠁⠙⠛⠈⡴⢿⣿⡷⣬⣽⢽⠧⣷⡏⣿⡇⣧⣽⣿",
	"⣿⠟⢻⡧⡇⣿⡇⣇⣆⢄⡜⢃⡀⡀⡀⡀⡀⢎⣁⠁⣸⣗⣸⣿⣧⣼⡿⢹⢿⢾⣿",
	"⣿⣷⣾⣿⢻⣿⢧⢻⣽⡀⡀⡀⡀⢄⡀⡀⡀⡀⡀⢀⣷⡸⡟⣿⣶⣻⣧⡛⡱⢝⣿",
	"⣿⣿⣿⣿⢸⡿⢚⡜⣿⣇⡀⡀⡀⡀⡀⡀⡀⡀⠚⢁⢣⣜⡿⣿⡇⢼⣿⠨⣸⣿⣿",
	"⣿⣄⣿⣗⢾⢻⣧⢿⣾⣿⣦⡀⡀⠑⠚⠉⡀⡀⣤⣿⢨⣿⠗⣻⢣⣿⢹⢈⣽⣿⣿",
	"⣿⣿⣿⣿⢎⡄⢿⣞⡇⣿⠹⣿⣶⣀⡀⣀⡴⡩⢸⢏⣿⣿⣶⢻⣾⢏⡞⠡⢽⣇⣾",
	"⣿⣿⣿⣮⣼⢬⣦⢿⣳⣌⠧⡉⠈⣇⣛⣁⣈⣼⣿⡸⠫⠛⠐⠛⠕⣙⣻⣬⣼⣿⣿",
	"⢟⢿⣿⣿⣿⡢⣃⣪⣭⣡⣤⣶⠟⡿⠿⠿⠿⠛⢁⣿⣿⢩⠉⡀⠈⠓⡝⣿⣿⣿⣿",
	"⣾⣿⣿⣿⣿⠞⢔⡣⡴⣾⣿⠓⣤⢧⡼⣉⠠⢤⣿⣿⠇⠃⡀⡀⡀⡀⡸⢿⣾⣿⣿",
	"⣿⣿⣿⡿⣺⡸⢗⢠⣇⣿⣿⠊⠃⡀⠉⡀⢠⣿⣿⠟⡸⡀⡀⡀⡀⡀⣃⣬⠽⠿⣿",
	"⣿⣿⣿⣿⡇⡏⢸⣿⠟⣽⡇⡀⡀⡀⡀⣴⣟⢭⣾⣿⡇⠎⣠⠒⠉⠈⢀⡀⢨⡋⣿",
	"⠛⠛⠛⠋⠃⠓⠚⠛⠘⠛⠃⡀⠊⡀⠛⠛⠛⠂⠛⠛⠓⠁⠚⡀⠂⠒⠒⠐⠒⠋⠛",
}

dashboard.section.buttons.val = {
	dashboard.button("e", "[+] New file", ":ene <BAR> startinsert <CR>"),
	dashboard.button("f", "[?] Find file", ":Telescope find_files <CR>"),
	dashboard.button("r", "[~] Recent files", ":Telescope oldfiles <CR>"),
	dashboard.button("y", "[Y] Yazi", ":Yazi<CR>"),
	dashboard.button("m", "[M] Mason", ":Mason<CR>"),
	dashboard.button("q", "[X] Quit", ":qa<CR>"),
}

dashboard.section.footer.val = "Circuits hum in anticipation of your will."

vim.api.nvim_create_autocmd("VimEnter", {
	callback = function()
		if vim.fn.argc() == 0 then
			require("alpha").start()
		end
	end,
})

alpha.setup(dashboard.config)
