--邮件管理
local LuaMongo = _G.lua_mongo
local Log = require("common.Log")
local DB = require("common.DB")
local Util = require("common.Util")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic") 
local RoleSystemDefine = require("roleSystem.RoleSystemDefine") 
local RoleDBLogic = require("role.RoleDBLogic")
local MailExcel = require("excel.mail")
local CommonDB = require("common.CommonDB")

SYSTEM = 1 				-- 系统邮件
GONGGAO = 2 				-- 公告

MAIL_MAX_CNT = 100			-- 邮件最大值

local FIELD_ID = {_id = nil}
local FIELD_RECEIVER = {uuid = nil,type = nil}

--后面如果fbAccount有值应该把区服id一起
function add(type,receiverUuid,title,content,items,senderName,sender,time,fbTime,fbContent,fbAccount,expireTime) 
	if _G.is_middle == true or type == GONGGAO then
		return
	end
	
	local mail = {}
	mail.type = type
	mail.receiverUuid = receiverUuid
	mail.title = title
	mail.content = content
	mail.read = nil
	mail.senderName = title
    mail.head = 0
    mail.fbTime = fbTime
    mail.fbContent = fbContent
    
	--后面用到
    local fields = {head = 1,lv = 1}
    if fbAccount ~= nil then
        local db = RoleDBLogic.getDbByAccount(fbAccount,fields)
        mail.fbHead = db.head
        mail.fbLv = db.lv
	end
	
	if sender and sender.db and sender.db.identity then
		mail.identity = sender.db.identity
	end

	if sender and sender.db and sender.db.head then
		mail.head = sender.db.head
	end

    if time == nil then 
		mail.time = os.time()
    else
		mail.time = time
    end
	
    if expireTime then
        mail.expireTime = expireTime
    end	
	
	if items then
		mail.items = {}
		for _,item in ipairs(items) do 
			mail.items[#mail.items + 1] = {item[1],item[2]}
		end
	end
    if items == nil then
        mail.get = 1
        mail.flag = nil
    else
        mail.get = nil
        mail.flag = 1
    end
	LuaMongo.insert(DB.db_mail, mail)
	-- 检测红点会调用getMails(), 短时间插入多封邮件加上玩家邮件数量过多，会发生段错误
	-- RoleSystemLogic.onDotByUuid(receiverUuid, RoleSystemDefine.ROLE_SYS_ID_204)
	return mail

end

-- condition = {startLv = 1, endLv = 100, lastLoginTime = xxx}
local MailLvQuery = {lv = {["$gte"] = 0, ["$lte"] = 0}}
local MailLvField = {lastLoginTime = 1, lastLogoutTime = 1}
function sendMailByCondition(condition, title, content, gridList,fbTime,fbContent,fbAccount,expireTime)
	local startLv = condition.startLv and tonumber(condition.startLv)
	local endLv = condition.endLv and tonumber(condition.endLv)		
	local lastLoginTime = condition.lastLoginTime and tonumber(condition.lastLoginTime) or 0
	if startLv == nil or endLv == nil or lastLoginTime == nil then
		return 
	end
    
    local successCount = 0
    local failCount = 0

    --Log.write(Log.LOGID_ERR_PCALL, "mail sendMailByCondition" , "")
	-- 在线的只要等级符合直接发
	for uuid, oHuman in pairs(ObjHuman.onlineUuid) do
		if oHuman.db.lv >= startLv and 
			oHuman.db.lv <= endLv then
			p_ret, err = pcall(add, SYSTEM, oHuman.db._id, title, content, gridList, condition.senderName, nil, nil,fbTime,fbContent,fbAccount,expireTime)
			if p_ret then
				successCount = successCount + 1
                --Log.write(Log.LOGID_ERR_PCALL, "mail rolename=" .. oHuman.db.name, err)
			else 
				failCount = failCount + 1
				--Log.write(Log.LOGID_ERR_PCALL, "mail rolename=" .. oHuman.db.name, err)
			end					
		end 
	end

	-- 不在线的，还需要验证x天内登录
	MailLvQuery.lv["$gte"] = startLv
	MailLvQuery.lv["$lte"] = endLv
	LuaMongo.find(DB.db_char, MailLvQuery, MailLvField)
    while true do
        local data = {}
        if not LuaMongo.next(data) then
        	break
        end
        if not ObjHuman.onlineUuid[data._id] and 
        	(lastLoginTime == 0 or 
        		(data.lastLoginTime and data.lastLoginTime >= lastLoginTime) or
        		(data.lastLogoutTime and data.lastLogoutTime >= lastLoginTime)
        	) then
			p_ret, err = pcall(add, SYSTEM, data._id, title, content, gridList, condition.senderName, nil, nil,fbTime,fbContent,fbAccount)
			if p_ret then	
				successCount = successCount + 1
			else 
				failCount = failCount + 1
				Log.write(Log.LOGID_ERR_PCALL, "mail role uuid=" .. data._id, err)
			end	
        end
    end
    return successCount, failCount
end

function del(mailUuid)
	FIELD_ID._id = mailUuid
	LuaMongo.remove(DB.db_mail, FIELD_ID)
end

function getMail(mailUuid)
	FIELD_ID._id = mailUuid
	LuaMongo.find(DB.db_mail,FIELD_ID)
	local mail = {}
	if not LuaMongo.next(mail) then
		return nil
	end
	return mail
end

local function cmpMail(a, b)
	return a.time > b.time
end

local mails = {}
-- function getMails(receiverUuid,mailType)
-- 	for key in ipairs(mails) do 
-- 		mails[key] = nil
-- 	end

-- 	FIELD_RECEIVER.receiverUuid = receiverUuid
-- 	FIELD_RECEIVER.type = mailType

--     LuaMongo.find(DB.db_mail,{["$query"]=FIELD_RECEIVER})
    
-- 	local lastTime = os.time() - 7 * 86400
--     local mailCnt = 0
-- 	while true do
-- 		local mail = {}
-- 		-- if not LuaMongo.next(mail) then
-- 		-- 	break
-- 		-- end

-- 		local res, err = pcall(function ()
-- 			return LuaMongo.next(mail)
-- 		end)

-- 		if not res then
-- 			Log.write(Log.LOGID_DEBUG, "MailManager.getMails err = ".. err)
-- 			break
-- 		end

-- 		if not err then
-- 			break
-- 		end

--        if mail.expireTime then  -- 有指定过期时间
--             if mail.time > os.time() - mail.expireTime then
-- 			    mailCnt = mailCnt + 1
-- 			    mails[mailCnt] = mail
--             end
--        elseif mail.time > lastTime then -- 没有就用默认过期时间
--             mailCnt = mailCnt + 1
-- 			mails[mailCnt] = mail
--        end
-- 	end
    
--     if mailCnt > MAIL_MAX_CNT then
-- 		table.sort(mails, cmpMail)
-- 		for i = MAIL_MAX_CNT + 1, mailCnt do
-- 			mails[i] = nil
-- 		end
-- 	end    
-- 	return mails
-- end

-- 替换原有的 getMails 函数
function getMails(receiverUuid, mailType)
    -- 1. 清空缓存表
    for i = 1, #mails do mails[i] = nil end

    local now = os.time()
    local mailCnt = 0
    local tempMails = {}
    local SCAN_LIMIT = 2000  -- 单次分段查询安全上限
    local foundEnough = false

    -- 2.将时间划分为多个小窗口，避免单次 find 触发底层 OOM
    -- 窗口设计：最近7天 -> 7~14天 -> 14~30天 -> 30~60天
    local timeWindows = {
        {now - 7*86400,   now},
        {now - 14*86400,  now - 7*86400},
        {now - 30*86400,  now - 14*86400},
        {now - 60*86400,  now - 30*86400}
    }
	-- 60天 -> 开服
	local serverOpenTime = CommonDB.getServerOpenTime()
	timeWindows[#timeWindows+1] = { serverOpenTime, now - 60*86400 }

    for _, window in ipairs(timeWindows) do
        if foundEnough then break end

        -- 使用最简平铺查询，彻底避开 C 扩展解析缺陷
        local query = {
            receiverUuid = receiverUuid,
            type = mailType,
            time = { ["$gte"] = window[1], ["$lte"] = window[2] }
        }

        LuaMongo.find(DB.db_mail, query)

        local mail = {}
        local scanCnt = 0
        while true do
            local has_next = LuaMongo.next(mail)
            if not has_next then break end
            
            scanCnt = scanCnt + 1
            if scanCnt > SCAN_LIMIT then 
                Log.write(Log.LOGID_DEBUG, string.format("Mail segment limit hit! uuid=%s window=%d~%d", 
                    receiverUuid, window[1], window[2]))
                break 
            end

            -- 浅拷贝隔离 C 驱动内部 Buffer
            local m = {}
            for k, v in pairs(mail) do m[k] = v end
            tempMails[#tempMails + 1] = m

            -- 清空复用表
            for k in pairs(mail) do mail[k] = nil end
        end

        -- 如果已收集足够多数据（留足过滤冗余），提前终止后续窗口查询
        if #tempMails >= 500 then 
            foundEnough = true 
            break 
        end
    end

    -- 3.按时间倒序排序，确保后续取到的是“最新”的
    table.sort(tempMails, cmpMail)

    -- 4. 过滤过期邮件，精准截取最新 100 条
    for _, m in ipairs(tempMails) do
        if type(m.time) ~= "number" then m.time = 0 end

        local isExpired = false
        local expireTime = m.expireTime
        if expireTime and type(expireTime) == "number" then
            if m.time <= now - expireTime then isExpired = true end
        elseif m.time <= now - 7 * 86400 then
            isExpired = true
        end

        if not isExpired then
            mailCnt = mailCnt + 1
            mails[mailCnt] = m
            if mailCnt >= MAIL_MAX_CNT then break end -- 达到 100 条立即退出
        end
    end

    return mails
end




function saveMail(mail)
    FIELD_ID._id = mail._id
    LuaMongo.update(DB.db_mail, FIELD_ID, mail)
end

function delAll(uuid,mailType)
    local QueryMailByUuid = {get = {["$exists"] = 0},  read = {["$exists"] = 1}}
    QueryMailByUuid.receiverUuid = uuid
    QueryMailByUuid.type = mailType
    QueryMailByUuid.get["$exists"] = 1
	LuaMongo.remove(DB.db_mail, QueryMailByUuid)
end