local ADDON_NAME, ns = ...

-- =============================================================
--  MT/OT TANK SYSTEM (EXTRACTED MODULE)
--  - Caches other tanks in group/raid
--  - Provides ns:GetTankModeState(unit) -> r,g,b,shouldFlash
-- =============================================================

ns.TankUnits = ns.TankUnits or {}

-- NOTE: role assignment can be unreliable in some group contexts.
-- For reporting, we allow a spec-role fallback for the player.
local function PlayerIsTankRole_ForReport()
    if (IsInGroup() or IsInRaid()) and UnitGroupRolesAssigned("player") == "TANK" then
        return true
    end

    if GetSpecialization and GetSpecializationRole then
        local spec = GetSpecialization()
        if spec then
            return GetSpecializationRole(spec) == "TANK"
        end
    end

    return false
end

local function ReportTanks()
    -- Chat report (lightly throttled):
    -- We only print when the detected tank set changes, otherwise
    -- GROUP_ROSTER_UPDATE / ROLE events would spam.

    local inGroup = IsInGroup() or IsInRaid()

    -- Count tanks INCLUDING player (for the message)
    local playerIsTank = PlayerIsTankRole_ForReport()

    local tankCount = #ns.TankUnits + (playerIsTank and 1 or 0)

    -- Build a stable signature so we can detect changes.
    -- (unit tokens change, so use names where possible)
    local names = {}
    if playerIsTank then
        local pn = UnitName("player")
        if pn then names[#names+1] = pn .. " (you)" end
    end
    for _, u in ipairs(ns.TankUnits) do
        local n = UnitName(u)
        if n then names[#names+1] = n end
    end
    table.sort(names)
    local sig = (inGroup and "G" or "S") .. ":" .. tostring(tankCount) .. ":" .. table.concat(names, ",")

    if ns._lastTankReportSig == sig then
        return
    end
    ns._lastTankReportSig = sig

    if not inGroup then
        -- Only say something when we transition to solo or on login.
        print("|cFF00FF00Plate-o-Matic:|r Tank cache: solo (0 other tanks).")
        return
    end

    if tankCount == 0 then
        print("|cFF00FF00Plate-o-Matic:|r Tank cache: 0 tanks detected (roles not set?).")
    else
        print(string.format("|cFF00FF00Plate-o-Matic:|r Tank cache: %d tank(s): %s", tankCount, table.concat(names, ", ")))
    end
end

function ns:UpdateTankCache()
    table.wipe(ns.TankUnits)

    -- Solo: keep cache empty, but still report state.
    if not IsInGroup() and not IsInRaid() then
        ReportTanks()
        return
    end

    local prefix = IsInRaid() and "raid" or "party"
    local count = GetNumGroupMembers()

    -- party members are 1..4, raid is 1..N
    local limit = IsInRaid() and count or (count - 1)

    for i = 1, limit do
        local unit = prefix .. i
        if UnitExists(unit) and not UnitIsUnit(unit, "player") then
            if UnitGroupRolesAssigned(unit) == "TANK" then
                table.insert(ns.TankUnits, unit)
            end
        end
    end

    ReportTanks()
end

-- =============================================================
--  Role helpers
-- =============================================================
local function PlayerIsTankRole()
    -- In group/raid this is the most reliable and cheap.
    if IsInGroup() then
        -- If roles aren't assigned yet, this can be "NONE" briefly.
        -- We'll fall back to spec-role below.
        if UnitGroupRolesAssigned("player") == "TANK" then
            return true
        end
    end

    -- Fallback: specialization role (solo / edge cases)
    if GetSpecialization and GetSpecializationRole then
        local spec = GetSpecialization()
        if spec then
            return GetSpecializationRole(spec) == "TANK"
        end
    end

    return false
end

-- =============================================================
--  Main decision function:
--  Returns tank-safe color if I have aggro,
--  off-tank color if another tank has it,
--  danger color if no tank has it.
-- =============================================================
function ns:GetTankModeState(unit)
    if not PlateOMaticDB or not PlateOMaticDB.tankModeEnabled then
        return nil, nil, nil, false
    end

    if not PlayerIsTankRole() then
        return nil, nil, nil, false
    end

    -- Only meaningful in combat (prevents annoying out-of-combat states)
    if not UnitAffectingCombat("player") then
        return nil, nil, nil, false
    end

    local colors = PlateOMaticDB.colors or {}

    local cSafe = colors.threatTankSafe or { r = 0.2, g = 0.8, b = 0.2 }
    local cOT   = colors.threatOffTank  or { r = 0.6, g = 0.2, b = 1.0 }
    local cBad  = colors.threatHigh     or { r = 1.0, g = 0.0, b = 0.0 }

    local status = UnitThreatSituation("player", unit) or 0
    status = tonumber(status) or 0

    -- I have aggro
    if status >= 3 then
        return cSafe.r, cSafe.g, cSafe.b, false
    end

    -- Optional OT check toggle (from DB)
    if PlateOMaticDB.checkOffTank then
        for _, tankUnit in ipairs(ns.TankUnits) do
            local otStatus = UnitThreatSituation(tankUnit, unit)
            otStatus = tonumber(otStatus) or 0

            -- Accept 2 or 3 as “OT has it”
            if otStatus >= 2 then
                return cOT.r, cOT.g, cOT.b, false
            end
        end
    end

    -- No tank has it
    return cBad.r, cBad.g, cBad.b, true
end

-- NOTE:
-- We intentionally do NOT register events here anymore.
-- pom.lua already updates tank cache on relevant events, and keeping both
-- causes duplicate work and inconsistent ordering in refresh cycles.
