-- 周年活动 - 代金转转乐
-- db
--[=[
    human.db.absAct[ACT_ID] = {
        lotteryTimes   = 0,  -- 可用抽奖次数（每累充100元+1，可叠加，活动结束清空）
        totalRecharge  = 0,  -- 活动期间累充总额（跨天持续累加）
        processedDaily = 0,  -- 本日已从 topupAcountDaily 处理过的金额，跨天由 updateDaily 清零
    }
]=]--

local Msg          = require("core.Msg")
local Grid         = require("bag.Grid")
local BagLogic     = require("bag.BagLogic")
local AbsActLogic  = require("absAct.AbsActLogic")
local Broadcast    = require("broadcast.Broadcast")
local Lang         = require("common.Lang")
local YunYingLogic = require("yunying.YunYingLogic")
local AbsActExcel  = require("excel.absAct")
local RewardCfg    = require("excel.anniversaryAct").voucherWheel
local variablesCfg = require("excel.anniversaryAct").var

local LOGTYPE      = "AnniversaryVoucherWheel"
local ACT_ID       = 7702


local function getData(human)
    return human.db.absAct[ACT_ID]
end

local function addTimes(human, val)
    local d = getData(human)
    d.lotteryTimes = (d.lotteryTimes or 0) + val
end


local function isOpenAct(human, funcID)
    return AbsActLogic.isStarted(human, funcID or ACT_ID)
end
-- 每累充x, 获得1次机会
local function getRechargeUnit()
    local cfg = variablesCfg[1]
    return cfg.rechargeUnit
end

local function updateRedDot(human)
    YunYingLogic.sendBanner(human)
    local config = AbsActExcel.absActivity[ACT_ID]
    YunYingLogic.sendGroupUpdate(YYInfo[ACT_ID], human, config.panelID)
end

local function doLottery()
    local totalWeight = 0
    for _, row in ipairs(RewardCfg) do
        totalWeight = totalWeight + row.weight
    end
    if totalWeight <= 0 then return 0 end

    local r, acc = math.random(1, totalWeight), 0
    for i, row in ipairs(RewardCfg) do
        acc = acc + row.weight
        if r <= acc then return i end
    end
    return 0
end

local function doMultiLottery(count)
    local results = {}
    for _ = 1, count do
        local idx = doLottery()
        if idx == 0 then return nil end
        local row = RewardCfg[idx]
        results[#results + 1] = { itemId = row.reward[1], itemNum = row.reward[2] }
    end
    return results
end


-- config 为第一参数（框架固定传入），human 为新增第二参数
function genAbsActData(config, human)
    local initRecharge = (human and human.db.topupAcountDaily) or 0
    local rechargeUnit = getRechargeUnit()
    local initTimes    = math.floor(initRecharge / rechargeUnit)
    return {
        lotteryTimes   = initTimes,    -- 活动开启前当天已充的次数直接算入
        totalRecharge  = initRecharge, -- 以当天已充金额为起点
        processedDaily = initRecharge, -- 标记已处理到此刻，避免 onCharge 重复计算
    }
end

-- 跨天回调（玩家在线或上线时由框架调用一次）
-- topupAcountDaily 已跨天清零，同步重置 processedDaily，确保 onCharge 计算正确
function updateDaily(human, funcID)
    if not isOpenAct(human, funcID) then return end
    local d = getData(human)
    if not d then return end
    d.processedDaily = 0
end

function isRed(human, YYInfo, funcConfig)
    if not isOpenAct(human, funcConfig and funcConfig.funcID) then return false end
    local d = getData(human)
    if not d then return false end
    return (d.lotteryTimes or 0) > 0
end

function isOpen(human, YYInfo, funcConfig)
    return isOpenAct(human, funcConfig and funcConfig.funcID)
end

function isActive(human, YYInfo, funcConfig)
    return not isOpen(human, YYInfo, funcConfig)
end



-- 充值回调
-- 框架在充值成功并更新 topupAcountDaily 后自动调用
-- 活动开启当天0点起计算，活动开启前当天的充值因 processedDaily=0 会在首次触发时自动补算
function onCharge(human, price, funcID, buyID, buyNum)
    if not isOpenAct(human) then return end

    local d          = getData(human)
    local dailyTotal = human.db.topupAcountDaily  -- 今日0点起累计（已含本次充值）
    local processed  = d.processedDaily or 0

    local delta = dailyTotal - processed
    if delta <= 0 then return end

    local oldTotal   = d.totalRecharge or 0
    local newTotal   = oldTotal + delta
    d.totalRecharge  = newTotal
    d.processedDaily = dailyTotal

    local rechargeUnit = getRechargeUnit()
    local oldTimes = math.floor(oldTotal  / rechargeUnit)
    local newTimes = math.floor(newTotal  / rechargeUnit)
    local gained   = newTimes - oldTimes

    if gained > 0 then
        addTimes(human, gained)
        updateRedDot(human)
    end
end

function VoucherWheel_Query(human)
    if not isOpenAct(human) then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local d = getData(human)
    local _, endTime, startTime = isOpenAct(human)

    local msgRet = Msg.gc.GC_ANNIV_VOUCHER_WHEEL_QUERY
    msgRet.lotteryTimes  = d.lotteryTimes  or 0
    msgRet.totalRecharge = d.totalRecharge or 0
    msgRet.startTime     = startTime or 0
    msgRet.endTime       = endTime   or 0

    -- 下发完整奖励配置表
    msgRet.rewardList[0] = 0
    for i, row in ipairs(RewardCfg) do
        msgRet.rewardList[0] = i
        Grid.makeItem(msgRet.rewardList[i], row.reward[1], row.reward[2])
    end

    Msg.send(msgRet, human.fd)
end

local function doSpin(human, count)
    if not isOpenAct(human) then
        return Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
    end

    local d = getData(human)
    local curTimes = d.lotteryTimes or 0
    if curTimes < count then
        return Broadcast.sendErr(human, Lang.JINBI_EXCHANGE_ERR_CNT)
    end

    local results = doMultiLottery(count)
    if not results then
        return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
    end

    d.lotteryTimes = curTimes - count

    for _, res in ipairs(results) do
        BagLogic.addItem(human, res.itemId, res.itemNum, LOGTYPE)
    end

    -- 告知客户端完整结果列表，客户端据此播放动画
    local msgRet = Msg.gc.GC_ANNIV_VOUCHER_WHEEL_RESULT
    msgRet.count      = count
    msgRet.results[0] = 0
    for i, res in ipairs(results) do
        msgRet.results[0] = i
        Grid.makeItem(msgRet.results[i], res.itemId, res.itemNum)
    end
    msgRet.lotteryTimes      = d.lotteryTimes

    Msg.send(msgRet, human.fd)

    updateRedDot(human)
end

function VoucherWheel_Single(human)
    doSpin(human, 1)
end

function VoucherWheel_Ten(human)
    doSpin(human, 10)
end