-- ApiVault Source Example / Secure Pattern Cross-Link polish helpers. Generated for ApiVault v0.3.3.
-- Metadata-only. No runtime file reads, no full Blizzard source display, no protected/secure execution.
local addonName, ApiVault = ...

ApiVault.ExampleSecureLinks = ApiVault.ExampleSecureLinks or {}
local Links = ApiVault.ExampleSecureLinks

Links.metadata = {
	version = "0.3.3",
	interface = 120007,
	policy = "metadata-only detail polish; inspect-only secure links; no runtime file reads; no protected/secure execution",
	source_archive = "Interface.zip",
	target_package = "ApiVault-v0.3.2.zip",
}

local function append(text, line)
	if ApiVault and ApiVault.AppendLine then
		return ApiVault:AppendLine(text, line)
	end
	if text == nil or text == "" then
		return tostring(line or "")
	end
	return tostring(text) .. "\n" .. tostring(line or "")
end

local function asText(value)
	if value == nil then
		return ""
	end
	return tostring(value)
end

local function unwrap(entryOrData)
	if type(entryOrData) ~= "table" then
		return nil
	end
	return entryOrData.data or entryOrData
end

local function limitNumber(value, fallback)
	value = tonumber(value)
	if value and value > 0 then
		return value
	end
	return fallback or 5
end

local function sameText(left, right)
	return asText(left) ~= "" and asText(left) == asText(right)
end

local function lower(value)
	return string.lower(tostring(value or ""))
end

local function isFunctionOwner(ownerType)
	ownerType = lower(ownerType)
	return ownerType == "function" or ownerType == "api"
end

local function isEventOwner(ownerType)
	ownerType = lower(ownerType)
	return ownerType == "event"
end

local function isTemplateOwner(ownerType)
	ownerType = lower(ownerType)
	return ownerType == "template" or ownerType == "xmltemplate" or ownerType == "xml"
end

function Links:GetStats()
	return 2, "source-example and secure-pattern cross-link polish"
end

function Links:GetAPIEntry(name, expectedKind)
	if not name or name == "" or not ApiVault.Index then
		return nil
	end
	if ApiVault.Index.Build then
		ApiVault.Index:Build()
	end
	local entry = ApiVault.Index.byFullName and ApiVault.Index.byFullName[name]
	if entry and (not expectedKind or entry.kind == expectedKind) then
		return entry
	end
	for _, candidate in ipairs(ApiVault.Index.entries or {}) do
		if candidate.display == name and (not expectedKind or candidate.kind == expectedKind) then
			return candidate
		end
	end
	return nil
end

function Links:GetResourceFile(sourcePath)
	if not sourcePath or sourcePath == "" then
		return nil
	end
	if ApiVault.ResourceLinks and ApiVault.ResourceLinks.FindResourceFile then
		return ApiVault.ResourceLinks:FindResourceFile(sourcePath)
	end
	if ApiVault.InterfaceResources then
		for _, fileInfo in ipairs(ApiVault.InterfaceResources.files or {}) do
			if fileInfo.sp == sourcePath or fileInfo.ap == sourcePath then
				return fileInfo
			end
		end
	end
	return nil
end

function Links:GetModuleSummary(moduleName)
	if not moduleName or moduleName == "" or not ApiVault.ModuleCatalog or not ApiVault.ModuleCatalog.GetModuleSummary then
		return nil
	end
	return ApiVault.ModuleCatalog:GetModuleSummary(moduleName)
end

function Links:GetXMLTemplate(templateName)
	if not templateName or templateName == "" or not ApiVault.XMLCatalog or not ApiVault.XMLCatalog.GetTemplate then
		return nil
	end
	return ApiVault.XMLCatalog:GetTemplate(templateName)
end

function Links:GetExamplesForFile(sourcePath, limit)
	local out = {}
	if not sourcePath or sourcePath == "" or not ApiVault.SourceExamples then
		return out, 0
	end
	limit = limitNumber(limit, 5)
	local total = 0
	for _, example in ipairs(ApiVault.SourceExamples.entries or {}) do
		if sameText(example.sourcePath, sourcePath) or sameText(example.addonPath, sourcePath) then
			total = total + 1
			if #out < limit then
				out[#out + 1] = example
			end
		end
	end
	return out, total
end

function Links:GetSecureForExample(example, limit)
	local out = {}
	if type(example) ~= "table" or not ApiVault.SecurePatterns then
		return out
	end
	limit = limitNumber(limit, 5)

	local function addUnique(list)
		for _, entry in ipairs(list or {}) do
			local exists = false
			for _, current in ipairs(out) do
				if current.patternId == entry.patternId then
					exists = true
					break
				end
			end
			if not exists then
				out[#out + 1] = entry
				if #out >= limit then
					return true
				end
			end
		end
		return false
	end

	if example.ownerName and (isFunctionOwner(example.ownerType) or example.ownerType == nil) then
		if addUnique(ApiVault.SecurePatterns:GetForAPI(example.ownerName, limit)) then
			return out
		end
	end
	if example.sourcePath and addUnique(ApiVault.SecurePatterns:GetForFile(example.sourcePath, limit)) then
		return out
	end
	if example.addonPath and addUnique(ApiVault.SecurePatterns:GetForFile(example.addonPath, limit)) then
		return out
	end
	if example.module and addUnique(ApiVault.SecurePatterns:GetForModule(example.module, limit)) then
		return out
	end
	return out
end

function Links:GetExamplesForSecurePattern(pattern, limit)
	local out = {}
	if type(pattern) ~= "table" or not ApiVault.SourceExamples then
		return out, 0
	end
	limit = limitNumber(limit, 5)
	local total = 0

	local function maybeAdd(example)
		if type(example) ~= "table" then
			return
		end
		local match = false
		if pattern.linkedAPI and pattern.linkedAPI ~= "" and example.ownerName == pattern.linkedAPI then
			match = true
		elseif pattern.linkedTemplate and pattern.linkedTemplate ~= "" and example.ownerName == pattern.linkedTemplate then
			match = true
		elseif sameText(example.sourcePath, pattern.sourcePath) or sameText(example.addonPath, pattern.addonPath) then
			match = true
		elseif pattern.module and pattern.module ~= "" and example.module == pattern.module then
			match = true
		end
		if match then
			total = total + 1
			if #out < limit then
				out[#out + 1] = example
			end
		end
	end

	for _, example in ipairs(ApiVault.SourceExamples.entries or {}) do
		maybeAdd(example)
	end
	return out, total
end

local function appendPolicyBadges(text, riskClass, autoRunPolicy, sourceBacked)
	text = append(text, "")
	text = append(text, "Policy badges:")
	text = append(text, "- GENERATED_METADATA: ApiVault generated this detail from indexed metadata")
	if sourceBacked ~= nil then
		text = append(text, "- SOURCE_BACKED: " .. tostring(sourceBacked and true or false))
	end
	text = append(text, "- INSPECT_ONLY: no Blizzard source file is read or displayed at runtime")
	text = append(text, "- NO_PROTECTED_EXECUTION: secure/protected execution is not enabled")
	if riskClass and riskClass ~= "" then
		text = append(text, "- RISK_CLASS: " .. tostring(riskClass))
	end
	if autoRunPolicy and autoRunPolicy ~= "" then
		text = append(text, "- AUTO_RUN_POLICY: " .. tostring(autoRunPolicy))
	end
	return text
end

local function appendSecureSamples(text, entries, limit)
	limit = limitNumber(limit, 5)
	if type(entries) ~= "table" or #entries == 0 then
		return append(text, "- no linked secure patterns indexed")
	end
	for index, entry in ipairs(entries) do
		if index > limit then
			text = append(text, "- ... +" .. tostring(#entries - limit) .. " more")
			break
		end
		text = append(text, "  " .. tostring(index) .. ". " .. tostring(entry.patternName or "?") .. " / " .. tostring(entry.riskClass or "?") .. " / " .. tostring(entry.autoRunPolicy or "inspect-only"))
		text = append(text, "     " .. tostring(entry.addonPath or entry.sourcePath or "?") .. ":" .. tostring(entry.line or "?") .. " [" .. tostring(entry.module or "?") .. "] " .. tostring(entry.contextLabel or ""))
	end
	return text
end

local function appendExampleSamples(text, entries, total, limit)
	limit = limitNumber(limit, 5)
	if type(entries) ~= "table" or #entries == 0 then
		return append(text, "- no linked source examples indexed")
	end
	for index, example in ipairs(entries) do
		if index > limit then
			break
		end
		text = append(text, "  " .. tostring(index) .. ". " .. tostring(example.ownerName or "?") .. " / " .. tostring(example.riskClass or "?") .. " / " .. tostring(example.module or "?"))
		text = append(text, "     " .. tostring(example.addonPath or example.sourcePath or "?") .. ":" .. tostring(example.line or "?") .. " " .. tostring(example.contextLabel or ""))
	end
	if total and total > #entries then
		text = append(text, "- ... +" .. tostring(total - #entries) .. " more")
	end
	return text
end

function Links:AppendSourceExampleLinks(text, exampleOrEntry, limit)
	local example = unwrap(exampleOrEntry)
	if type(example) ~= "table" then
		return text
	end
	limit = limitNumber(limit, 5)

	text = appendPolicyBadges(text, example.riskClass, "inspect-only", example.sourceBacked)
	text = append(text, "")
	text = append(text, "Source example cross-links:")

	local ownerType = example.ownerType
	local ownerName = example.ownerName
	if ownerName and ownerName ~= "" then
		text = append(text, "- owner: " .. tostring(ownerName) .. " (" .. tostring(ownerType or "?") .. ")")
	end

	local apiEntry = nil
	if ownerName and isFunctionOwner(ownerType) then
		apiEntry = self:GetAPIEntry(ownerName, "Function")
	elseif ownerName and isEventOwner(ownerType) then
		apiEntry = self:GetAPIEntry(ownerName, "Event")
	end
	if apiEntry then
		text = append(text, "- API/Event docs: found, kind=" .. tostring(apiEntry.kind or "?") .. ", risk=" .. tostring(apiEntry.risk or "?") .. ", namespace=" .. tostring(apiEntry.namespace or ""))
	else
		text = append(text, "- API/Event docs: no direct documented owner match indexed")
	end

	if ApiVault.SourceUsage and ownerName then
		local usage = nil
		if isFunctionOwner(ownerType) and ApiVault.SourceUsage.GetAPIUsage then
			usage = ApiVault.SourceUsage:GetAPIUsage(ownerName)
		elseif isEventOwner(ownerType) and ApiVault.SourceUsage.GetEventUsage then
			usage = ApiVault.SourceUsage:GetEventUsage(ownerName)
		end
		if usage then
			text = append(text, "- source usage: refs=" .. tostring(usage.c or 0) .. ", modules=" .. tostring(usage.m or ""))
		end
	end

	local fileInfo = self:GetResourceFile(example.sourcePath) or self:GetResourceFile(example.addonPath)
	if fileInfo then
		text = append(text, "- source file metadata: type=" .. tostring(fileInfo.ty or "?") .. ", module=" .. tostring(fileInfo.mod or "?") .. ", lines=" .. tostring(fileInfo.lines or 0) .. ", sha256=" .. tostring(fileInfo.sha or "?"))
		text = append(text, "  file: " .. tostring(fileInfo.ap or fileInfo.sp or "?"))
	else
		text = append(text, "- source file metadata: no resource record indexed")
	end

	local moduleSummary = self:GetModuleSummary(example.module)
	if moduleSummary then
		text = append(text, "- module summary: TOCs=" .. tostring(moduleSummary.tocEntries or 0) .. ", files=" .. tostring(moduleSummary.fileCount or 0) .. ", APIs=" .. tostring(moduleSummary.apiUsageCount or 0) .. ", events=" .. tostring(moduleSummary.eventUsageCount or 0) .. ", XML=" .. tostring(moduleSummary.xmlTemplateCount or 0))
	end

	if ownerName and isTemplateOwner(ownerType) then
		local template = self:GetXMLTemplate(ownerName)
		if template then
			text = append(text, "- XML template owner: found, type=" .. tostring(template.ty or "?") .. ", source=" .. tostring(template.ap or template.sp or "?"))
		end
	end

	text = append(text, "")
	text = append(text, "Linked secure patterns:")
	local secure = self:GetSecureForExample(example, limit)
	text = appendSecureSamples(text, secure, limit)

	text = append(text, "")
	text = append(text, "Validation note: generated snippet metadata is not proof of runtime behavior. Test OOC/combat where context or secure state matters.")
	return text
end

function Links:AppendSecurePatternLinks(text, patternOrEntry, limit)
	local pattern = unwrap(patternOrEntry)
	if type(pattern) ~= "table" then
		return text
	end
	limit = limitNumber(limit, 5)

	text = appendPolicyBadges(text, pattern.riskClass, pattern.autoRunPolicy or "inspect-only", nil)
	text = append(text, "")
	text = append(text, "Secure pattern cross-links:")

	if pattern.linkedAPI and pattern.linkedAPI ~= "" then
		local apiEntry = self:GetAPIEntry(pattern.linkedAPI, "Function") or self:GetAPIEntry(pattern.linkedAPI, nil)
		if apiEntry then
			text = append(text, "- linked API: " .. tostring(pattern.linkedAPI) .. " / docs found / risk=" .. tostring(apiEntry.risk or "?"))
		else
			text = append(text, "- linked API: " .. tostring(pattern.linkedAPI) .. " / no direct docs entry indexed")
		end
	elseif pattern.patternType == "api-metadata" then
		text = append(text, "- linked API: metadata pattern without explicit linkedAPI field")
	else
		text = append(text, "- linked API: none")
	end

	if pattern.linkedTemplate and pattern.linkedTemplate ~= "" then
		local template = self:GetXMLTemplate(pattern.linkedTemplate)
		if template then
			text = append(text, "- linked XML template: " .. tostring(pattern.linkedTemplate) .. " / type=" .. tostring(template.ty or "?") .. " / source=" .. tostring(template.ap or template.sp or "?"))
		else
			text = append(text, "- linked XML template: " .. tostring(pattern.linkedTemplate) .. " / no template metadata match")
		end
	else
		text = append(text, "- linked XML template: none")
	end

	local moduleName = pattern.linkedModule or pattern.module
	if moduleName and moduleName ~= "" then
		local moduleSummary = self:GetModuleSummary(moduleName)
		if moduleSummary then
			text = append(text, "- linked module: " .. tostring(moduleName) .. " / TOCs=" .. tostring(moduleSummary.tocEntries or 0) .. ", files=" .. tostring(moduleSummary.fileCount or 0) .. ", APIs=" .. tostring(moduleSummary.apiUsageCount or 0) .. ", events=" .. tostring(moduleSummary.eventUsageCount or 0))
		else
			text = append(text, "- linked module: " .. tostring(moduleName) .. " / no TOC summary indexed")
		end
	end

	local fileInfo = self:GetResourceFile(pattern.sourcePath) or self:GetResourceFile(pattern.addonPath)
	if fileInfo then
		text = append(text, "- source file metadata: type=" .. tostring(fileInfo.ty or "?") .. ", lines=" .. tostring(fileInfo.lines or 0) .. ", sha256=" .. tostring(fileInfo.sha or "?"))
		text = append(text, "  file: " .. tostring(fileInfo.ap or fileInfo.sp or "?"))
	else
		text = append(text, "- source file metadata: no resource record indexed")
	end

	text = append(text, "")
	text = append(text, "Linked source examples:")
	local examples, total = self:GetExamplesForSecurePattern(pattern, limit)
	text = appendExampleSamples(text, examples, total, limit)

	text = append(text, "")
	text = append(text, "Security note: secure pattern metadata is inspect-only. ApiVault does not create secure buttons, call SetAttribute, call protected APIs or bypass combat lockdown.")
	return text
end
