-- ApiVault External Error Bridge. Added in v1.1.4.
-- Generic data-only error ingestion bridge for BugGrabber/custom detectors.
-- No BugGrabber internals are assumed. External addons must supply records as data.
local addonName, ApiVault = ...

ApiVault.ExternalErrorBridge = ApiVault.ExternalErrorBridge or {}
local Bridge = ApiVault.ExternalErrorBridge

Bridge.sources = Bridge.sources or {}
Bridge.lastSource = Bridge.lastSource or "none"

local function now()
	return GetTime and GetTime() or 0
end

local function wallTime()
	return date and date("%Y-%m-%d %H:%M:%S") or tostring(now())
end

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

local function clamp(value, limit)
	value = tostring(value or "")
	limit = limit or 12000
	if #value > limit then
		return string.sub(value, 1, limit) .. "\n<truncated by ApiVault>"
	end
	return value
end

local function sanitizeRecord(record)
	record = record or {}
	local out = {
		addon = clamp(record.addon or record.addonName or record.owner or "UNKNOWN_ADDON", 256),
		message = clamp(record.message or record.error or record.errorMessage or "unknown error", 12000),
		stack = clamp(record.stack or record.stackTrace or record.trace or "", 24000),
		source = clamp(record.source or "External", 256),
		file = clamp(record.file or record.filename or "", 1024),
		line = tonumber(record.line or record.lineNumber) or nil,
		context = clamp(record.context or record.label or "", 2000),
		category = clamp(record.category or "", 256),
		timestamp = record.timestamp or now(),
		wallTime = record.wallTime or wallTime(),
	}
	if type(record.extra) == "table" then
		out.extra = record.extra
	end
	return out
end

function Bridge:RegisterSource(name, metadata)
	name = trim(name)
	if name == "" then
		return false, "source name required"
	end
	self.sources[name] = {
		name = name,
		metadata = metadata or {},
		registeredAt = wallTime(),
		policy = "data-only; ApiVault does not call adapter internals automatically",
	}
	return true, "registered source: " .. name
end

function Bridge:GetSources()
	return self.sources or {}
end

function Bridge:IngestError(record)
	local normalized = sanitizeRecord(record)
	self.lastSource = normalized.source
	if ApiVault.BugAdvisor and ApiVault.BugAdvisor.IngestError then
		return ApiVault.BugAdvisor:IngestError(normalized)
	end
	return nil, "BugAdvisor unavailable"
end

function Bridge:IngestBatch(records, sourceName)
	local count = 0
	if type(records) ~= "table" then
		return 0, "records table required"
	end
	for _, record in ipairs(records) do
		if type(record) == "table" then
			record.source = record.source or sourceName or "ExternalBatch"
			self:IngestError(record)
			count = count + 1
		end
	end
	return count, "ingested " .. tostring(count) .. " errors"
end

function Bridge:CreateBugGrabberAdapter()
	return {
		name = "BugGrabber",
		policy = "passive adapter; no BugGrabber internals assumed",
		Ingest = function(_, record)
			record = record or {}
			record.source = record.source or "BugGrabber"
			return ApiVault.ExternalErrorBridge:IngestError(record)
		end,
		IngestBatch = function(_, records)
			return ApiVault.ExternalErrorBridge:IngestBatch(records, "BugGrabber")
		end,
	}
end

function Bridge:CreateCustomAdapter(sourceName)
	sourceName = trim(sourceName)
	if sourceName == "" then sourceName = "CustomBugDetector" end
	return {
		name = sourceName,
		policy = "custom data-only adapter",
		Ingest = function(_, record)
			record = record or {}
			record.source = record.source or sourceName
			return ApiVault.ExternalErrorBridge:IngestError(record)
		end,
		IngestBatch = function(_, records)
			return ApiVault.ExternalErrorBridge:IngestBatch(records, sourceName)
		end,
	}
end

function Bridge:FormatSources()
	local lines = {}
	table.insert(lines, "ApiVault External Error Bridge")
	table.insert(lines, "Policy: generic data-only ingestion. ApiVault does not assume BugGrabber internals.")
	table.insert(lines, "lastSource: " .. tostring(self.lastSource or "none"))
	table.insert(lines, "")
	for name, source in pairs(self.sources or {}) do
		table.insert(lines, "- " .. tostring(name) .. " | registeredAt=" .. tostring(source.registeredAt) .. " | " .. tostring(source.policy))
	end
	if next(self.sources or {}) == nil then
		table.insert(lines, "No sources registered yet.")
	end
	return table.concat(lines, "\n")
end

function Bridge:GetStats()
	local count = 0
	for _ in pairs(self.sources or {}) do count = count + 1 end
	return count, self.lastSource or "none"
end

-- Convenience global methods for external addons that do not want a full DeveloperAPI bridge.
function ApiVault:IngestExternalError(record)
	return ApiVault.ExternalErrorBridge:IngestError(record)
end

function ApiVault:RegisterExternalErrorSource(name, metadata)
	return ApiVault.ExternalErrorBridge:RegisterSource(name, metadata)
end
