local DB = require("common.DB")
local LuaMongo = _G.lua_mongo
local Config = require("Config")
local Util = require("common.Util")
local ObjHuman = require("core.ObjHuman")
local YunYingLogic = require("yunying.YunYingLogic")
local OpenAct = require("present.OpenAct")

local DBUpdate = {_id=nil}								-- 更新	
local DBUpdateField = {}								-- 更新域
local nVoucherInflateLen = 20							-- 代金券记录信息长度

KEY_SERVER_START_TIME = "serverStartTime"				-- 开服时间
KEY_IDENTITY_MAX = "identityMax"						-- 自增的最大的数字 从1开始
KEY_UNION_IDENTITY_MAX = "unionIdentityMax"				-- 自增的最大的数字 从1开始
KEY_REWARD_INDEX = "rewardIndex"						-- 好友排行榜奖励索引rewardIndex
-- KEY_BAN_IP = "banIp"									-- 被禁IP
KEY_CHONGJI_ACT = "chongJiAct"							-- 全服冲级活动 领取情况
KEY_ACT_MONTH = "actMonth"								-- 当前计算的真实月份
KEY_UNION_WAR = "unionWar"								-- 公会战
KEY_ACT_MONTH_LIST = "actMonthList"						-- 现实活动
KEY_RESET_TIME = "resetTime"
KEY_DRILL = "drill"										-- 过关斩将信息（本期开始时间等）
KEY_SHARE_PLATFORM_BOARD = "sharePlatformBoard"			-- 分享排行
KEY_BILLBOARD_AIM = "billboardAim"						-- 排行榜达标记录
KEY_JJC_LADDER = "jjcLadder"							-- 天梯争霸信息
KEY_VALLEY = "valley"									-- 荣耀峡谷信息
KEY_LIANYU = "lianyu" 									-- 绝望深渊信息
KEY_MIDDLE_INFO = "middleInfo"							-- 跨服链接信息
KEY_CHAMPION_END_TIME = "championEndTime"				-- 冠军竞技场本赛季结束时间
KEY_DRAGON_NEST_CITIAO = "dragonNestCiTiao"             -- 冰龙巢穴词条
KEY_WORK_MAN = "workMan"                                -- 打工人活动
KEY_OPEN_SERVER_TOPUP_TOP = "openServerTopupTop"		-- 开服充值排名活动
KEY_CIYUAN_MOZHU = "ciyuanMoZhu"                        -- 次元魔蛛
KEY_YJ_TIME = "yjTreasureTime"                          -- 遗迹探险时间
KEY_CDK_BATCH = "cdkBatchIdx"                           -- CDK批次序号
KEY_WEEKLOOP_CARD_BATCH = "weekLoopCardBatch"			-- 周活动-抽卡批次
KEY_VOUCHER_INFLATE = "tVoucherInflateInfo"				-- 代金券膨胀信息
kEY_RECOMMENDLINEUP = "recommendlineup"					-- 推荐阵容
KEY_FIREWORKBONUS_TIME="fireWorksBonusTime"             -- 烟花加成时间
KEY_COMMERCEACT_INFO = "commerceActInfo"				-- 跨服活动信息
KEY_JJCLADDER_INFO = "jjcNewladderInfo"					-- 天梯赛信息
KEY_COMMERCEACT_MIDDLE_INFO = "commerceMiddleActInfo"	-- 中心服跨服商业活动信息
KEY_BAN_DATA = "banData"								-- 封禁数据
KEY_DESKTOP_DATA = "desktopData"					-- 桌面添加数据（账号级）
KEY_REBATE_DATA = "rebateData"							-- 渠道返利数据
KEY_ANOTHERWORLDBATTLE_START_TI = "anotherWorldBattleStart" -- 最近一轮异界之战开启时间
KEY_BZCS_START_TIME = "bzcsStartTime" -- 百战成神活动开启时间

db = db or {
	serverStartTime = nil,								-- 开服时间
	zhuanpanRecord = nil,								-- 转盘中奖记录
	identityMax = nil,									-- 自增的最大的数字 从1开始
    rewardIndex = nil,                                  -- 好友排行榜奖励索引rewardIndex
    unionIdentityMax = nil,                             -- 自增的最大的数字 从1开始
    mergeSvrIndex = nil,								-- 合服之后对应的服务器索引 比如如果10001,10003,100004合服了 这里的数据结构是{10001,10003,10004}
    -- banIp = {},                                         -- 被禁IP
	chongJiAct  = {},                                   -- 全服冲级活动 领取情况
	actMonth = nil,                                     -- 当前计算的真实月份
	unionWarState = nil,                                -- 当前工会战状态
	actMonthList = nil,                                 -- 现实活动
	resetTime = nil,                                    -- 确认是否重置数据
	middleInfo = {},									-- 跨服链接信息
	championEndTime = nil,							    -- 冠军竞技场本赛季结束时间
	dragonNestCiTiao = {},                              -- 冰龙巢穴词条
	workMan = {},                                       -- 打工人活动
	ciyuanMoZhu = nil,                                  -- 次元魔蛛 
    yjTreasureTime = nil,                               -- 遗迹探险时间
	cdkBatchIdx = nil,									-- CDK批次序号
	weekLoopCardBatch = nil,							-- 周活动-抽卡批次
	tVoucherInflateInfo = {},							-- 代金券膨胀信息
	recommendlineup = {},								-- 推荐阵容
	fireWorksBonusTime = nil,                           -- 烟花加成时间
	commerceActInfo = {},								-- 跨服商业活动信息
	jjcNewladderInfo = {},								-- 天梯赛信息
	commerceMiddleActInfo = {},							-- 中心服跨服商业活动信息
}


--普通服缓存的封禁数据
local banList = {}

local isInit = false

function init()
	if isInit then
		return
	end

	LuaMongo.find(DB.db_common)
	if not LuaMongo.next(db) then
		LuaMongo.insert(DB.db_common, db)
	end

	isInit = true
end

-- 修改db单个字段
function updateValue(key, value)
	if not key then return end	
	if not db then return end
	if value then
		DBUpdateField["$set"] = {[key]=value}
		DBUpdateField["$unset"] = nil
	else
		DBUpdateField["$set"] = nil
		DBUpdateField["$unset"] = {[key]=1}
	end
	DBUpdate._id = db._id
	db[key] = value
	LuaMongo.update(DB.db_common, DBUpdate, DBUpdateField)
end

function getCDKBatch()
	if not db  then 
		return
	end
	return db[KEY_CDK_BATCH] or 0
end

function setCDKBatch(idx)
	idx = idx + 1
	updateValue(KEY_CDK_BATCH,idx)
end

function getValueByKey(key)
	if not db then return end
	return db[key]
end

-- 同步db内容
function reset()
	LuaMongo.find(DB.db_common)
	
	if not LuaMongo.next(db) then
		db = {banIp = {},}
	end
	print("db.serverStartTime:",db.serverStartTime)
end

-- 设置开服时间
function setServerOpenTime(time)
	db.serverStartTime = time
	updateValue(KEY_SERVER_START_TIME, time)
	
    YunYingLogic.onServerOpenTime()
	OpenAct.onServerOpenTime()
end

function getServerOpenTime()
	if not db.serverStartTime and not isInit then
		init()
	end

	if not db.serverStartTime then
		local t = Util.getDayStartTime()
		setServerOpenTime(t)
	end
	return  db.serverStartTime
end

-- 获得当前是开服第几天（如果是开服第一天返回1）
function getServerOpenDay()
	local openTime = getServerOpenTime()
	if openTime == 0 then
		return
	end
	
	local startTime = Util.getDayStartTime(openTime)
	
	local now = os.time()
	return math.ceil((now - startTime + 1) / 24 / 3600)
end

function getIdentityMax()
	if db.identityMax == nil then
		db.identityMax = math.random(10001, 20000)	
		setIdentityMax(db.identityMax)
	elseif db.identityMax < 10001 then
		db.identityMax = math.random(10001, 20000) -- 兼容老规则下数据
		setIdentityMax(db.identityMax)
	end
	
	return db.identityMax
end

-- 虚拟ID，假的
function getFakeIdentityMax()
	return math.random(1, 9999)
end

function setIdentityMax(idMax)
	updateValue(KEY_IDENTITY_MAX, idMax)
end

function getUnionIdentityMax()
	if db.unionIdentityMax == nil then
		db.unionIdentityMax = math.random(10001, 20000)	
		setUnionIdentityMax(db.unionIdentityMax)
	elseif db.unionIdentityMax < 10001 then
		db.unionIdentityMax = math.random(10001, 20000) -- 兼容老规则下数据
		setUnionIdentityMax(db.unionIdentityMax)
	end
	
	return db.unionIdentityMax
end

function setUnionIdentityMax(idMax)
	updateValue(KEY_UNION_IDENTITY_MAX, idMax)
end

function getRewardIndex()
	return db.rewardIndex or 0
end

function setRewardIndex(rewardIndex)
	updateValue(KEY_REWARD_INDEX, rewardIndex)
end

function getMergeSvrIndex()
	return db.mergeSvrIndex
end

-- cnt = 1
-- function setBanIp(ip,time)
--     db.banIp[cnt] =db.banIp[cnt] or {}
--     db.banIp[cnt].ip = ip
--     db.banIp[cnt].time = time
--     cnt = cnt + 1
	
-- 	updateValue(KEY_BAN_IP, db.banIp)
-- end

-- function getBanIp(ip)
--     for k,v in pairs(db.banIp) do
--         if v.ip == ip then
--             return v.ip,v.time
--         end
--     end
--     return 
-- end

-- function delBanIp(ip)
--     for k,v in pairs(db.banIp) do
--         if v.ip == ip then
--             db.banIp[k] = nil
--         end
--     end

--     updateValue(KEY_BAN_IP, db.banIp)
-- end

--跨服才用的函数
function UpdateBanData(newBanData)
	--db.banData = newBanData
	updateValue(KEY_BAN_DATA, newBanData)
end

-- 普通服用的函数
function GetBanCache()
	return banList
end

-- 普通服用的函数
function UpdateBanCache(banTag, banTime)
	if banTime == 0 then
        banList[banTag] = nil
    else
        banList[banTag] = banTime
    end
end

-- 全服创号 冲级活动
function getSvrChongJiGet(id)
	local num = 0 
	if not db.chongJiAct then
		return num
	end

	if db.chongJiAct[id] then
		num = db.chongJiAct[id] or 0
	end

	return num
end

function addSvrChongJiGet(id)
	db.chongJiAct = db.chongJiAct or {}
    db.chongJiAct[id] = db.chongJiAct[id] or 0
    db.chongJiAct[id] = db.chongJiAct[id] + 1

	updateValue(KEY_CHONGJI_ACT, db.chongJiAct)	
end

function getActMonth()
    return db.actMonth or 0
end

function setActMonth(month)
	updateValue(KEY_ACT_MONTH, month)	
end

function getActMonthList(id)
	local act = nil 
	if not db.actMonthList then
		return act
	end

	if db.actMonthList[id] then
		act = db.actMonthList[id] or 0
	end

	return act
end

function setActMonthList(id, endTime, month)
	db.actMonthList = db.actMonthList or {}
    db.actMonthList[id] = db.actMonthList[id] or {}
    db.actMonthList[id].endTime = endTime
	db.actMonthList[id].month = month
	updateValue(KEY_ACT_MONTH_LIST, db.actMonthList)
end

function getResetTime()
	return db.resetTime or 0
end

function setResetTime(time)
	updateValue(KEY_RESET_TIME, time)
end

function getMiddleInfo()
	return db.middleInfo
end

function setMiddleInfo(ip, port, host)
	db.middleInfo.ip = ip
	db.middleInfo.port = port
	db.middleInfo.host = host
	updateValue(KEY_MIDDLE_INFO, db.middleInfo)
end

function getChampionEndTime()
	return db.championEndTime or 0
end

function setChampionEndTime(time)
	updateValue(KEY_CHAMPION_END_TIME, time)
end

function getDragonNestCitiao()
	return db.dragonNestCiTiao
end

function setDragonNestCitiao(list, time)
	db.dragonNestCiTiao.citiao = Util.copyTable(list)
	db.dragonNestCiTiao.time = time
	updateValue(KEY_DRAGON_NEST_CITIAO, db.dragonNestCiTiao)
end

function setWorkManState(state)
    db.workMan.state = state
    updateValue(KEY_WORK_MAN, db.workMan)
end

function setWorkManGroup(group)
    db.workMan.group = group
    updateValue(KEY_WORK_MAN, db.workMan)
end

function setWorkManTs(ts)
    db.workMan.time = ts
    updateValue(KEY_WORK_MAN, db.workMan)
end

function getWorkMan()
	return db.workMan
end

-- 获取合服时间
function getMergeServerTime()
	return db.mergeServerTime or 0
end


-- 获得当前是合服第几天（如果是合服第一天返回1）
function getServerMergeDay()
	local mergeTime = getMergeServerTime()
	if mergeTime == 0 then
		return
	end
	
	local startTime = Util.getDayStartTime(mergeTime)
	
	local now = os.time()
	return math.ceil((now - startTime + 1) / 24 / 3600)
end

function setMergeTime(ts)
    db.mergeServerTime = ts
    updateValue("mergeServerTime", db.mergeServerTime)
end

function getYjTreasureEndTime()
	return db.yjTreasureTime or 0
end

function setYjTreasureEndTime(time)
	updateValue(KEY_YJ_TIME, time)
end

function getWeekCardBatch()
	return db.weekLoopCardBatch or 0
end

function setWeekCardBatch(nValue)
	updateValue(KEY_WEEKLOOP_CARD_BATCH, nValue)
end

function getVoucherInflate()
	return db.tVoucherInflateInfo
end

function setVoucherInflate(szText, nTime)
	if not szText or 0 >= nTime then
		return
	end
	
	local nNowLen =  #db.tVoucherInflateInfo
	if nNowLen >= nVoucherInflateLen then
		local nDelLen = nNowLen - nVoucherInflateLen + 1
		for i = nDelLen, 1, -1 do
			table.remove(db.tVoucherInflateInfo, i)
		end
	end

	table.insert(db.tVoucherInflateInfo, {szText = szText, nTime = nTime})

	updateValue(KEY_VOUCHER_INFLATE, db.tVoucherInflateInfo)
end

-- 获取阵容数据
function getRecommendLineUp()
	return db.recommendlineup
end

-- 修改阵容数据
function SetRecommendLineUp(tData)
	db.recommendlineup = tData

	updateValue(kEY_RECOMMENDLINEUP, db.recommendlineup)
end

-- 获取烟花加成时间
function getFireWorksBonusTime()
	return db.fireWorksBonusTime or 0
end

-- 设置烟花加成时间
function setFireWorkBonusTime(nValue)
	updateValue(KEY_FIREWORKBONUS_TIME,nValue)
end

function GetInFireWork()
    -- 获取当前时间
    local nNowTime = os.time()
    local currentDuration = getFireWorksBonusTime()
    -- 检查是否在加成内
    if nNowTime <= currentDuration then
        return true
    end
    
    return false
end

-- 获取跨服商业活动信息
function GetCommerceActInfo()
	return db.commerceActInfo
end

-- 设置跨服商业活动信息
--[[
	db.commerceActInfo ={
		nBeginTime = nNowTime,		-- 开始时间
        nEndTime = nEndTime,		-- 结束时间
        nPoint = 0,					-- 全服点数
        nSendRankMail = false,		-- 是否发送全服邮件
		nBatchID = 1		-- 批次ID
	}
]]
function SetCommerceActInfo(tData)
	db.commerceActInfo = tData
	
	updateValue(KEY_COMMERCEACT_INFO, db.commerceActInfo)
end

function GetCommerceActInfo_Point()
	return db.commerceActInfo.nPoint or 0
end

function SetCommerceActInfo_Point(nValue)
	db.commerceActInfo.nPoint = nValue
	updateValue(KEY_COMMERCEACT_INFO, db.commerceActInfo)
end

-- 是否发送邮件
function GetCommerceActInfo_SendServerMail()
	return db.commerceActInfo.nSendRankMail
end

function SetCommerceActInfo_SendServerMail(tData)
	db.commerceActInfo = tData

	updateValue(KEY_COMMERCEACT_INFO, db.commerceActInfo)
end

-- 天梯赛结束时间
function GetJjcLadderEndTime()
	return db.jjcNewladderInfo.nEndTime or 0
end

-- 设置天梯赛结束时间
function SetJjcLadderEndTime(nEndTime)
	db.jjcNewladderInfo.nEndTime = nEndTime

	updateValue(KEY_JJCLADDER_INFO, db.jjcNewladderInfo)
end

-- 设置天梯赛前三数据
function SetJjcLadderLast3RankInfo(tData)
	db.jjcNewladderInfo.tLast3Rank = tData

	updateValue(KEY_JJCLADDER_INFO, db.jjcNewladderInfo)
end

-- 获取天梯赛前三数据
function GetJjcLadderLast3RankInfo()
	return db.jjcNewladderInfo.tLast3Rank
end

-- 获取中心服跨服商业活动信息
--[[
	-- 战区所属服务器key
	[nKey] = 
	{
		nBatchID,		-- 批次
		nBeginTime,		-- 开始时间
		nEndTime,		-- 结束时间
	}
]]
function GetCommerceMiddleAct()
	return db.commerceMiddleActInfo
end

-- 设置中心服跨服商业活动信息
function SetCommerceMiddleAct(tData)
	db.commerceMiddleActInfo = tData

	updateValue(KEY_COMMERCEACT_MIDDLE_INFO, db.commerceMiddleActInfo)
end

-- 获取中心服跨服商业某个服的信息
function GetCommerceMiddleAct_ByKey(nKey)
	return db.commerceMiddleActInfo[nKey] or nil
end

-- 设置中心服跨服商业某个服的信息
function SetCommerceMiddleAct_ByKey(nKey, tData)
	db.commerceMiddleActInfo[nKey] = tData

	updateValue(KEY_COMMERCEACT_MIDDLE_INFO, db.commerceMiddleActInfo)
end

-- 桌面添加数据（账号级，多区服共享）
-- 结构：{ [newUniqueTag] = { ["channelId_platform"] = true, ... }, ... }

local function makeDesktopAccountKey(channelId, serverId, account)
	return tostring(channelId) .. "|" .. tostring(serverId) .. "|" .. tostring(account)
end

function GetDesktopData(channelId, serverId, account)
	local data = db[KEY_DESKTOP_DATA]
	if not data then return nil end
	local accountKey = makeDesktopAccountKey(channelId, serverId, account)
	return data[accountKey]
end

function SetDesktopData(channelId, serverId, account, platform)
	local accountKey = makeDesktopAccountKey(channelId, serverId, account)
	local platformKey = tostring(channelId) .. "_" .. tostring(platform)
	local data = db[KEY_DESKTOP_DATA] or {}
	data[accountKey] = data[accountKey] or {}
	data[accountKey][platformKey] = true
	db[KEY_DESKTOP_DATA] = data
	updateValue(KEY_DESKTOP_DATA, data)
end

function IsDesktopAdded(channelId, serverId, account, platform)
	local accountData = GetDesktopData(channelId, serverId, account)
	if not accountData then return false end
	local platformKey = tostring(channelId) .. "_" .. tostring(platform)
	return accountData[platformKey] == true
end