local ADDON_NAME, ns = ...

-- =============================================================
-- pom_threat.lua
-- All threat/combat coloring + flashing lives here ONLY.
--
-- Provides:
--   ns.threat:GetState(unit)
--     -> r,g,b, shouldFlash, threatPct, status, reason
--
-- This module is defensive and avoids "combat makes everything flash":
-- It will NOT apply threat colors/flash unless the UNIT is actually involved.
-- =============================================================

ns.threat = ns.threat or {}
local T = ns.threat

-- -------------------------------------------------------------
-- DB helper (READ-ONLY)
-- InitDB in pom.lua owns defaults + migrations.
-- -------------------------------------------------------------
local function GetDB()
    if not PlateOMaticDB then return nil end
    if type(PlateOMaticDB.threat) ~= "table" then return nil end
    return PlateOMaticDB.threat
end

-- -------------------------------------------------------------
-- Helpers
-- -------------------------------------------------------------
local function Clamp01(x)
    x = tonumber(x) or 0
    if x < 0 then return 0 end
    if x > 1 then return 1 end
    return x
end

local function GetRole()
    if GetSpecialization and GetSpecializationRole then
        local spec = GetSpecialization()
        if spec then
            return GetSpecializationRole(spec) or "NONE"
        end
    end
    return "NONE"
end

local function ThreatNumbers(playerUnit, unit)
    -- Returns: status (0..3), threatPct (0..100)
    local _, status, threatPct = UnitDetailedThreatSituation(playerUnit, unit)
    if status == nil then
        status = UnitThreatSituation(playerUnit, unit)
    end
    status = tonumber(status) or 0
    threatPct = tonumber(threatPct) or 0
    return status, threatPct
end

local function PickColor(tbl, a, b, fallback)
    -- returns tbl[a] or tbl[b] or fallback
    if type(tbl) ~= "table" then return fallback end
    local c = tbl[a]
    if type(c) == "table" then return c end
    c = tbl[b]
    if type(c) == "table" then return c end
    return fallback
end

local function GetThreatColors(db)
    -- Colors belong to PlateOMaticDB.threat.colors
    local c = (db and db.colors) or {}

    -- Support both NEW keys (pom.lua) and OLD keys (legacy):
    -- NEW: high / medium / low / safe / ot / group
    -- OLD: high / med / low / tankSafe / offTank / groupTint
    local high = PickColor(c, "high", "threatHigh", { r=1.0, g=0.0, b=0.0 })
    local med  = PickColor(c, "medium", "med",       { r=1.0, g=1.0, b=0.0 })
    local low  = PickColor(c, "low", "threatLow",    { r=0.5, g=0.5, b=0.5 })

    local tankOk = PickColor(c, "safe", "tankSafe",  { r=0.2, g=0.8, b=0.2 })
    local offT   = PickColor(c, "ot", "offTank",     { r=0.6, g=0.2, b=1.0 })

    local group  = PickColor(c, "group", "groupTint", { r=0.2, g=0.7, b=1.0, a=1.0 })

    return high, med, low, tankOk, offT, group
end

-- -------------------------------------------------------------
-- Core rule:
-- ONLY apply threat colors if the UNIT is actually relevant.
-- -------------------------------------------------------------
local function UnitIsThreatRelevant(unit, status)
    if UnitAffectingCombat(unit) then
        return true, "unitCombat"
    end
    if (tonumber(status) or 0) > 0 then
        return true, "hasThreat"
    end
    return false, "notRelevant"
end

-- =============================================================
-- Public: GetState(unit)
-- Returns threat override color + flashing decision (or nil if none)
-- =============================================================
function T:GetState(unit)
    local db = GetDB()
    if not db then
        return nil, nil, nil, false, 0, 0, "noDBThreat"
    end

    if db.enabled == false then
        return nil, nil, nil, false, 0, 0, "disabled"
    end

    -- If player isn't in combat, threat visuals are usually noise.
    if not UnitAffectingCombat("player") then
        return nil, nil, nil, false, 0, 0, "playerOOC"
    end

    local role = GetRole()
    local status, threatPct = ThreatNumbers("player", unit)

    -- Defensive gate
    local relevant, why = UnitIsThreatRelevant(unit, status)
    if not relevant then
        return nil, nil, nil, false, threatPct, status, why
    end

    local high, med, low, tankSafe, offTank, groupTint = GetThreatColors(db)

    -- Optional: DPS/Heal group tint (only while in group)
    local r, g, b
    if db.groupTintEnabled and role ~= "TANK" and (IsInGroup() or IsInRaid()) then
        r, g, b = groupTint.r or 0.2, groupTint.g or 0.7, groupTint.b or 1.0
    end

    -- Tank mode override (MT/OT logic) lives in ns:GetTankModeState
    local tankOverride = false
    local tankFlash = false
    if db.tankModeEnabled and role == "TANK" and ns and ns.GetTankModeState then
        local tr, tg, tb, tf = ns:GetTankModeState(unit)
        if tr then
            r, g, b = tr, tg, tb
            tankOverride = true
            tankFlash = tf and true or false
        end
    end

    -- Threat coloring
    if db.colorBarByThreat then
        if role == "TANK" then
            if status > 0 and (not tankOverride) then
                if status >= 3 then
                    r, g, b = tankSafe.r, tankSafe.g, tankSafe.b
                elseif status >= 1 then
                    r, g, b = med.r, med.g, med.b
                end
            end
        else
            -- DPS/Heal gradient from medium->high starting at 60%
            if threatPct >= 60 then
                local t = Clamp01((threatPct - 60) / 40)
                r = (med.r or 1) + ((high.r or 1) - (med.r or 1)) * t
                g = (med.g or 1) + ((high.g or 0) - (med.g or 1)) * t
                b = (med.b or 0) + ((high.b or 0) - (med.b or 0)) * t
            end
        end
    end

    if not r then
        return nil, nil, nil, false, threatPct, status, "noOverride"
    end

    -- Flash decision
    local shouldFlash = false
    if db.flashAggro then
        if role == "TANK" and db.tankModeEnabled then
            shouldFlash = tankFlash
        else
            shouldFlash = (threatPct >= 60) or (status >= 3)
        end
    end

    return r, g, b, shouldFlash, threatPct, status, "ok"
end
