---------------------------------------------------
-- 充值-每周/每月礼包
-- 开服起每x天为1期

-- db.richangLibao[libaoType] = libaoData
-- libaoData.ts 				购买时间戳	
-- libaoData.list				购买记录 [id] = cnt
---------------------------------------------------

local Util = require("common.Util")
local PresentExcel = require("excel.present")
local Lang = require("common.Lang")
local CommonDB = require("common.CommonDB")
local Msg = require("core.Msg")
local Broadcast = require("broadcast.Broadcast")
local PanelDefine = require("broadcast.PanelDefine")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local BuyLogic = require("topup.BuyLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local CommonDB = require("common.CommonDB")

LIBAOTYPE_WEEK = 1 			-- 每周礼包
LIBAOTYPE_MONTH = 2 		-- 每月礼包

FREE_BUY = 1 				-- 免费领取
RMB_BUY = 2 				-- rmb购买


local COND_OPEN_SRV_DAYS = 2	--  需要开服2天后才展示

local WEEK_GITFT_ACTID = 315	-- 周礼包活动Id
local MONTH_GITFT_ACTID = 316	-- 月礼包活动Id

-- 根据类型获取配置
function getConfigs(libaoType)
	if libaoType == LIBAOTYPE_WEEK then
		return PresentExcel.weekLibao
	elseif libaoType == LIBAOTYPE_MONTH then
		return PresentExcel.monthLibao
	end
end

-- 获取刷新周期 x天
function getRefreshDay(libaoType)
	if libaoType == LIBAOTYPE_WEEK then
		return 7
	elseif libaoType == LIBAOTYPE_MONTH then
		return 30
	end
end

-- 
function getLogType(libaoType)
	if libaoType == LIBAOTYPE_WEEK then
		return "week_libao"
	elseif libaoType == LIBAOTYPE_MONTH then
		return "month_libao"
	end
end

-- 获取本期礼包开始和结束时间
function getLibaoTime(libaoType)
	local openDay = CommonDB.getServerOpenDay()
	if not openDay then return end -- 没有设置开服时间 不开活动哦
	if openDay < 1 then return end -- 开服时间不对 也不开

	local refreshDay = getRefreshDay(libaoType)
	if not refreshDay then return end

	local day = openDay % refreshDay -- 本期礼包 第x天
	if day == 0 then
		day = refreshDay
	end
	local dayStartTime = Util.getDayStartTime(os.time())
	local startTime = dayStartTime - (day - 1) * 86400
	local endTime = startTime + refreshDay * 86400
	return startTime, endTime
end

-- 检查是否需要刷新
function checkDirty(human)
	if not human.db.richangLibao then
		return 
	end

	for libaoType, libaoData in pairs(human.db.richangLibao) do
		local startTime, endTime = getLibaoTime(libaoType)
		if (startTime and libaoData.ts < startTime) or 
			(endTime and libaoData.ts > endTime) then			
			human.db.richangLibao[libaoType] = nil
		end
	end
end

-- 获取已购买次数
function getBuyCnt(human, libaoType, id)
	if not human.db.richangLibao then
		return 0
	end
	local libaoData = human.db.richangLibao[libaoType]
	if not libaoData then
		return 0
	end
	return libaoData.list[id] or 0
end

-- 增加已购买次数
function addBuyCnt(human, libaoType, id, nBuyNum)
	nBuyNum = nBuyNum or 1
	if not human.db.richangLibao then
		human.db.richangLibao = {}
	end
	local libaoData = human.db.richangLibao[libaoType]
	if not libaoData then
		libaoData = {}
		libaoData.ts = os.time()
		libaoData.list = {}
		human.db.richangLibao[libaoType] = libaoData
	end
	libaoData.list[id] = (libaoData.list[id] or 0) + nBuyNum
end

-- 封装礼包结构体
function fontLibaoNet(net, id, config, libaoType, human)
	net.id = id 
	net.items[0] = #config.items
	for i = 1, net.items[0] do
		local itemID = config.items[i][1]
		local itemCnt = config.items[i][2]
		Grid.makeItem(net.items[i], itemID, itemCnt)
	end
	net.name = config.name 
	net.buyItem[0] = 0
	if config.buyID > 0 then
		net.buyItem[0] = 1
		BuyLogic.fontBuyItem(human, net.buyItem[1], config.buyID)
	end
	net.cnt = getBuyCnt(human, libaoType, id)
	net.maxCnt = config.cnt
end

-- 界面查询
function sendQuery(human, libaoType)
	local startTime, endTime = getLibaoTime(libaoType)
	if not startTime then -- 没设置开服时间不开
		return Broadcast.sendErr(human, Lang.JJC_NOT_SET_OPEN_TIME)
	end 
	local configs = getConfigs(libaoType)
	if not configs then return end

	checkDirty(human)	
	local msgRet = Msg.gc.GC_RICHANG_LIBAO_QUERY
	msgRet.libaoType = libaoType
	msgRet.leftTime = endTime - os.time()
	msgRet.list[0] = #configs
	for i = 1, msgRet.list[0] do
		local config = configs[i]
		fontLibaoNet(msgRet.list[i], i, config, libaoType, human)
	end
	--Msg.trace(msgRet)
	Msg.send(msgRet, human.fd)
end

-- 购买礼包
function buyLibao(human, libaoType, id, buyType, nBuyNum)
	local startTime, endTime = getLibaoTime(libaoType)
	if not startTime then -- 没设置开服时间不开
		return Broadcast.sendErr(human, Lang.JJC_NOT_SET_OPEN_TIME)
	end 
	local configs = getConfigs(libaoType)
	local config = configs and configs[id]
	if not config then return end

	if buyType == FREE_BUY and config.buyID > 0 then
		return -- rmb礼包不能免费领取
	end

	checkDirty(human)
	local nCnt = getBuyCnt(human, libaoType, id)
	if getBuyCnt(human, libaoType, id) >= config.cnt then
		return Broadcast.sendErr(human, Lang.YUNYING_BUY_ERR_CNT)
	end

	if nCnt + nBuyNum > config.cnt then
		return Broadcast.sendErr(human, Lang.YUNYING_BUY_ERR_CNT)
	end

	local logType = getLogType(libaoType)
	addBuyCnt(human, libaoType, id, nBuyNum)
	local tItemList = {}
	for _, v in ipairs(config.items) do
		table.insert(tItemList, {v[1], v[2]*nBuyNum})
	end
	BagLogic.addItemList(human, tItemList, logType)
	sendQuery(human, libaoType)
	
	-- 更新界面
	local targetPanelID = nil
	if libaoType == LIBAOTYPE_WEEK then
		targetPanelID = PanelDefine.PANEL_ID_3104
	else
		targetPanelID = PanelDefine.PANEL_ID_3207
	end
	
	-- 通过panelID找到对应的funcID和YYInfo
	-- funcID和YYInfo是在YunYingLogic.initYYInfo中动态添加到模块的
	-- 直接使用当前模块的 funcID 和 YYInfo，不需要重新 require
	local moduleFuncID = funcID or {}
	local moduleYYInfo = YYInfo or {}
	for k, v in pairs(moduleFuncID) do
		local funcConfig = YunYingLogic.getFuncConfig(k)
		if funcConfig and funcConfig.panelID == targetPanelID then
			YunYingLogic.updateIcon(moduleYYInfo[k], human)
			YunYingLogic.sendGroupUpdate(moduleYYInfo[k], human, targetPanelID)
			break
		end
	end
end

-- 红点
function isRed(human, YYInfo, funcConfig)
	local libaoType = nil
	if funcConfig.panelID == PanelDefine.PANEL_ID_3104 then
		libaoType = LIBAOTYPE_WEEK 
	elseif funcConfig.panelID == PanelDefine.PANEL_ID_3207 then 
		libaoType = LIBAOTYPE_MONTH
	end 
	if not libaoType then return end
	local configs = getConfigs(libaoType)
	if not configs then return end

	for id, config in pairs(configs) do
		if config.buyID < 1 and 
			getBuyCnt(human, libaoType, id) < config.cnt then
			return true
		end
	end
end

-- 是否开启
function isOpen(human, YYInfo, funcConfig)
	local libaoType = nil
	if funcConfig.panelID == PanelDefine.PANEL_ID_3104 then
		libaoType = LIBAOTYPE_WEEK 
	elseif funcConfig.panelID == PanelDefine.PANEL_ID_3207 then 
		libaoType = LIBAOTYPE_MONTH
	end 
	if not libaoType then
		print("[RichangLibaoLogic.isOpen] libaoType is nil for panelID="..funcConfig.panelID)
		return
	end
	
	local startTime, endTime = getLibaoTime(libaoType)
	if not startTime then
		print("[RichangLibaoLogic.isOpen] getLibaoTime returned nil for libaoType="..libaoType..", panelID="..funcConfig.panelID)
		return
	end

	-- 没有充值过, 不显示
	if not BuyLogic.isChange(human) then
		return false
	end

	local openDay = CommonDB.getServerOpenDay()
    if libaoType == LIBAOTYPE_WEEK and openDay < COND_OPEN_SRV_DAYS then
        return false
    end

	return true, endTime, startTime
end

function ShowAct(human)
	local YunYingExcel = require("excel.yunying")
	local config = YunYingExcel.func[WEEK_GITFT_ACTID]
	YunYingLogic.sendGroupUpdate(YYInfo[WEEK_GITFT_ACTID], human, config.panelID)

	config = YunYingExcel.func[MONTH_GITFT_ACTID]
	YunYingLogic.sendGroupUpdate(YYInfo[MONTH_GITFT_ACTID], human, config.panelID)
end



function updateDaily(human, funcID)
	checkDirty(human)
end

local function GetConfIDAndType(tConf, nBuyID, nType)
	for nID, v in ipairs(tConf) do
		if v.buyID == nBuyID then
			return true, nID, nType, v.cnt
		end
	end

	return false, 0, 0, 0
end

function GetRemainNum(human, nBuyID)
	-- 这里只有礼包ID,只能遍历
	local bHave, nID, nType, nLimitCnt = GetConfIDAndType(PresentExcel.weekLibao, nBuyID, LIBAOTYPE_WEEK)
	if false == bHave then
		bHave, nID, nType, nLimitCnt = GetConfIDAndType(PresentExcel.monthLibao, nBuyID, LIBAOTYPE_MONTH)
	end

	if false == bHave then
		return 0
	end

	local nBuyNum = getBuyCnt(human, nType, nID)
	return (nLimitCnt > nBuyNum) and (nLimitCnt - nBuyNum) or 0
end
