-- SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
--
-- SPDX-License-Identifier: GPL-3.0-or-later

-- Load main.lua as a module (it exports functions when required)
package.path = package.path .. ";./?.lua"
local wt = dofile("src/main.lua")

describe("load_global_config", function()
	local temp_dir

	setup(function()
		-- Create temp directory for test configs
		local handle = io.popen("mktemp -d")
		if handle then
			temp_dir = handle:read("*l")
			handle:close()
		end
	end)

	teardown(function()
		-- Restore HOME and clean up
		if temp_dir then
			os.execute("rm -rf " .. temp_dir)
		end
	end)

	describe("with no config file", function()
		it("returns empty table when config file missing", function()
			local config = wt.load_global_config()
			assert.is_table(config)
		end)
	end)

	describe("config file format", function()
		-- Note: These tests document expected behavior but can't easily
		-- override HOME in the running process. They serve as specification.

		it("accepts simple table config", function()
			-- Expected: { branch_path_style = "flat" }
			-- The loader prepends "return " so file should NOT have return
			local config = wt.load_global_config()
			assert.is_table(config)
		end)
	end)
end)

describe("load_project_config", function()
	local temp_dir

	setup(function()
		local handle = io.popen("mktemp -d")
		if handle then
			temp_dir = handle:read("*l")
			handle:close()
		end
	end)

	teardown(function()
		if temp_dir then
			os.execute("rm -rf " .. temp_dir)
		end
	end)

	describe("with no config file", function()
		it("returns empty table for nonexistent path", function()
			local config = wt.load_project_config("/nonexistent/path")
			assert.are.same({}, config)
		end)

		it("returns empty table for directory without .wt.lua", function()
			local config = wt.load_project_config(temp_dir)
			assert.are.same({}, config)
		end)
	end)

	describe("with valid config file", function()
		it("loads hooks configuration", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			-- Write a test config
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[{
	hooks = {
		copy = { ".env.example" },
		symlink = { "node_modules" },
		run = { "npm install" },
	}
}]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.is_table(config.hooks)
				assert.are.same({ ".env.example" }, config.hooks.copy)
				assert.are.same({ "node_modules" }, config.hooks.symlink)
				assert.are.same({ "npm install" }, config.hooks.run)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)

		it("loads branch_path_style from project config", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[{ branch_path_style = "flat", flat_separator = "-" }]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.equal("flat", config.branch_path_style)
				assert.are.equal("-", config.flat_separator)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)
	end)

	describe("error handling", function()
		it("returns empty table for syntax error in config", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[{ invalid syntax here !!!]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.same({}, config)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)

		it("returns empty table for runtime error in config", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[{ value = undefined_var + 1 }]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.same({}, config)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)

		it("returns empty table when config returns non-table", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([["just a string"]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.same({}, config)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)

		it("loads config with leading comment", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[-- my config comment
{ branch_path_style = "flat" }]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.equal("flat", config.branch_path_style)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)

		it("loads config with explicit return", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[return { branch_path_style = "flat" }]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				assert.are.equal("flat", config.branch_path_style)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)
	end)

	describe("sandboxed environment", function()
		it("cannot access os module in config", function()
			if not temp_dir then
				pending("temp_dir not available")
				return
			end
			local config_path = temp_dir .. "/.wt.lua"
			local f = io.open(config_path, "w")
			if f then
				f:write([[{ home = os.getenv("HOME") }]])
				f:close()

				local config = wt.load_project_config(temp_dir)
				-- Returns empty table due to runtime error (os is nil)
				assert.are.same({}, config)

				os.remove(config_path)
			else
				pending("could not write test config")
			end
		end)
	end)
end)
