-- ApiVault Build Diff Support. Added in v1.0.0.
-- Supports current build manifest plus pasted compact manifests. Does not invent build differences.
local addonName, ApiVault = ...

ApiVault.BuildDiff = ApiVault.BuildDiff or {}
local Diff = ApiVault.BuildDiff

local NUMERIC_KEYS = {
	"interface", "apiDocs", "apiFunctions", "apiEvents", "apiTables",
	"sourceUsageAPIs", "sourceUsageEvents", "interfaceFiles", "interfaceFolders", "interfaceModules",
	"xmlTemplates", "moduleTOCs", "sourceExamples", "securePatterns", "symbols", "catalogEntries", "widgetEntries",
}

local function trim(value)
	value = tostring(value or "")
	return (value:gsub("^%s+", ""):gsub("%s+$", ""))
end

function Diff:GetCurrentManifest()
	return self.currentManifest or {}
end

function Diff:ParseManifestText(text)
	local manifest = {}
	text = tostring(text or "")
	for line in string.gmatch(text, "[^\r\n]+") do
		local key, value = string.match(line, "^%s*([%w_]+)%s*[:=]\s*(.-)%s*$")
		if not key then
			key, value = string.match(line, '^%s*"([%w_]+)"%s*:%s*"?([^",}]+)"?')
		end
		if key and value then
			value = trim(value)
			local n = tonumber(value)
			manifest[key] = n or value
		end
	end
	return manifest
end

function Diff:Compare(other)
	local current = self:GetCurrentManifest()
	other = other or {}
	local rows = {}
	for _, key in ipairs(NUMERIC_KEYS) do
		local a = tonumber(current[key])
		local b = tonumber(other[key])
		if a ~= nil and b ~= nil then
			table.insert(rows, { key = key, current = a, other = b, delta = a - b })
		elseif a ~= nil then
			table.insert(rows, { key = key, current = a, other = "missing", delta = "UNCERTAIN" })
		end
	end
	return rows
end

function Diff:FormatManifest(manifest)
	manifest = manifest or self:GetCurrentManifest()
	local lines = {}
	table.insert(lines, "ApiVault Build Manifest")
	table.insert(lines, "label: " .. tostring(manifest.label or ""))
	table.insert(lines, "sourceArchive: " .. tostring(manifest.sourceArchive or ""))
	table.insert(lines, "sourceSHA256: " .. tostring(manifest.sourceSHA256 or ""))
	table.insert(lines, "policy: " .. tostring(manifest.policy or ""))
	table.insert(lines, "")
	for _, key in ipairs(NUMERIC_KEYS) do
		table.insert(lines, key .. ": " .. tostring(manifest[key] or ""))
	end
	return table.concat(lines, "\n")
end

function Diff:FormatDiff(otherManifest)
	local rows = self:Compare(otherManifest)
	local lines = {}
	table.insert(lines, "ApiVault Build Diff")
	table.insert(lines, "Current: " .. tostring((self.currentManifest or {}).label or "current"))
	table.insert(lines, "Other: " .. tostring(otherManifest and otherManifest.label or "pasted manifest"))
	table.insert(lines, "")
	table.insert(lines, "UNCERTAIN: a real diff requires a second uploaded/generated Interface manifest.")
	table.insert(lines, "This panel only compares numeric manifest fields supplied by the user.")
	table.insert(lines, "")
	for _, row in ipairs(rows) do
		table.insert(lines, tostring(row.key) .. ": current=" .. tostring(row.current) .. " other=" .. tostring(row.other) .. " delta=" .. tostring(row.delta))
	end
	return table.concat(lines, "\n")
end

function Diff:GetStats()
	local m = self:GetCurrentManifest()
	return m.interface or 0, m.apiFunctions or 0, m.xmlTemplates or 0, m.symbols or 0
end
