Json = Json or require("common.Json")
local Config = require("Config")
local CommonDefine = require("common.CommonDefine")
local Log = require("common.Log")
local CommonDB = require("common.CommonDB")
local LogDefine = require("common.LogDefine")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local CreateRole = require("role.CreateRole")
local PlatformDefine = require("platform.Define")
local PfLogic = require("platform.PfLogic")
local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local RoleDBLogic = require("role.RoleDBLogic")
local Util = require("common.Util")
local AuthCheck = require("scene.AuthCheck")
local ApiLogic = require("platform.ApiLogic")
local CDKLoigc = require("present.CDK")
local MailManager = require("mail.MailManager")
local QQBigShot = require("platform.QQBigShot")
local BanLogic = require("scene.BanLogic")


local function HumanLogin_Handle(human, params)
	-- 单次上报时长设置为登录时间
	human.db.onlineTimeDayReport = os.time()
	-- print("[HumanLogin_Handle] 进入了判断")
	--table.print_lua_table(params)
	if params.dwkLevel then
		print("[HumanLogin_Handle] 获取到的等级 dwkLevel = "..params.dwkLevel)
		QQBigShot.QQBigShot_HumanLoginHandle(human, params.dwkLevel)
	end
end

-- 是否禁止登录
local function isBan(uuid, channelId, account, appId)
	return BanLogic.CheckBan(uuid, channelId, account, appId)
end

-- 判断是否属于白名单IP
local function isWhiteIp(ip)
	if not ip then
		return false
	end

	if not Config.WHITEIP_LIST or #Config.WHITEIP_LIST == 0 then
		return true
	end

	if table.find(Config.WHITEIP_LIST, ip) then
		return true
	end

	return false
end


--在线玩家列表不再从 ObjHuman.onlineAccount 获取, 改为从 ObjHuman.onlineNewUniqueTag 获取
function CG_TEST_PROTO(fd,msg)
	-- print("============ CG_TEST_PROTO============", msg.param)
	Log.write(Log.LOGID_DEBUG, "[CG_TEST_PROTO]=" .. tostring(msg.param))
	local param = Json.Decode(msg.param)
	local uTag
	if param.type == "UseCDKV2" or param.type == "UseCDK" or param.type == "UseFixCDK" then
		uTag = RoleDBLogic.Generateuuid(param.channel_id, msg.account, msg.serverTag)
	end

	-- Util.printTable(param)

	if param.type == "UseCDKV2" then
		-- local human = ObjHuman.onlineAccount[msg.account]
		local human = ObjHuman.onlineNewUniqueTag[uTag]
		if  not human then
			-- 玩家不在线 做一个离线处理
			return
		end
		CDKLoigc.cdkDoV2(human,{
			itemList = param.itemList,
		})
	elseif param.type == "UseCDK" then
		-- local human = ObjHuman.onlineAccount[msg.account]
		local human = ObjHuman.onlineNewUniqueTag[uTag]
		if  not human then
			-- 玩家不在线 做一个离线处理
			return
		end
	    local batch = Json.Decode(param.batchInfo)
		CDKLoigc.cdkDo(human,{
			itemList = Json.Decode(batch.itenList),
			serverList = Json.Decode(batch.serverList),
			batch = tonumber(batch.batch),
			useCnt = tonumber(batch.cnt),
			err = param.err,
		})
	elseif param.type == "UseFixCDK" then
		-- local human = ObjHuman.onlineAccount[msg.account]
		local human = ObjHuman.onlineNewUniqueTag[uTag]
		if  not human then
			-- 玩家不在线 做一个离线处理
			return
		end
		CDKLoigc.cdkFixDo(human,param.code) -- 
	elseif param.type == "sendMail" then 
		local mail = Json.Decode(param.mail)
		MailManager.add(MailManager.SYSTEM,mail.uuid,mail.title,mail.content,mail.items,nil,nil,nil,nil,nil,nil,mail.expire)
	elseif param.type == "kickAllUser" then
		-- for _,h in pairs(ObjHuman.onlineAccount) do 
		-- 	ObjHuman.doDisconnect(h, CommonDefine.DISCONNECT_KICK_ALL)
		-- 	sendDisconnect(h.fd,CommonDefine.DISCONNECT_KICK_ALL)
		-- end

		for _,h in pairs(ObjHuman.onlineNewUniqueTag) do 
			ObjHuman.doDisconnect(h, CommonDefine.DISCONNECT_KICK_ALL)
			sendDisconnect(h.fd,CommonDefine.DISCONNECT_KICK_ALL)
		end
	elseif param.type == "setBan" then
		local banInfo = {
			roleBanInfo = param.roleBanInfo,
			accountBanInfo = param.accountBanInfo,
			appBanInfo = param.appBanInfo
		}
		BanLogic.Update_Ban_Info(banInfo)
	elseif param.type == "deliverGoods" then
		local uTag = RoleDBLogic.Generateuuid(param.channel_id, msg.account, msg.serverTag)
		local human = ObjHuman.onlineNewUniqueTag[uTag]
		if not human then
			Log.write(Log.LOGID_DEBUG, "[deliverGoods] 玩家不在线 account=" .. tostring(msg.account) .. " orderId=" .. tostring(param.orderId))
			return
		end
		local items = {}
		if param.goods and #param.goods > 0 then
			for _, good in ipairs(param.goods) do
				table.insert(items, {good.Id, good.Num})
			end
		end
		Log.write(Log.LOGID_DEBUG, "[deliverGoods] 开始发货 account=" .. tostring(msg.account) .. " orderId=" .. tostring(param.orderId) .. " itemCnt=" .. #items)
		youxiSdkReward(human, items)
	end
end

function CG_AA_DISCONNECT(human)
	if type(human) ~= "table" then return end
	ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_NORMAL)
end

function setLoginParams(human, msg, params)
	human.lang = msg.lang
	human.region = (msg.region == "") and "CN" or string.upper(msg.region) 
	human.ip = (msg.ip ~= "") and msg.ip or _G.global.get_ip_from_fd(human.fd)

	-- 有些字段重复赋值，看看以后要不要干掉。。。
	human.pf = params.pf
	human.isIOS = params.isIOS or 0
	human.vopenid = params.openid or ""
	human.openkey = params.openkey or ""
	human.phpChanelID = params.phpChanelID or ""
	human.appid = params.appid
    human.gameName = params.gameName or ""
    human.version = params.version or nil
	human.serverTag = msg.serverTag
	human.deviceNo  = params.deviceNo or ""  --设备号

	human.pf_info = human.pf_info or {}
	human.pf_info.openid = params.openid or ""
	human.pf_info.openkey = params.openkey or ""
	human.pf_info.pf = params.pf or ""
	human.pf_info.pfkey = params.pfkey or ""
	human.pf_info.zoneid = params.zoneid or 0
	human.pf_info.serverid = params.serverid or 0
	human.pf_info.tcTime = os.time()	
	human.pf_info.lvYellow = params.lvYellow or 0
	human.pf_info.yearYellow = params.yearYellow or 0
	human.pf_info.superYellow = params.superYellow or 0
	human.pf_info.lvBlue = params.lvBlue or 0
	human.pf_info.yearBlue = params.yearBlue or 0
	human.pf_info.superBlue = params.superBlue or 0
	human.pf_info.validTimeBlue = params.validTimeBlue or 0
	human.pf_info.vipSevenk = params.vipSevenk or 0
	human.pf_info.validTimeSevenk = params.validTimeSevenk or 0
	human.pf_info.phpChanelID = params.phpChanelID or ""
	human.pf_info.phoneSystem = params.phoneSystem or "android"
	human.pf_info.from_openid = params.from_openid or ""
end

function sendDisconnect(fd, errCode)
	local mm = Msg.gc.GC_DISCONNECT
	mm.code = errCode
	mm.msg = CommonDefine.DISCONNECT_MSG[errCode]
	Msg.send(mm, fd)
end

function CG_ASK_LOGIN(fd, msg)
	 -- 测试支付回调 有时间换个地方
	 if msg.account == "H1EqhbpA80jt0Jw6Q3T2" then
		Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 开始处理, account=" .. msg.account .. ", serverTag=" .. msg.serverTag)
		
		-- 解析支付参数
		local payParams = Json.Decode(msg.params)
		if not payParams then
			Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 解析参数失败, params=" .. tostring(msg.params))
			return
		end
		Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 解析参数成功, params=" .. Json.Encode(payParams))		
		-- 构建发货请求参数
		oJsonInput = {
			type=1,
			id=payParams.id,--商品id
			cnt=payParams.cnt, --数量
			money=payParams.money, -- 金额
			account=payParams.account, --账号
			serverTag = msg.serverTag, --区服标识
			order=payParams.order,--订单号
			region="cn",
			channelID = payParams.channel_id
		}
		Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 构建发货请求, oJsonInput=" .. Json.Encode(oJsonInput))
		
		-- 调用发货接口
		Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 开始调用发货接口, order=" .. tostring(payParams.order))
        local buyRet  = ApiLogic.deliver(oJsonInput,{})
        if buyRet then
			Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 发货接口返回成功, result=" .. Json.Encode(buyRet))
		else
			Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 发货接口返回失败或无返回值")
		end
		Log.write(Log.LOGID_OSS_DELIVER, "[测试支付回调] 处理完成")
        return
	end

	if _G.is_middle == true then return end

	--判断是否是数字类型
	if type(fd) ~= "number" then
		assert()
	end

	if msg.account == "" then
		return sendDisconnect(fd, CommonDefine.DISCONNECT_AUTH_FAIL)
	end

	if Config.IS_CHECK_IP == true and not isWhiteIp(msg.ip) then
		return
	end


	--如果在线人数大于最大可容纳在线人数时，断开链接
	local onlineCnt = ObjHuman.getOnlineCnt()
	if onlineCnt >= CommonDefine.MAX_ONLINE_COUNT then		
		return sendDisconnect(fd, CommonDefine.DISCONNECT_MAX_ONLINE)
	end

	--目前暂未校验，返回的都是true，后续如果需要校验，再看看是否需要把区服标识传入
    local retAuth = AuthCheck.authCheck(msg.account, msg.authkey, msg.timestamp, msg.ip)
	if retAuth ~= true then
		return sendDisconnect(fd, CommonDefine.DISCONNECT_AUTH_FAIL)
	end

	local account = msg.account
	local serverTag = msg.serverTag
	local params = Json.Decode(msg.params)

	print("CG_ASK_LOGIN", msg.account, msg.serverTag, params.phpChanelID, type(params.phpChanelID), params.deviceNo, type(params.deviceNo))

	--如果是已经登录的，也断开连接
	--local human_old = ObjHuman.onlineAccount[account]

	local uTag = RoleDBLogic.Generateuuid(params.phpChanelID, account, serverTag)
	local human_old = ObjHuman.onlineNewUniqueTag[uTag]
	if human_old then
		ObjHuman.doDisconnect(human_old, CommonDefine.DISCONNECT_DUPLICATE)
	end		

	--创建新角色
	-- local human = ObjHuman.create(fd, account, human_old and human_old.db, nil)
	local human = ObjHuman.create(fd, account, human_old and human_old.db, uTag)
	setLoginParams(human, msg, params) -- 设置登录参数


	-- 禁止登录检测
	if isBan(human.db and human.db._id, params.phpChanelID, account, params.deviceNo) then
		return sendDisconnect(fd, CommonDefine.DISCONNECT_AUTH_FAIL)
	end


	if human.db == nil then
		-- 新号
        -- local ip,time = CommonDB.getBanIp(msg.ip)
        -- if (time and time > os.time()) then
        --     ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_BANIP)
		-- 	return
        -- else
        --     CommonDB.delBanIp(msg.ip)
        -- end
		
		Log.write(Log.LOGID_OSS_CREATELOSS,account, "", LogDefine.HUMAN_LOST.ENTRANCE, human.ip, human.pf, human.appid, human.phpChanelID)
		CreateRole.createNewRole(human)
		HumanLogin_Handle(human, params)
	else
		-- 封号
		-- if human.db.banUserTime == -1 or 
		-- 	(human.db.banUserTime and human.db.banUserTime > os.time()) then
		-- 	ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_BANUSER)
		-- 	return
		-- end

        -- local ip,time = CommonDB.getBanIp(msg.ip)
        -- if (time and time > os.time()) then
		-- 	ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_BANIP)
		-- 	return
        -- else
        --     CommonDB.delBanIp(msg.ip)
        -- end
		ObjHuman.onLogin(human, nil)
		HumanLogin_Handle(human, params)
	end

	-- 存储美团相关参数（如果存在）
	if human.db then
		-- mtSubscribe 改为由专门协议处理，这里不再从登录参数写入
		if params.mtFrom2floor ~= nil then
			local from2floor = tonumber(params.mtFrom2floor) or 0
			-- 只在“当天第一次从2楼进入”时，将 mtFrom2floor 置为 1
			-- 如果当天已经被服务器逻辑（领取奖励或11点邮件）置为 0，则本日内前端不能再次覆盖为 1
			if from2floor == 1 then
				local now = os.time()
				local todayStart = Util.getDayStartTime(now)
				human.db.mtFrom2floorDay = human.db.mtFrom2floorDay or 0
				if not Util.isSameDay(human.db.mtFrom2floorDay) then
					human.db.mtFrom2floor = 1
					human.db.mtFrom2floorDay = todayStart
				end
			end
		end
	end
end

function CG_HEART_BEAT(human, msg)
	local msgRet = Msg.gc.GC_HEART_BEAT
	msgRet.timeStamp = os.time()
	Msg.send(msgRet, human.fd)
end


-- 记录fps
local FPS_TB = {["guaji"]=1, ["zhandou"]=1, ["zhucheng"]=1, ["buzhen"]=1}
function CG_PHONE_FPS(human, msg)
    if FPS_TB[msg.fpsType] == nil then return end

    human.db.fpsTb = human.db.fpsTb or {}
    human.db.fpsTb[msg.fpsType] = { lv = human.db.lv, startFps = msg.startFps, endFps = msg.endFps}
end


function CG_HEART_BEAT_M(human)

end

function CG_ASK_DISCONNECT(human)
    ObjHuman.doDisconnect(human, CommonDefine.DISCONNECT_NORMAL)
end

function CG_CLIENT_ERROR(human, msg)
	Log.write(Log.LOGID_OSS_CLIENT_ERR, human.db and human.db._id or "", human.db and human.db.account or human.account, human.db and human.db.name or "", msg.err)
end

function CG_CLIENT_LOAD_ERROR(human, msg)
	Log.write(Log.LOGID_OSS_CLIENT_LOAD_ERR, human.db and human.db._id or "", human.db and human.db.account or human.account, human.db and human.db.name or "", msg.err)
end


IOS_FLAG_CHARGECLOSE = 0 	-- 提示关闭
IOS_FLAG_CHARGEOPENTIP = 1 	-- 提示开放
IOS_FLAG_CHARGEOPEN = 2 	-- 充值开放

function getIosChargeOpenFlag(human)
	if PfLogic.isFkwTishen() == true then
		if human.isIOS == 1 then
			return IOS_FLAG_CHARGECLOSE
		end
	end
	
	if PfLogic.isKunTangTishen() == true then
		return IOS_FLAG_CHARGECLOSE
	end
	
	return IOS_FLAG_CHARGEOPEN 
end

function canCharge(human)
	if getIosChargeOpenFlag(human) == IOS_FLAG_CHARGECLOSE then
		return
	end
	return true
end
