-- 百战成神 常量定义
--
-- 玩法概要:
--   跨服 5v5 积分 PvP, 5 种族独立阵容(COMBAT_TYPE39~43), 5 局 3 胜制。
--   开服>=45 天可参与; 周六 0:10 ~ 周日 23:00 可挑战; 每轮开放后隔 3 个开放周，第 5 周再开新轮。
--   一次点击挑战仅扣 1 次(每日 5 次免费, 不足扣道具 115 x5)。
--   攻胜+100/攻负-50, 守胜+50/守负-50; 初始积分 3000。
--
-- 架构: 普通服 NS + 跨服 CS + Mongo DB(db_bzcs)
--   首次挑战完成 REGISTER; 阵容变更 UPDATE_SHOW; 积分/匹配/排行在跨服

--------------------------------------------------------------------------------
-- 活动时间 (Util.getWeekDay: 1=周日, 2=周一, 3=周二 ... 7=周六)
--------------------------------------------------------------------------------
BZCS_OPEN_WDAY_AREA   = {7, 1}    -- 可挑战星期: 周六~周日 (getWeekDay: 7=周六, 1=周日)
BZCS_START_SEC        = 600       -- 每日开始时刻: 0:10 (距 0 点秒数)
BZCS_END_SEC          = 82800     -- 每日结束时刻: 23:00
BZCS_SKIP_OPEN_WEEKS  = 3         -- 本轮开放后跳过的开放周数(第2~4周不开新轮)
BZCS_CYCLE_DAYS       = (1 + BZCS_SKIP_OPEN_WEEKS) * 7  -- 距上次开轮最少天数(28), 第5个开放周可开
BZCS_OPEN_DAYS        = 2         -- 单轮活动持续天数(周六+周日, 用于 IsRunning 校验)

-- 开放结束日相对开始日的天数偏移(周六->周日为 1)
function GetOpenEndDayOffset()
    local s = BZCS_OPEN_WDAY_AREA[1]
    local e = BZCS_OPEN_WDAY_AREA[2]
    if s <= e then
        return e - s
    end
    return e + 7 - s
end

--------------------------------------------------------------------------------
-- 积分规则
--------------------------------------------------------------------------------
BZCS_INIT_SCORE       = 3000      -- 每轮初始/重置积分
BZCS_ATK_WIN_SCORE    = 100       -- 进攻方整场获胜加分
BZCS_ATK_LOSE_SCORE   = -50       -- 进攻方整场失败扣分
BZCS_DEF_WIN_SCORE    = 50        -- 防守方整场获胜加分(对手进攻失败)
BZCS_DEF_LOSE_SCORE   = -50       -- 防守方整场失败扣分(对手进攻成功)

-- excel.baiZhanChengShen.fightReward 配置 id
BZCS_FIGHT_REWARD_WIN_ID  = 1     -- 挑战整场胜利奖励
BZCS_FIGHT_REWARD_LOSE_ID = 2     -- 挑战整场失败奖励

--------------------------------------------------------------------------------
-- 种族与战斗类型 (teamType 41~45, 见 excel/ssecy/combat.lua)
-- race 1~5 与 camp 一致: 妖/人/兽/仙/魔
--------------------------------------------------------------------------------
BZCS_RACE_ORDER       = {1, 2, 3, 4, 5}
BZCS_RACE_COMBAT_TYPE = {39, 40, 41, 42, 43}
BZCS_RACE_NAME        = {"妖", "人", "兽", "仙", "魔"}
BZCS_RACE_CNT         = 5
BZCS_WIN_TARGET       = 3         -- 5 局 3 胜: 先赢 3 族或打满 5 族

--------------------------------------------------------------------------------
-- 挑战次数与门票
--------------------------------------------------------------------------------
BZCS_FREE_TIMES       = 5         -- 每日免费挑战次数(0 点重置)
BZCS_TICKET_ITEM_ID   = 115       -- 挑战券道具 id
BZCS_TICKET_COST      = 5         -- 无免费时每次消耗数量

--------------------------------------------------------------------------------
-- 匹配与排行
--------------------------------------------------------------------------------
BZCS_OPPONENT_CNT     = 3         -- 单次匹配对手数量
BZCS_MATCH_CACHE_TTL  = 30        -- 匹配列表内存缓存有效期(秒); 过期按 rank 轻量刷新展示
BZCS_MATCH_STEP       = 500       -- 积分匹配步进(第1步±500, 第2步±1000, 第3步±1500...)
BZCS_MATCH_MAX_STEP   = 50        -- 最大扩大步数(最多 ±25000 分范围)

BZCS_RANK_MAX         = 100       -- 客户端展示排行榜条数(全服积分榜含机器人, 规模更大)
-- 全服排行: 积分高者优先; 同分则 scoreTime 小者优先(先达到该积分)
BZCS_REWARD_RANK_MAX  = 9999      -- 周期发奖最大排名(超出不发)

--------------------------------------------------------------------------------
-- 准入与其它
--------------------------------------------------------------------------------
BZCS_OPEN_SVR_DAY     = 45        -- 开服天数>=此值本服才可参与
BZCS_WARREPORT_MAX    = 20        -- 玩家本地战报条数(新记录在前, 超出删最老)

-- 战报类型 warType(客户端展示用)
BZCS_WAR_TYPE_ATK_WIN  = 1        -- 主动挑战获胜
BZCS_WAR_TYPE_ATK_LOSE = 2        -- 主动挑战失败
BZCS_WAR_TYPE_DEF_WIN  = 3        -- 被挑战, 己方获胜
BZCS_WAR_TYPE_DEF_LOSE = 4        -- 被挑战, 己方失败

BZCS_AWARD_MAIL_ID    = 7038      -- 周期结算邮件 id(需在 excel/mail 配置)

-- 机器人池数量 = 策划 robotList 条数(见 GetRobotListCount)
BZCS_SVR_BASE_NUM     = 810537    -- 逻辑服 serverId 基准(Config.SVR_INDEX 等)
BZCS_ROBOT_DISPLAY_SERVER_ID = 1  -- 协议下发: 机器人展示为第1服

-- 逻辑服 serverId -> GC 协议展示服号(仅 NS 下发客户端时调用); isRobot=1 固定为第1服
function ToClientServerId(serverId, isRobot)
    if isRobot == 1 then
        return BZCS_ROBOT_DISPLAY_SERVER_ID
    end
    if not serverId or serverId <= 0 then
        return 0
    end
    if serverId > BZCS_SVR_BASE_NUM then
        return serverId - BZCS_SVR_BASE_NUM
    end
    return serverId
end

--------------------------------------------------------------------------------
-- 跨服 WL_BZCS_TIPS 错误码 (普通服收到后提示)
--------------------------------------------------------------------------------
BZCS_ERR_NOT_OPEN       = 1       -- 活动未开启
BZCS_ERR_NOT_ELIGIBLE   = 2       -- 不满足参与条件
BZCS_ERR_NO_TIMES       = 3       -- 挑战次数不足
BZCS_ERR_TARGET_INVALID = 4       -- 对手不存在
BZCS_ERR_DATA           = 5       -- 数据异常
BZCS_ERR_IN_BATTLE      = 6       -- 战斗中(重复挑战)

--------------------------------------------------------------------------------
-- LW_BZCS_UPDATE_SHOW 增量类型(showInfo 仅带变更字段, 跨服 MergeShowInfo 合并)
--------------------------------------------------------------------------------
BZCS_UPDATE_SHOW_NAME       = 1   -- name
BZCS_UPDATE_SHOW_HEAD       = 3   -- head
BZCS_UPDATE_SHOW_HEAD_FRAME = 4   -- headFrame
BZCS_UPDATE_SHOW_LINEUP     = 5   -- heroArr[race], 须配合 race 参数
BZCS_UPDATE_SHOW_BODY       = 6   -- body(形象, HEAD_TYPE_3)

-- 将增量 showInfo 合并进跨服已有展示数据
function MergeShowInfo(si, patch)
    if not si or not patch then return end
    if patch.name ~= nil then
        si.name = patch.name
    end
    if patch.head ~= nil then
        si.head = patch.head
    end
    if patch.headFrame ~= nil then
        si.headFrame = patch.headFrame
    end
    if patch.body ~= nil then
        si.body = patch.body
    end
    if patch.heroArr then
        si.heroArr = si.heroArr or {}
        for race, raceShow in pairs(patch.heroArr) do
            si.heroArr[race] = raceShow
        end
    end
end

--------------------------------------------------------------------------------
-- robotList 配置(策划表 excel/ssecy/baiZhanChengShen.lua)
--   score: 机器人积分
--   monsterOutIDs[1..5]: 妖/人/兽/仙/魔 五族 monsterOutID, 每 ID 一支队伍(见 CombatLogic.getMonsterObjList)
--------------------------------------------------------------------------------

local BzcsConfig = require("excel.baiZhanChengShen")
local CombatLogic = require("combat.CombatLogic")

local robotListCount

function GetRobotListCount()
    if robotListCount then
        return robotListCount
    end
    local max = 0
    for k in pairs(BzcsConfig.robotList or {}) do
        if type(k) == "number" and k > max then
            max = k
        end
    end
    robotListCount = max
    return max
end

-- bzcs_robot_N 与 robotList[N] 一一对应
function GetRobotListIndex(uuid)
    if not uuid then return end
    local n = string.match(uuid, "^bzcs_robot_(%d+)$")
    if not n then return end
    local idx = tonumber(n)
    if not idx or idx < 1 or idx > GetRobotListCount() then return end
    return idx
end

function GetRobotListCfg(uuid)
    local idx = GetRobotListIndex(uuid)
    if not idx then return end
    return BzcsConfig.robotList[idx], idx
end

-- 由 monsterOutID 计算单族队伍战力(与战斗 getMonsterObjList 一致)
function CalcMonsterOutPower(monsterOutID)
    if not monsterOutID then return 0 end
    local _, _, rolebase = CombatLogic.getMonsterObjList(monsterOutID)
    return rolebase and rolebase.zhandouli or 0
end

--------------------------------------------------------------------------------
-- 战力与机器人阵容展开(机器人仅存 monsterOutID+racePower, 展示字段用时生成)
--------------------------------------------------------------------------------

local MonsterExcel

local function getMonsterExcel()
    MonsterExcel = MonsterExcel or require("excel.monster")
    return MonsterExcel
end

-- 机器人单族仅存 monsterOutID+racePower, 有 monsterOutID 则需展开
local function needExpandRaceShow(raceShow)
    return raceShow and raceShow.monsterOutID ~= nil
end

-- 由 monsterOut 展开英雄展示; racePower 均分到各英雄 heroPower(不修改入参)
function ExpandBzcsRaceShow(raceShow)
    if not raceShow or not needExpandRaceShow(raceShow) then
        return raceShow
    end
    local excel = getMonsterExcel()
    local mout = excel.monsterOut[raceShow.monsterOutID]
    local racePower = raceShow.racePower or 0
    local heroArr = {}
    local cnt = 0
    if mout and mout.member then
        for idx, member in ipairs(mout.member) do
            if idx > 6 then break end
            cnt = cnt + 1
        end
    end
    local per = cnt > 0 and math.floor(racePower / cnt) or racePower
    local len = 0
    if mout and mout.member then
        for idx, member in ipairs(mout.member) do
            if idx > 6 then break end
            local mid = member[1]
            local mcf = excel.monster[mid]
            if mcf then
                len = len + 1
                heroArr[len] = {
                    heroBody = mcf.body,
                    heroStar = mcf.star or 0,
                    heroLevel = member[2],
                    heroCamp = mcf.camp or 0,
                    heroIcon = mcf.head or 0,
                    heroId = mid,
                    heroQuality = mcf.heroQuality or 1,
                    heroPower = per,
                }
            end
        end
    end
    if len == 0 then
        heroArr[1] = {
            heroPower = racePower,
            heroId = 0,
            heroBody = 0,
            heroStar = 0,
            heroLevel = 0,
            heroCamp = 0,
            heroIcon = 0,
            heroQuality = 1,
        }
    end
    return {
        heroArr = heroArr,
        formation = raceShow.formation or 1,
        helpSkillId = raceShow.helpSkillId or 0,
        elfList = raceShow.elfList,
        elfSkillIds = raceShow.elfSkillIds,
        monsterOutID = raceShow.monsterOutID,
        racePower = racePower,
    }
end

-- 单族队伍战力: 机器人用 racePower; 真人用 heroArr 内 heroPower 之和
function CalcRaceTeamPower(raceShow)
    if not raceShow then return 0 end
    if raceShow.racePower then
        return raceShow.racePower
    end
    local sum = 0
    for _, h in ipairs(raceShow.heroArr or {}) do
        sum = sum + (h.heroPower or 0)
    end
    return sum
end

-- 玩家总战力 = 五族队伍战力之和
function CalcPlayerPower(showInfo)
    if not showInfo then return 0 end
    local total = 0
    for _, race in ipairs(BZCS_RACE_ORDER) do
        total = total + CalcRaceTeamPower(showInfo.heroArr and showInfo.heroArr[race])
    end
    return total
end
