local addonName = ...
local SlickUI = _G.SlickUI
if not SlickUI then return end

local AuctionData = { SchemaVersion = 2, StaleAfter = 24 * 60 * 60, MaxHistory = 20 }
SlickUI.CraftingAuctionData = AuctionData

local function Settings()
	SlickUI.DB.crafting = SlickUI.DB.crafting or {}
	SlickUI.DB.crafting.auctionPrices = SlickUI.DB.crafting.auctionPrices or {}
	if (tonumber(SlickUI.DB.crafting.auctionDataSchema) or 1) < AuctionData.SchemaVersion then
		for _, record in pairs(SlickUI.DB.crafting.auctionPrices) do
			if type(record) == "table" and type(record.history) ~= "table" and tonumber(record.unitPrice) then
				record.history = {{ unitPrice = record.unitPrice, observedAt = record.observedAt, source = record.source }}
			end
		end
	end
	SlickUI.DB.crafting.auctionDataSchema = AuctionData.SchemaVersion
	return SlickUI.DB.crafting
end

function AuctionData:Get(itemID)
	itemID = tonumber(itemID)
	return itemID and Settings().auctionPrices[itemID] or nil
end

function AuctionData:GetUnitPrice(itemID)
	local record = self:Get(itemID)
	local price = record and tonumber(record.unitPrice)
	if not price or price <= 0 then return nil, record end
	return price, record
end

function AuctionData:IsStale(record)
	local observedAt = record and tonumber(record.observedAt)
	return not observedAt or (time() - observedAt) > self.StaleAfter
end

function AuctionData:GetStats(itemID)
	local record = self:Get(itemID)
	local history = record and record.history
	if type(history) ~= "table" or #history == 0 then return nil end
	local prices, total, low, high = {}, 0
	for _, sample in ipairs(history) do
		local price = tonumber(type(sample) == "table" and sample.unitPrice)
		if price and price > 0 then
			prices[#prices + 1] = price
			total = total + price
			low = not low and price or math.min(low, price)
			high = not high and price or math.max(high, price)
		end
	end
	local count = #prices
	if count == 0 then return nil end
	local average = total / count
	local oldAverage, newAverage
	if count >= 4 then
		local split, oldTotal, newTotal = math.floor(count / 2), 0, 0
		for index, price in ipairs(prices) do
			if index <= split then oldTotal = oldTotal + price else newTotal = newTotal + price end
		end
		oldAverage = oldTotal / split
		newAverage = newTotal / (count - split)
	elseif count >= 2 then
		oldAverage, newAverage = prices[1], prices[count]
	end
	local change = oldAverage and oldAverage > 0 and ((newAverage - oldAverage) / oldAverage * 100) or 0
	local trend = change > 5 and "rising" or (change < -5 and "falling" or (count >= 2 and "stable" or "new"))
	local current = tonumber(record.unitPrice) or prices[count]
	return {
		current = current, average = math.floor(average + 0.5), low = low, high = high,
		count = count, trend = trend, changePercent = change,
		outlier = count >= 4 and current < average * 0.6,
	}
end

function AuctionData:Observe(itemID, unitPrice, source)
	itemID, unitPrice = tonumber(itemID), tonumber(unitPrice)
	if not itemID or not unitPrice or unitPrice <= 0 then return false end
	local build = select(4, GetBuildInfo())
	local settings, observedAt = Settings(), time()
	unitPrice = math.floor(unitPrice + 0.5)
	local record = settings.auctionPrices[itemID] or {}
	record.history = type(record.history) == "table" and record.history or {}
	local last = record.history[#record.history]
	if last and tonumber(last.unitPrice) == unitPrice and observedAt - (tonumber(last.observedAt) or 0) < 60 then
		last.observedAt, last.source = observedAt, source or "auction-observation"
	else
		record.history[#record.history + 1] = { unitPrice = unitPrice, observedAt = observedAt, source = source or "auction-observation" }
		while #record.history > self.MaxHistory do table.remove(record.history, 1) end
	end
	record.unitPrice, record.observedAt = unitPrice, observedAt
	record.source, record.gameBuild = source or "auction-observation", tonumber(build) or 0
	settings.auctionPrices[itemID] = record
	return true
end
