--------------------------------
-- 文件名       ：  TreasureChestLogic.lua
-- 文件说明     ：  宝箱系统
-- 创建时间     :   2025/03/10
-- 创建人       :   FC
--------------------------------
---
local Util = require("common.Util")
local Msg = require("core.Msg")
local BagLogic = require("bag.BagLogic")
local Log = require("common.Log")
local TreasureConf = require("excel.treasurechest")
local CommonDefine = require("common.CommonDefine")
local Grid = require("bag.Grid")
local MainDianLogic = require("MaiDian.MaiDianLogic")
local MaiDianDefine = require("MaiDian.MaiDianDefine")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")
local WeekTaskLogic = require("dailyTask.WeekTaskLogic")

-- 奖励缓存有序 key为宝箱类型
local tCacheBoxPrize = nil

-- 一次性最多打开宝箱数量
local TREASURECHEST_OPEN_NUM = 9999

-- 自动开宝箱解锁条件
local TREASURECHEST_OPEN_AUTO_TYPE  =   5       -- 钻石
local TREASURECHEST_OPEN_AUTO_NUM   =   2       -- 开两次

local TREASURECHEST_OPEN_ONETOUCH_NUM = 10       -- 激活一键开启宝箱功能, 需要开启钻石宝箱数量

----------------------------------------- 内部处理开始 -------------------------------------


-- 写日志
local function TreasureChestLogic_WriteLog(human, szText)
    Log.write(Log.LOGID_OSS_COMMON, "name = "..human.db.name.." id = "..human.db._id..szText)
end

-- 获取宝箱配置
local function TreasureChestLogic_GetBoxTypeConf()
    return TreasureConf.boxtype
end

-- 获取宝箱积分配置
local function TreasureChestLogic_GetPointConf()
    return TreasureConf.boxpoint
end


-- 重置积分奖励数据
local function TreasureChestLogic_ResetDBPointPrize(human)
    local tBoxPoint = TreasureChestLogic_GetPointConf()
    
    for key, v in pairs(tBoxPoint) do
        human.db.TreasureChest.tPointPrize[key] = CommonDefine.COMMON_PRIZE_STATE_NOGET
    end
end

-- 创建DB数据
local function TreasureChestLogic_CreateDB(human)
    human.db.TreasureChest = {
        nPoint = 0,
        nOpenNum = 0,
        tPointPrize  = {},
        tItem = {}, -- 宝箱数量
        openBoxSumNum = 0, -- 开启宝箱总数量
    }

    TreasureChestLogic_ResetDBPointPrize(human)
end

-- 获取开启总宝箱数量
local function TreasureChestLogic_GetDBOpenBoxSumNum(human)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    return human.db.TreasureChest.openBoxSumNum
end

-- 增加宝箱开启数量
local function TreasureChestLogic_AddDBOpenBoxSumNum(human, nValue)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    human.db.TreasureChest.openBoxSumNum = (human.db.TreasureChest.openBoxSumNum or 0) + nValue
end




-- 获取宝箱奖励配置
local function TreasureChestLogic_GetPointPrizeConf(human)
    local openBoxSumNum = TreasureChestLogic_GetDBOpenBoxSumNum(human)

    --if not tCacheBoxPrize then
        tCacheBoxPrize = {}
        for _, v in pairs(TreasureConf.boxprize) do
            local nType = v.nType
            if not tCacheBoxPrize[nType] then
                tCacheBoxPrize[nType] = {}
            end

            -- table.insert(tCacheBoxPrize[nType], v)
            if openBoxSumNum >= v.count then
                table.insert(tCacheBoxPrize[nType], v)
            end
        end

        -- 变成有序
        for _, v in pairs(tCacheBoxPrize) do
            table.sort(v, function (l, r)
                return l.nPro < r.nPro
            end)
        end

        -- 整合权重
        for _, data in ipairs(tCacheBoxPrize) do
            local nAllWeight = 0
            for _, v in ipairs(data) do
                if nAllWeight == 0 then
                    nAllWeight = v.nPro
                else
                    nAllWeight = nAllWeight + v.nPro
                end

                v.nAllPro = nAllWeight
            end
        end
    --end

    return tCacheBoxPrize
end





-- 获取当前积分
local function TreasureChestLogic_GetDBPoint(human)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    return human.db.TreasureChest.nPoint
end

-- 设置当前积分
local function TreasureChestLogic_SetDBPoint(human, nValue)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    human.db.TreasureChest.nPoint = nValue
end

-- 获取当前积分奖励状态
local function TreasureChestLogic_GetDBPointPrize(human, nID)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    return human.db.TreasureChest.tPointPrize[nID]
end

-- 设置当前积分奖励状态
local function TreasureChestLogic_SetDBPointPrize(human, nID, nState)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    human.db.TreasureChest.tPointPrize[nID] = nState
end

-- 更新积分奖励状态
local function TreasureChestLogic_UpdatePointPrize(human)
    local nNowPoint = TreasureChestLogic_GetDBPoint(human)
    local tBoxPointCof = TreasureChestLogic_GetPointConf()

    for nID, v in ipairs(tBoxPointCof) do
        local nState = TreasureChestLogic_GetDBPointPrize(human, nID)
        if nNowPoint >= v.nPoint then
            --print("[TreasureChestLogic_UpdatePointPrize] nID = "..nID.." nNowPoint "..nNowPoint.." nPoint "..v.nPoint.." nState "..nState)
            if CommonDefine.COMMON_PRIZE_STATE_NOGET == nState then
                TreasureChestLogic_SetDBPointPrize(human, nID,  CommonDefine.COMMON_PRIZE_STATE_CANGET)
                nNowPoint = nNowPoint - v.nPoint
            elseif CommonDefine.COMMON_PRIZE_STATE_CANGET == nState then
                nNowPoint = nNowPoint - v.nPoint
            end
        else
            if CommonDefine.COMMON_PRIZE_STATE_NOGET == nState then
                break
            end
        end
    end
end

-- 打开宝箱操作
local function TreasureChestLogic_OpenBox(human, nType, nBoxNum)
    local tBoxTypeConf = TreasureChestLogic_GetBoxTypeConf()
    local tBoxPrize = TreasureChestLogic_GetPointPrizeConf(human)
    if not tBoxTypeConf[nType] or not tBoxPrize[nType] then
        return nil
    end
    local nOpenNum = tBoxTypeConf[nType].nOpenNum
    -- 获取的表是有序的
    local tBoxTypePrize = tBoxPrize[nType]
    local nLen = #tBoxTypePrize
    local nAllWeight = tBoxTypePrize[nLen].nAllPro
    --print("[TreasureChestLogic_OpenBox] nAllWeight = "..nAllWeight)

    local tOpenPrize = {}
    for i = 1, nBoxNum, 1 do
        for j = 1, nOpenNum, 1 do
            -- 随机权重
            local nRandNum = math.random(1, nAllWeight)
            --print("[TreasureChestLogic_OpenBox] j = "..j.." nRandNum = "..nRandNum)
            for _, v in pairs(tBoxTypePrize) do
                --print("[TreasureChestLogic_OpenBox] nAllPro = "..v.nAllPro.." ID = "..v.tPrize[1].." num = "..v.tPrize[2].."\n")
                if nRandNum <= v.nAllPro then
                    table.insert(tOpenPrize, v.tPrize)
                    --print("[TreasureChestLogic_OpenBox] 获得的道具 nID = "..v.tPrize[1].." nNum = "..v.tPrize[2].." nKey "..v.nAllPro)
                    TreasureChestLogic_AddDBOpenBoxSumNum(human, 1)
                    break
                end
            end

            tBoxPrize = TreasureChestLogic_GetPointPrizeConf(human)
            tBoxTypePrize = tBoxPrize[nType]
            nLen = #tBoxTypePrize
            nAllWeight = tBoxTypePrize[nLen].nAllPro
        end
    end

    return tOpenPrize
end

-- 获取宝箱数量
local function TreasureChestLogic_GetGoodsNum(human, nGoodsID)
    if not human.db.TreasureChest.tItem[nGoodsID] then
        human.db.TreasureChest.tItem[nGoodsID] = 0
    end
    
    return human.db.TreasureChest.tItem[nGoodsID]
end

-- 添加宝箱物品
local function TreasureChestLogic_AddGoods(human, nGoodsID, nGoodsNum)
    if not human.db.TreasureChest.tItem[nGoodsID] then
        human.db.TreasureChest.tItem[nGoodsID] = 0
    end
    
    human.db.TreasureChest.tItem[nGoodsID] = human.db.TreasureChest.tItem[nGoodsID] + nGoodsNum
end

-- 删除物品
local function TreasureChestLogic_DelGoods(human, nGoodsID, nGoodsNum)
    human.db.TreasureChest.tItem[nGoodsID] = human.db.TreasureChest.tItem[nGoodsID] - nGoodsNum
    if 0 > human.db.TreasureChest.tItem[nGoodsID] then
        human.db.TreasureChest.tItem[nGoodsID] = 0
    end

    TreasureChestLogic_WriteLog(human, "减少了宝箱道具 nItemID "..nGoodsID.." nDelNum "..nGoodsNum)
end

-- 获取当前打开的钻石宝箱数量
local function TreasureChestLogic_GetAutoOpenNum(human)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    return human.db.TreasureChest.nOpenNum
end

-- 记录打开钻石宝箱数量
local function TreasureChestLogic_AddAutoNum(human, nType, nNum)
    if TREASURECHEST_OPEN_AUTO_TYPE ~= nType then
        print("[TreasureChestLogic_AddAutoNum] 类型不正确返回")
        return
    end

    -- local nNowNum = TreasureChestLogic_GetAutoOpenNum(human)
    -- if TREASURECHEST_OPEN_AUTO_NUM <= nNowNum then
    --     print("[TreasureChestLogic_AddAutoNum] 数量已经足够 nNowNum = "..nNowNum)
    --     return
    -- end

    local nNowNum = TreasureChestLogic_GetAutoOpenNum(human)
    if TREASURECHEST_OPEN_ONETOUCH_NUM <= nNowNum then
        print("[TreasureChestLogic_AddAutoNum] 数量已经足够 nNowNum = "..nNowNum)
        return
    end


    human.db.TreasureChest.nOpenNum = human.db.TreasureChest.nOpenNum + nNum


    if human.db.TreasureChest.nOpenNum >= TREASURECHEST_OPEN_ONETOUCH_NUM then
        TreasureChestLogic_Query(human)
    end
end


-- 处理老数据
local function openBoxSumNumCheck(human)
    local num = TreasureChestLogic_GetDBOpenBoxSumNum(human)
    if not num then
        TreasureChestLogic_AddDBOpenBoxSumNum(human, 2300)
    end
end


----------------------------------------- 客户端请求 -------------------------------------
-- 请求宝箱界面信息
function TreasureChestLogic_Query(human)
    if not human then
        return
    end

    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    TreasureChestLogic_UpdatePointPrize(human)

    -- table.print_lua_table(human.db.TreasureChest)
    -- print("\n")

    --local nOpenNum = TreasureChestLogic_GetAutoOpenNum(human)
    local tMsgData = Msg.gc.GC_TEEASURECHEST_QUERY
    tMsgData.nNowPoint = TreasureChestLogic_GetDBPoint(human)
    -- tMsgData.nAuto = TreasureChestLogic_GetAutoOpenNum(human) >= TREASURECHEST_OPEN_AUTO_NUM and 1 or 0
    tMsgData.nAuto = 1 --改为默认开启
    tMsgData.nOneTouch = TreasureChestLogic_GetAutoOpenNum(human) >= TREASURECHEST_OPEN_ONETOUCH_NUM and 1 or 0
    tMsgData.nID = 0
    tMsgData.nNextPoint = 0
    tMsgData.nState = 0
    local tBoxPointConf = TreasureChestLogic_GetPointConf() 
    local tBoxTypeConf = TreasureChestLogic_GetBoxTypeConf()

    --print("[TreasureChestLogic_Query] nAuto = "..tMsgData.nAuto.." num = "..nOpenNum)

    -- 下一阶段需要的积分信息
    for nID, v in ipairs(tBoxPointConf) do
        local nState = TreasureChestLogic_GetDBPointPrize(human, nID)

        if CommonDefine.COMMON_PRIZE_STATE_NOGET == nState or CommonDefine.COMMON_PRIZE_STATE_CANGET == nState then
            tMsgData.nID = nID
            tMsgData.nNextPoint = v.nPoint
            tMsgData.nState = nState
            Grid.makeItem(tMsgData.tPointPirze, v.tPrize[1], v.tPrize[2])
            break
        end
    end

    -- 奖励信息
    local nLen = 0
    for nType, v in pairs(tBoxTypeConf) do
        nLen = nLen + 1
        tMsgData.tList[0] = nLen
        local tData = tMsgData.tList[nLen]
        tData.nType = nType
        local nGoodsID = v.nItemID
        local nGoodsNum = TreasureChestLogic_GetGoodsNum(human, nGoodsID)
        Grid.makeItem(tData.tItemData, nGoodsID, nGoodsNum)
    end

    Msg.send(tMsgData, human.fd)
end

-- 请求宝箱内奖励信息
function TreasureChestLogic_QueryPrize(human, nBoxType)
    local tBoxPrize = TreasureChestLogic_GetPointPrizeConf()
    if not tBoxPrize[nBoxType] then
        print("[TreasureChestLogic_QueryPrize] 不存在对应的奖励配置 nBoxType = "..nBoxType)
        return
    end

    local tBoxTypePrize = tBoxPrize[nBoxType]
    local tMsgData = Msg.gc.GC_TEEASURECHEST_PRIZE_QUERY

    local nLen = 0
    tMsgData.tItemData[0] = nLen
    for _, v in pairs(tBoxTypePrize) do
            nLen = nLen + 1
            tMsgData.tItemData[0] = nLen
    
            local tData = tMsgData.tItemData[nLen]
            local nGoodsID = v.prize[1]
            local nGoodsNum = v.prize[2]
            local quality = v.prize[3]
            Grid.makeItem(tData, nGoodsID, nGoodsNum, nil, nil, nil, nil, quality)
    end

    Msg.send(tMsgData, human.fd)
end

-- 请求打开宝箱
function TreasureChestLogic_Open(human, nBoxType, nBoxNum)
    openBoxSumNumCheck(human)

    print("[TreasureChestLogic_Open]玩家当前请求打开的宝箱类型 ntyepe = "..nBoxType)
    local szText = "[TreasureChestLogic_Open] 玩家请求打开宝箱 nBoxType = "..nBoxType.." nBoxNum = "..nBoxNum
    TreasureChestLogic_WriteLog(human, szText)

    if nBoxNum >= TREASURECHEST_OPEN_NUM or 0 >= nBoxNum then
        szText = szText .. " 失败不正确的打开数量 nBoxNum "..nBoxNum
        TreasureChestLogic_WriteLog(human, szText)
        return
    end

    -- 检测配置
    local tBoxTypeConf = TreasureChestLogic_GetBoxTypeConf()
    if not tBoxTypeConf[nBoxType] then
        print("[TreasureChestLogic_Open] 不存在对应的宝箱类型 nBoxType = "..nBoxType)
        szText = szText.." 失败不存在对应宝箱类型"
        TreasureChestLogic_WriteLog(human, szText)
        return
    end

    local nGoodsID = tBoxTypeConf[nBoxType].nItemID
    local nGoodsNum = TreasureChestLogic_GetGoodsNum(human, nGoodsID)
    if nBoxNum > nGoodsNum or 0 >= nGoodsNum then
        print("[TreasureChestLogic_Open] 玩家拥有宝箱数量不足 nBoxType = "
                ..nBoxType.." nBoxNum = "..nBoxNum.." nGoodsNum = "..nGoodsNum)

        szText = szText.." 数量不正确 nGoodsNum = "..nGoodsNum
        TreasureChestLogic_WriteLog(human, szText)
        return
    end

    local tPrize = TreasureChestLogic_OpenBox(human, nBoxType, nBoxNum)

    -- 发送奖励
    BagLogic.addItemList(human, tPrize, "treasurechest")
    --BagLogic.sendItemGetList(human, tPrize, "treasurechest")
    szText = szText .." 发送奖励成功"
    TreasureChestLogic_WriteLog(human, szText)

    -- 加积分
    local nAddPoint = nBoxNum * tBoxTypeConf[nBoxType].nPoint
    local nNowPoint = TreasureChestLogic_GetDBPoint(human)
    nNowPoint = nAddPoint + nNowPoint
    TreasureChestLogic_SetDBPoint(human, nNowPoint)
    szText = szText.." 增加积分 nAddPoint = "..nAddPoint.." nNowPoint = "..nNowPoint
    TreasureChestLogic_WriteLog(human, szText)

    -- 删除使用了的物品
    TreasureChestLogic_DelGoods(human, nGoodsID, nBoxNum)

    -- 更新积分奖励状态
    TreasureChestLogic_UpdatePointPrize(human)

    
    MainDianLogic.MaiDian_Begin(human, MaiDianDefine.MAIDIAN_TYPE_CHEST_OPEN,{nValue = nBoxNum})  
    
    if TREASURECHEST_OPEN_AUTO_TYPE == nBoxType then
        TreasureChestLogic_AddAutoNum(human, nBoxType, nBoxNum)
    end

    TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_OPENBOX, human.db._id, nBoxNum,nBoxType)
    print("TreasureChestLogic..当前已经进入商业活动注册事件",nBoxType)
    --周任务开启宝箱
    WeekTaskLogic.recordWeekTaskFinishCnt(human, WeekTaskLogic.WEEK_TASK_ID_5, nBoxNum)
    TreasureChestLogic_Query(human)
    TreasureChestLogic_GetAllBoxNum(human)
end

-- 请求自动打开宝箱
function TreasureChestLogic_AutoOpen(human, nBoxType)
    local szText = "[TreasureChestLogic_AutoOpen] 玩家请求打开宝箱开始 nBoxType = "..nBoxType

    local tBoxTypeConf = TreasureChestLogic_GetBoxTypeConf()
    if not tBoxTypeConf[nBoxType] then
        print("[TreasureChestLogic_AutoOpen] 不存在对应的宝箱类型 nBoxType = "..nBoxType)
        szText = szText.." 失败不存在对应宝箱类型"
        TreasureChestLogic_WriteLog(human, szText)
        return
    end

    local nGoodsID = tBoxTypeConf[nBoxType].nItemID
    local nGoodsNum = TreasureChestLogic_GetGoodsNum(human, nGoodsID)
    if 0 >= nGoodsNum then
        return
    end

    -- 改为默认开启
    -- if TreasureChestLogic_GetAutoOpenNum(human) < TREASURECHEST_OPEN_AUTO_NUM then
    --     return
    -- end

    TreasureChestLogic_WriteLog(human, szText)
    TreasureChestLogic_Open(human, nBoxType, 1)

    TreasureChestLogic_GetAllBoxNum(human)
end

-- 请求领取积分奖励
function TreasureChestLogic_GetPointPrize(human, nID)
    local szText = "[TreasureChestLogic_GetPointPrize] 玩家请求领取积分奖励 nID = "..nID

    local tPointPrize = TreasureChestLogic_GetPointConf()
    if not tPointPrize[nID] then
        print("[TreasureChestLogic_GetPointPrize] 不存在对应的积分ID nID = "..nID)
        return
    end

    -- 积分检测
    local nNowPoint = TreasureChestLogic_GetDBPoint(human)
    if nNowPoint < tPointPrize[nID].nPoint then
        print("[TreasureChestLogic_GetPointPrize] 玩家当前积分不足 nNowPoint = "
                ..nNowPoint.." nNeedPoint = "..tPointPrize[nID].nPoint)
        return
    end

    local nState = TreasureChestLogic_GetDBPointPrize(human, nID)
    if CommonDefine.COMMON_PRIZE_STATE_CANGET ~= nState then
        print("[TreasureChestLogic_GetPointPrize] 玩家奖励状态不正确 nNowPoint = "
                ..nNowPoint.." nState = "..nState.."nID = "..nID)
        return
    end

    local tGoodsInfo = 
    {
        [tPointPrize[nID].tPrize[1]] = tPointPrize[nID].tPrize[2]
    }

    -- 添加奖励
    BagLogic.addItemList(human, tGoodsInfo, "treasurechest")
    -- BagLogic.sendItemGetList(human, tGoodsInfo, "treasurechest")
    TreasureChestLogic_SetDBPointPrize(human, nID,  CommonDefine.COMMON_PRIZE_STATE_GET)

    local szSendPrize = szText .. " 发送奖励成功 nGoodsID = "..tPointPrize[nID].tPrize[1]
                        .." nGoodsNum = "..tPointPrize[nID].tPrize[2]
    TreasureChestLogic_WriteLog(human, szSendPrize)

    -- 改变积分
    local nNewPoint = nNowPoint - tPointPrize[nID].nPoint
    TreasureChestLogic_SetDBPoint(human, nNewPoint)

    local szPointPrize = szText.." nNowPoint = "..nNowPoint.." nDelPoint = "
                            ..tPointPrize[nID].nPoint.." nNewPoint = "..nNewPoint
    TreasureChestLogic_WriteLog(human, szPointPrize)

    if 0 == tPointPrize[nID].nNextID then
        TreasureChestLogic_ResetDBPointPrize(human)
        local szResetText = szText.." 玩家领取完最后的奖励进行重置"
        TreasureChestLogic_WriteLog(human, szResetText)
    end

    -- 更新积分奖励状态
    TreasureChestLogic_UpdatePointPrize(human)

    TreasureChestLogic_Query(human)

    TreasureChestLogic_GetAllBoxNum(human)
end

--请求一件开启宝箱
function TreasureChestLogic_OneTouchOpen(human)
    local boxCfg = TreasureChestLogic_GetBoxTypeConf()

    for boxType, boxInfo in ipairs(boxCfg) do
        local nGoodsID = boxInfo.nItemID
        local nGoodsNum = TreasureChestLogic_GetGoodsNum(human, nGoodsID)
        if nGoodsNum > 0 then
            TreasureChestLogic_Open(human, boxType, nGoodsNum)
        end
    end

    TreasureChestLogic_GetAllBoxNum(human)
end


function TreasureChestLogic_GmClear(human)
    TreasureChestLogic_CreateDB(human)
end

-- 增加道具
function TreasureChestLogic_AddItem(human, nItemID, nAddNum)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    if 0 >= nAddNum then
        return
    end

    TreasureChestLogic_AddGoods(human, nItemID, nAddNum)
    TreasureChestLogic_WriteLog(human, "增加了宝箱道具 nItemID "..nItemID.." nAddNum "..nAddNum)
end

-- 购买终身月卡解锁自动开宝箱
function TreasureChestLogic_BuyOpenAuto(human)
    --local nOpenNum = TreasureChestLogic_GetAutoOpenNum(human)
    --print("[TreasureChestLogic_BuyOpenAuto] nOpenNum = "..nOpenNum)
    -- TreasureChestLogic_AddAutoNum(human, TREASURECHEST_OPEN_AUTO_TYPE, TREASURECHEST_OPEN_AUTO_NUM)

    TreasureChestLogic_AddAutoNum(human, TREASURECHEST_OPEN_AUTO_TYPE, TREASURECHEST_OPEN_ONETOUCH_NUM)
end

function TreasureChestLogic_GetAllBoxNum(human)
    if not human.db.TreasureChest then
        TreasureChestLogic_CreateDB(human)
    end

    local tBoxTypeConf = TreasureChestLogic_GetBoxTypeConf()

    local tMsgData =  Msg.gc.GC_GET_ALL_GJBOX_NUM
    local nAllNum = 0
    for nType, v in pairs(tBoxTypeConf) do
        local nGoodsID = v.nItemID
        local nGoodsNum = TreasureChestLogic_GetGoodsNum(human, nGoodsID)
        nAllNum = nAllNum + nGoodsNum
    end

    tMsgData.nAllNum = nAllNum

    Msg.send(tMsgData, human.fd)
end