-- =========================================================
-- Cooperativa Agrícola — Registro de Transações (TransactionLog)
-- =========================================================
-- Fundação do sistema de dados/visibilidade. Registra cada compra/venda
-- que passa pela cooperativa. Desse registro saem: notificações, histórico
-- e dashboard. Persiste no savegame e sincroniza no multiplayer.
--
-- Cada transação guarda:
--   kind        -> "sell" (vendeu à coop) | "buy" (comprou da coop)
--   farmId      -> quem fez a operação
--   fillType    -> nome do produto
--   liters      -> quantidade
--   value       -> valor em dinheiro
--   day, hour   -> quando (tempo do jogo)
-- =========================================================

TransactionLog = {}
local TransactionLog_mt = Class(TransactionLog)

TransactionLog.MAX_ENTRIES = 100  -- guarda as últimas 100 (evita inflar o save)

function TransactionLog.new()
    local self = setmetatable({}, TransactionLog_mt)
    self.entries = {}   -- lista, mais recente no fim
    return self
end

-- Registra uma nova transação (chamado no servidor, nos pontos de compra/venda)
function TransactionLog:record(kind, farmId, fillTypeName, liters, value)
    local day, hour = 1, 0
    local env = g_currentMission and g_currentMission.environment
    if env then
        day  = env.currentDay or env.currentMonotonicDay or 1
        if env.dayTime then hour = env.dayTime / (1000 * 60 * 60) end
    end

    local entry = {
        kind     = kind,
        farmId   = farmId or 0,
        fillType = fillTypeName or "?",
        liters   = liters or 0,
        value    = value or 0,
        day      = day,
        hour     = hour,
    }

    table.insert(self.entries, entry)

    -- Mantém só as últimas MAX_ENTRIES
    while #self.entries > TransactionLog.MAX_ENTRIES do
        table.remove(self.entries, 1)
    end

    return entry
end

-- Retorna as últimas N transações (mais recente primeiro)
function TransactionLog:getRecent(count)
    count = count or 50
    local result = {}
    local total = #self.entries
    for i = total, math.max(1, total - count + 1), -1 do
        table.insert(result, self.entries[i])
    end
    return result
end

-- ─── Agregações (pro dashboard) ──────────────────────────
function TransactionLog:getStats()
    local stats = {
        totalTransactions = #self.entries,
        totalBought       = 0,   -- litros que a coop comprou (fazendeiros venderam)
        totalSold         = 0,   -- litros que a coop vendeu (fazendeiros compraram)
        spentBuying       = 0,   -- $ que a coop pagou aos fazendeiros
        earnedSelling     = 0,   -- $ que a coop recebeu dos fazendeiros
        byFillType        = {},  -- [fillType] = { volume, profit }
        byFarm            = {},  -- [farmId]   = { count, volume }
    }

    for _, e in ipairs(self.entries) do
        -- kind "sell" = fazendeiro vendeu À coop (coop pagou)
        -- kind "buy"  = fazendeiro comprou DA coop (coop recebeu)
        if e.kind == "sell" then
            stats.totalBought = stats.totalBought + e.liters
            stats.spentBuying = stats.spentBuying + e.value
        elseif e.kind == "buy" then
            stats.totalSold   = stats.totalSold + e.liters
            stats.earnedSelling = stats.earnedSelling + e.value
        end

        -- Por produto
        local ft = stats.byFillType[e.fillType] or { volume = 0, profit = 0 }
        ft.volume = ft.volume + e.liters
        ft.profit = ft.profit + (e.kind == "buy" and e.value or -e.value)
        stats.byFillType[e.fillType] = ft

        -- Por fazenda
        local fm = stats.byFarm[e.farmId] or { count = 0, volume = 0 }
        fm.count  = fm.count + 1
        fm.volume = fm.volume + e.liters
        stats.byFarm[e.farmId] = fm
    end

    -- Lucro líquido da coop = recebeu - pagou
    stats.netProfit = stats.earnedSelling - stats.spentBuying

    -- Produto mais lucrativo
    local bestFt, bestProfit = nil, -math.huge
    for name, data in pairs(stats.byFillType) do
        if data.profit > bestProfit then
            bestProfit = data.profit
            bestFt = name
        end
    end
    stats.topFillType = bestFt
    stats.topFillTypeProfit = (bestFt ~= nil) and bestProfit or 0

    return stats
end

-- ─── Persistência (savegame) ─────────────────────────────
function TransactionLog:saveToXML(xmlFile, key)
    local i = 0
    for _, e in ipairs(self.entries) do
        local entryKey = string.format("%s.entry(%d)", key, i)
        xmlFile:setString(entryKey .. "#kind",     e.kind)
        xmlFile:setInt(entryKey .. "#farmId",      e.farmId)
        xmlFile:setString(entryKey .. "#fillType", e.fillType)
        xmlFile:setFloat(entryKey .. "#liters",    e.liters)
        xmlFile:setFloat(entryKey .. "#value",     e.value)
        xmlFile:setInt(entryKey .. "#day",         e.day)
        xmlFile:setFloat(entryKey .. "#hour",      e.hour)
        i = i + 1
    end
end

function TransactionLog:loadFromXML(xmlFile, key)
    self.entries = {}
    local i = 0
    while true do
        local entryKey = string.format("%s.entry(%d)", key, i)
        local kind = xmlFile:getString(entryKey .. "#kind")
        if kind == nil then break end

        table.insert(self.entries, {
            kind     = kind,
            farmId   = xmlFile:getInt(entryKey .. "#farmId", 0),
            fillType = xmlFile:getString(entryKey .. "#fillType", "?"),
            liters   = xmlFile:getFloat(entryKey .. "#liters", 0),
            value    = xmlFile:getFloat(entryKey .. "#value", 0),
            day      = xmlFile:getInt(entryKey .. "#day", 1),
            hour     = xmlFile:getFloat(entryKey .. "#hour", 0),
        })
        i = i + 1
    end
    DepotLogger.info(">>> TransactionLog: %d transações carregadas do save", #self.entries)
end
