-- ============================================================
-- Komo Hold'Em — Ledger
-- Settle-up records, personal leaderboards (Gold / Chips), and
-- guild leaderboard sync (GUILD channel only — Gold/Chips tabs
-- never sync anywhere).
--
-- Every table has a unique id (host + open-time), so entries are
-- idempotent: syncing or replaying results can never double-count.
-- ============================================================
local _, KH = ...
KH.Ledger = {}
local Ledger = KH.Ledger

-- ------------------------------------------------------------
-- record a closed table
-- results:   { [playerFull] = netAmount }  (+win / -loss)
-- transfers: { { from=, to=, amt=, paid=false } } gold tables only
-- ------------------------------------------------------------
function Ledger:RecordTable(tbl, results, transfers)
    -- dedupe by table id
    for _, e in ipairs(KH.db.ledger) do
        if e.id == tbl.id then return false end
    end

    KH.db.ledger[#KH.db.ledger + 1] = {
        id        = tbl.id,
        when      = time(),
        stakes    = tbl.config.stakes,
        amount    = tbl.config.amount,
        hands     = tbl.handNo,
        results   = results,
        transfers = transfers or {},
    }

    -- fold into personal leaderboard
    local board = KH.db.leaderboard
    for player, net in pairs(results) do
        board[player] = board[player] or { gold = 0, chips = 0, tables = 0, handsWon = 0 }
        local row = board[player]
        row.tables = row.tables + 1
        if tbl.config.stakes == "gold" then
            row.gold = row.gold + net
        else
            row.chips = row.chips + net
        end
    end
    return true
end

function Ledger:MarkPaid(tableId, from, to)
    for _, e in ipairs(KH.db.ledger) do
        if e.id == tableId then
            for _, t in ipairs(e.transfers) do
                if t.from == from and t.to == to then
                    t.paid = true
                    KH.Sounds:Play("DEBT_PAID")
                    return true
                end
            end
        end
    end
    return false
end

-- unpaid gold debts involving me (fuel for launcher reminders)
function Ledger:OutstandingDebts()
    local owedToMe, iOwe = {}, {}
    for _, e in ipairs(KH.db.ledger) do
        for _, t in ipairs(e.transfers) do
            if not t.paid then
                if t.to == KH.playerFull then
                    owedToMe[#owedToMe + 1] = { tableId = e.id, from = t.from, amt = t.amt }
                elseif t.from == KH.playerFull then
                    iOwe[#iOwe + 1] = { tableId = e.id, to = t.to, amt = t.amt }
                end
            end
        end
    end
    return owedToMe, iOwe
end

-- ------------------------------------------------------------
-- sorted rows for leaderboard UI
-- mode: "gold" | "chips" (personal) | "guild" (last synced set)
-- ------------------------------------------------------------
function Ledger:Rows(mode)
    local src = (mode == "guild") and KH.db.guildBoard or KH.db.leaderboard
    local key = (mode == "chips") and "chips" or "gold"
    local rows = {}
    for player, r in pairs(src) do
        rows[#rows + 1] = {
            name   = player,
            net    = r[key] or 0,
            tables = r.tables or 0,
            you    = (player == KH.playerFull),
        }
    end
    table.sort(rows, function(a, b) return a.net > b.net end)
    return rows
end

-- ------------------------------------------------------------
-- guild sync — GUILD channel only, gold results only
-- ------------------------------------------------------------
function Ledger:GuildSyncRequest()
    if not KH.Comms:Guild(KH.Comms.MSG.GUILD_SYNC_REQ) then
        KH:Print("You're not in a guild — guild leaderboard unavailable.")
        return false
    end
    return true
end

-- handler registration happens once comms are up
function Ledger:Init()
    local MSG = KH.Comms.MSG

    KH.Comms:RegisterHandler(MSG.GUILD_SYNC_REQ, function(sender)
        -- respond with my gold rows (only gold tables are guild-visible)
        local rows = Ledger:Rows("gold")
        local parts = {}
        for i = 1, math.min(#rows, 10) do
            local r = rows[i]
            parts[#parts + 1] = r.name .. ";" .. r.net .. ";" .. r.tables
        end
        KH.Comms:Guild(MSG.GUILD_SYNC, table.concat(parts, "~"))
    end)

    KH.Comms:RegisterHandler(MSG.GUILD_SYNC, function(sender, _, fields)
        for _, entry in ipairs(fields) do
            local name, net, tables = strsplit(";", entry)
            if name and net then
                KH.db.guildBoard[name] = {
                    gold   = tonumber(net) or 0,
                    tables = tonumber(tables) or 0,
                }
            end
        end
        if KH.Launcher and KH.Launcher.RefreshLeaderboard then
            KH.Launcher:RefreshLeaderboard()
        end
    end)
end
