-- RL Pala Tank Helper
-- Shows paladin tank stats next to the character frame.

local addonName, addon = ...

-- Boss-level constants for TBC (level 73)
local BOSS_LEVEL = 73
local BASE_PLAYER_DEFENSE = 350
local CRIT_REDUCTION_REQUIRED = 5.6
local CRUSH_AVOIDANCE_REQUIRED = 102.4
local ARMOR_CONSTANT = 467.5 * BOSS_LEVEL - 22167.5 -- 11960 for level 73

-- SavedVariables
local db = RLPalaTankHelperDB or {}
RLPalaTankHelperDB = db

-- Default position (lower than before)
if not db.point then
    db.point = "TOPLEFT"
    db.relativeTo = "CharacterFrame"
    db.relativePoint = "TOPRIGHT"
    db.xOffset = -2
    db.yOffset = -50
end

-- Main frame
local frame = CreateFrame("Frame", "RLPalaTankHelperFrame", UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil)
frame:SetSize(200, 310)
frame:SetFrameStrata("HIGH")
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", function(self)
    self:StartMoving()
end)
frame:SetScript("OnDragStop", function(self)
    self:StopMovingOrSizing()
    local point, relativeTo, relativePoint, x, y = self:GetPoint()
    db.point = point
    db.relativeTo = relativeTo and relativeTo:GetName() or "UIParent"
    db.relativePoint = relativePoint
    db.xOffset = x
    db.yOffset = y
end)
frame:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 32, edgeSize = 16,
    insets = { left = 4, right = 4, top = 4, bottom = 4 }
})
frame:SetBackdropColor(0, 0, 0, 0.85)
frame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
frame:SetPoint(db.point, db.relativeTo, db.relativePoint, db.xOffset, db.yOffset)
frame:Hide()

-- Logo
local logo = frame:CreateTexture(nil, "ARTWORK")
logo:SetSize(32, 32)
logo:SetPoint("TOPLEFT", frame, "TOPLEFT", 12, -10)
logo:SetTexture("Interface\\AddOns\\RLPalaTankHelper\\img\\logo.png")
frame.logo = logo

-- Title
local title = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
title:SetPoint("LEFT", logo, "RIGHT", 8, 0)
title:SetText("|cffffd100Tank Stats|r")

-- Create text rows
local texts = {}
local rowHeight = 14
for i = 1, 15 do
    texts[i] = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    texts[i]:SetJustifyH("LEFT")
    texts[i]:SetPoint("TOPLEFT", 12, -48 - (i * rowHeight))
end

-- About Button
local aboutBtn = CreateFrame("Button", nil, frame)
aboutBtn:SetSize(80, 24)
aboutBtn:SetPoint("BOTTOM", frame, "BOTTOM", 0, 8)

local aboutBtnBg = aboutBtn:CreateTexture(nil, "BACKGROUND")
aboutBtnBg:SetAllPoints()
aboutBtnBg:SetColorTexture(0.3, 0.3, 0.35, 1)
aboutBtn.bg = aboutBtnBg

local aboutBtnText = aboutBtn:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
aboutBtnText:SetPoint("CENTER", aboutBtn, "CENTER", 0, 0)
aboutBtnText:SetText("About")
aboutBtn.text = aboutBtnText

aboutBtn:SetScript("OnEnter", function(self)
    self.bg:SetColorTexture(0.4, 0.4, 0.5, 1)
end)
aboutBtn:SetScript("OnLeave", function(self)
    self.bg:SetColorTexture(0.3, 0.3, 0.35, 1)
end)

-- About Panel
local aboutPanel = CreateFrame("Frame", "RLPalaTankHelperAboutPanel", UIParent, BackdropTemplateMixin and "BackdropTemplate" or nil)
aboutPanel:SetSize(350, 320)
aboutPanel:SetFrameStrata("DIALOG")
aboutPanel:SetMovable(true)
aboutPanel:EnableMouse(true)
aboutPanel:RegisterForDrag("LeftButton")
aboutPanel:SetScript("OnDragStart", function(self) self:StartMoving() end)
aboutPanel:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
aboutPanel:SetBackdrop({
    bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    tile = true, tileSize = 32, edgeSize = 16,
    insets = { left = 4, right = 4, top = 4, bottom = 4 }
})
aboutPanel:SetBackdropColor(0, 0, 0, 0.9)
aboutPanel:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
aboutPanel:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
aboutPanel:Hide()

-- About Panel Logo (centered, square aspect ratio like RLRaidDungeonReset)
local aboutLogo = aboutPanel:CreateTexture(nil, "ARTWORK")
aboutLogo:SetPoint("TOP", aboutPanel, "TOP", 0, -20)
aboutLogo:SetSize(180, 180)
aboutLogo:SetTexture("Interface\\AddOns\\RLPalaTankHelper\\img\\logo.png")

-- About Panel Text
local aboutText = aboutPanel:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
aboutText:SetPoint("TOP", aboutLogo, "BOTTOM", 0, -20)
aboutText:SetWidth(aboutPanel:GetWidth() - 32)
aboutText:SetJustifyH("CENTER")
aboutText:SetText("RL Pala Tank Helper\nVersion: 1.0\nAuthor: RL\n\nDisplays paladin tank stats next to the character frame.\n\nDesigned for The Burning Crusade / Classic Paladin tanks.")

-- Close Button for About Panel
local closeAboutBtn = CreateFrame("Button", nil, aboutPanel)
closeAboutBtn:SetSize(24, 24)
closeAboutBtn:SetPoint("TOPRIGHT", aboutPanel, "TOPRIGHT", -8, -8)

local closeAboutBg = closeAboutBtn:CreateTexture(nil, "BACKGROUND")
closeAboutBg:SetAllPoints()
closeAboutBg:SetColorTexture(0.3, 0.3, 0.35, 1)

local closeAboutText = closeAboutBtn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
closeAboutText:SetPoint("CENTER", closeAboutBtn, "CENTER", 0, 1)
closeAboutText:SetText("X")

closeAboutBtn:SetScript("OnEnter", function(self)
    self.bg:SetColorTexture(0.6, 0.2, 0.2, 1)
end)
closeAboutBtn:SetScript("OnLeave", function(self)
    self.bg:SetColorTexture(0.3, 0.3, 0.35, 1)
end)
closeAboutBtn:SetScript("OnClick", function()
    aboutPanel:Hide()
end)

aboutBtn:SetScript("OnClick", function()
    aboutPanel:Show()
end)

local function GetDefenseSkill()
    local base, modifier = UnitDefense("player")
    return base + modifier
end

-- Check if player is a Paladin with Protection spec
local function IsPaladinTank()
    local _, class = UnitClass("player")
    if class ~= "PALADIN" then
        return false
    end

    -- TBC/Classic: Check Protection talent points (tab 2 is Protection for Paladins)
    if GetNumTalentTabs then
        local numTabs = GetNumTalentTabs()
        if numTabs >= 3 then
            local _, _, pointsSpent = GetTalentTabInfo(2) -- Protection is tab 2
            return pointsSpent > 0
        end
    end

    -- Modern WoW: Check specialization
    if GetSpecialization then
        local spec = GetSpecialization()
        if spec then
            local _, _, _, _, role = GetSpecializationInfo(spec)
            return role == "TANK"
        end
    end

    return false
end

local function UpdateStats()
    local defense = GetDefenseSkill()
    local dodge = GetDodgeChance()
    local parry = GetParryChance()
    local block = GetBlockChance()

    -- Base miss 5% + defense contribution above boss base defense (350)
    local miss = 5 + (defense - BASE_PLAYER_DEFENSE) * 0.04
    local avoid = miss + dodge + parry
    local critRed = (defense - BASE_PLAYER_DEFENSE) * 0.04
    local crushAvoid = avoid + block

    local blockValue = (GetShieldBlock and GetShieldBlock()) or (GetBlockValue and GetBlockValue()) or 0
    local _, effectiveArmor = UnitArmor("player")
    local dr = effectiveArmor / (effectiveArmor + ARMOR_CONSTANT)
    local hp = UnitHealthMax("player")
    local ehp = math.floor(hp / (1 - dr))

    local sp = GetSpellBonusDamage(2) or 0
    local mh = (GetHitModifier and GetHitModifier()) or 0
    local sh = (GetSpellHitModifier and GetSpellHitModifier()) or 0

    texts[1]:SetText(string.format("|cff00ff00Miss:|r %.2f%%", miss))
    texts[2]:SetText(string.format("|cff00ff00Dodge:|r %.2f%%", dodge))
    texts[3]:SetText(string.format("|cff00ff00Parry:|r %.2f%%", parry))
    texts[4]:SetText(string.format("|cff00ff00Avoid:|r %.2f%%", avoid))
    texts[5]:SetText(string.format("|cff00ff00Block:|r %.2f%%", block))
    texts[6]:SetText(string.format("|cffff0000Crit:|r %.2f / %.1f%%", critRed, CRIT_REDUCTION_REQUIRED))
    texts[7]:SetText(string.format("|cffff0000Crush:|r %.2f / %.1f%%", crushAvoid, CRUSH_AVOIDANCE_REQUIRED))
    texts[8]:SetText(string.format("|cffffff00Defense:|r %d", defense))
    texts[9]:SetText(string.format("|cffffff00Block Value:|r %d", blockValue))
    texts[10]:SetText(string.format("|cffffff00Armor:|r %d", effectiveArmor))
    texts[11]:SetText(string.format("|cffffff00DR:|r %.2f%%", dr * 100))
    texts[12]:SetText(string.format("|cffffff00EHP/HP:|r %d/%d", ehp, hp))
    texts[13]:SetText(string.format("|cffffff00Spell Power:|r %d", sp))
    texts[14]:SetText(string.format("|cffffff00SH:|r %.2f%%", sh))
    texts[15]:SetText(string.format("|cffffff00MH:|r %.2f%%", mh))
end

local function UpdateVisibility()
    if CharacterFrame:IsShown() and PaperDollFrame and PaperDollFrame:IsShown() and IsPaladinTank() then
        frame:Show()
        UpdateStats()
    else
        frame:Hide()
    end
end

-- Show/hide alongside the character paper doll
CharacterFrame:HookScript("OnShow", UpdateVisibility)
CharacterFrame:HookScript("OnHide", function() frame:Hide(); aboutPanel:Hide() end)
hooksecurefunc("CharacterFrame_ShowSubFrame", function()
    UpdateVisibility()
end)

-- Register stat update events
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
frame:RegisterEvent("UNIT_STATS")
frame:RegisterEvent("UNIT_DEFENSE")
frame:RegisterEvent("UNIT_RESISTANCES")
frame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED")
frame:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
frame:RegisterEvent("UNIT_AURA")
frame:RegisterEvent("COMBAT_RATING_UPDATE")
frame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
frame:RegisterEvent("PLAYER_TALENT_UPDATE")
frame:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")

frame:SetScript("OnEvent", function(self, event, arg1)
    if event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED" then
        UpdateVisibility()
    elseif event == "UNIT_STATS" or event == "UNIT_DEFENSE" or event == "UNIT_RESISTANCES" or event == "UNIT_AURA" or event == "COMBAT_RATING_UPDATE" then
        if arg1 == "player" then
            UpdateStats()
        end
    else
        UpdateStats()
    end
end)

-- OnUpdate for real-time updates (every 0.5 seconds when visible)
local updateInterval = 0.5
local lastUpdate = 0
frame:SetScript("OnUpdate", function(self, elapsed)
    if not self:IsShown() then return end
    lastUpdate = lastUpdate + elapsed
    if lastUpdate >= updateInterval then
        UpdateStats()
        lastUpdate = 0
    end
end)
