local AddOnName = "Nanami-UI"
SFrames = SFrames or {}

-- ============================================================
-- Roll Tracker Data
-- ============================================================
local currentRolls = {}  -- [itemName] = { [playerName] = { action, roll } }

local _A = SFrames.ActiveTheme
local _bg = _A and _A.panelBg or { 0.08, 0.08, 0.10, 0.95 }
local _bd = _A and _A.panelBorder or { 0.3, 0.3, 0.35, 1 }

local RollUI = CreateFrame("Frame")
RollUI:RegisterEvent("CHAT_MSG_LOOT")
RollUI:RegisterEvent("CHAT_MSG_SYSTEM")

-- ============================================================
-- String helpers (Lua 5.0 only - NO string.match!)
-- ============================================================
local function StripLinks(msg)
    return string.gsub(msg, "|c%x%x%x%x%x%x%x%x|H.-|h(.-)|h|r", "%1")
end

local function GetBracketItem(text)
    local _, _, name = string.find(text, "%[(.-)%]")
    if name then return name end
    text = string.gsub(text, "^%s+", "")
    text = string.gsub(text, "%s+$", "")
    text = string.gsub(text, "%.$", "")
    return text
end

local function TrimStr(s)
    s = string.gsub(s, "^%s+", "")
    s = string.gsub(s, "%s+$", "")
    return s
end

-- ============================================================
-- Parse loot roll chat messages
-- ============================================================
local function TrackRollEvent(msg)
    if not msg or msg == "" then return nil end
    
    local clean = StripLinks(msg)
    local player, rawItem, rollType, rollNum
    
    -- Patterns based on ACTUAL Turtle WoW Chinese message format:
    -- "Buis选择了贪婪取向：[物品名]"
    -- "Buis选择了需求取向：[物品名]"
    
    local _, _, p, i
    
    -- === PRIMARY: Turtle WoW Chinese format "选择了需求取向" / "选择了贪婪取向" ===
    _, _, p, i = string.find(clean, "^(.+)选择了需求取向：(.+)$")
    if p and i then player = p; rawItem = i; rollType = "Need" end
    
    if not player then
        _, _, p, i = string.find(clean, "^(.+)选择了需求取向: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Need" end
    end
    
    if not player then
        _, _, p, i = string.find(clean, "^(.+)选择了贪婪取向：(.+)$")
        if p and i then player = p; rawItem = i; rollType = "Greed" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+)选择了贪婪取向: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Greed" end
    end
    
    -- Pass: "放弃了" format
    if not player then
        _, _, p, i = string.find(clean, "^(.+)放弃了：(.+)$")
        if p and i then player = p; rawItem = i; rollType = "Pass" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+)放弃了: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Pass" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+)放弃了(.+)$")
        if p and i then player = p; rawItem = i; rollType = "Pass" end
    end
    
    -- Roll (Chinese): "掷出 85 (1-100)"
    if not player then
        local r
        _, _, p, r, i = string.find(clean, "^(.+)掷出%s*(%d+).-：(.+)$")
        if p and r and i then player = p; rawItem = i; rollType = "Roll"; rollNum = r end
    end
    if not player then
        local r
        _, _, p, r, i = string.find(clean, "^(.+)掷出%s*(%d+).-: (.+)$")
        if p and r and i then player = p; rawItem = i; rollType = "Roll"; rollNum = r end
    end
    
    -- === FALLBACK: Other Chinese formats ===
    if not player then
        _, _, p, i = string.find(clean, "^(.+)需求了：(.+)$")
        if p and i then player = p; rawItem = i; rollType = "Need" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+)贪婪了：(.+)$")
        if p and i then player = p; rawItem = i; rollType = "Greed" end
    end
    
    -- === ENGLISH patterns ===
    if not player then
        _, _, p, i = string.find(clean, "^(.+) selected Need for: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Need" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+) selected Greed for: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Greed" end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+) passed on: (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Pass" end
    end
    if not player then
        local r
        _, _, p, r, i = string.find(clean, "^(.+) rolls (%d+) .+for: (.+)$")
        if p and r and i then player = p; rawItem = i; rollType = "Roll"; rollNum = r end
    end
    if not player then
        _, _, p, i = string.find(clean, "^(.+) passes on (.+)$")
        if p and i then player = p; rawItem = i; rollType = "Pass" end
    end
    
    if player and rawItem then
        player = TrimStr(player)
        local itemName = GetBracketItem(rawItem)
        
        if itemName == "" or player == "" then return nil end
        
        if not currentRolls[itemName] then currentRolls[itemName] = {} end
        if not currentRolls[itemName][player] then currentRolls[itemName][player] = {} end
        
        if rollType == "Roll" then
            currentRolls[itemName][player].roll = rollNum
        else
            currentRolls[itemName][player].action = rollType
        end
        return itemName
    end
    return nil
end

-- ============================================================
-- Update the tracker text on visible roll frames
-- ============================================================
local function UpdateRollTrackers()
    for idx = 1, 4 do
        local frame = _G["GroupLootFrame"..idx]
        if frame and frame:IsVisible() and frame.rollID then
            local _, itemName = GetLootRollItemInfo(frame.rollID)
            
            if itemName and frame.sfNeedFS then
                local data = currentRolls[itemName]
                local needText, greedText, passText = "", "", ""
                if data then
                    local needs, greeds, passes = {}, {}, {}
                    for pl, info in pairs(data) do
                        local hex = SFrames and SFrames:GetClassHexForName(pl)
                        local coloredPl = hex and ("|cff" .. hex .. pl .. "|r") or pl
                        local rollStr = ""
                        if info.roll then rollStr = "|cffaaaaaa(" .. info.roll .. ")|r" end
                        if info.action == "Need" then
                            table.insert(needs, coloredPl .. rollStr)
                        elseif info.action == "Greed" then
                            table.insert(greeds, coloredPl .. rollStr)
                        elseif info.action == "Pass" then
                            table.insert(passes, coloredPl)
                        end
                    end
                    if table.getn(needs) > 0 then
                        needText = "|cffff5555需求|r " .. table.concat(needs, " ")
                    end
                    if table.getn(greeds) > 0 then
                        greedText = "|cff55ff55贪婪|r " .. table.concat(greeds, " ")
                    end
                    if table.getn(passes) > 0 then
                        passText = "|cff888888放弃|r " .. table.concat(passes, " ")
                    end
                end
                frame.sfNeedFS:SetText(needText)
                frame.sfGreedFS:SetText(greedText)
                frame.sfPassFS:SetText(passText)
            end
        end
    end
end

-- ============================================================
-- Event Handler
-- ============================================================
RollUI:SetScript("OnEvent", function()
    if event == "CHAT_MSG_LOOT" or event == "CHAT_MSG_SYSTEM" then
        local matched = TrackRollEvent(arg1)
        if matched then
            UpdateRollTrackers()
        end
    end
end)

-- ============================================================
-- Kill ALL Blizzard textures on the main frame only
-- ============================================================
local function NukeBlizzTextures(frame)
    local regions = {frame:GetRegions()}
    for _, r in ipairs(regions) do
        if r:IsObjectType("Texture") and not r.sfKeep then
            r:SetTexture(nil)
            r:SetAlpha(0)
            r:Hide()
            -- Don't override Show! SetBackdrop needs it.
            -- Instead mark as nuked and move off-screen
            if not r.sfNuked then
                r.sfNuked = true
                r:ClearAllPoints()
                r:SetPoint("CENTER", UIParent, "CENTER", 9999, 9999)
            end
        end
    end
end

-- ============================================================
-- Style the GroupLootFrame
-- ============================================================
local function StyleGroupLootFrame(frame)
    if frame.sfSkinned then return end
    frame.sfSkinned = true
    
    local fname = frame:GetName()
    
    -- 1) Kill all Blizz textures on main frame
    NukeBlizzTextures(frame)
    
    -- 2) Alt-Drag
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetScript("OnDragStart", function()
        if IsAltKeyDown() then
            this:StartMoving()
        end
    end)
    frame:SetScript("OnDragStop", function()
        this:StopMovingOrSizing()
    end)
    
    -- 3) Rounded backdrop
    frame:SetBackdrop({
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 14,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
    })
    frame:SetBackdropColor(_bg[1], _bg[2], _bg[3], _bg[4])
    frame:SetBackdropBorderColor(_bd[1], _bd[2], _bd[3], _bd[4])
    
    -- Tag all backdrop regions so NukeBlizzTextures won't kill them
    local bdRegions = {frame:GetRegions()}
    for _, r in ipairs(bdRegions) do
        r.sfKeep = true
    end
    
    -- 5) Frame size (taller for tracker area)
    frame:SetWidth(300)
    frame:SetHeight(100)
    
    -- 6) Icon
    local iconFrame = _G[fname.."IconFrame"]
    if iconFrame then
        iconFrame:ClearAllPoints()
        iconFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 12, -10)
        iconFrame:SetWidth(36)
        iconFrame:SetHeight(36)
        
        -- Kill IconFrame's own textures
        local iRegions = {iconFrame:GetRegions()}
        for _, r in ipairs(iRegions) do
            if r:IsObjectType("Texture") then
                local tName = r:GetName() or ""
                if string.find(tName, "Icon") then
                    r:SetTexCoord(0.08, 0.92, 0.08, 0.92)
                    r:ClearAllPoints()
                    r:SetAllPoints(iconFrame)
                    r.sfKeep = true
                else
                    r:SetTexture(nil)
                    r:SetAlpha(0)
                    r:Hide()
                    r.sfNuked = true
                    r:ClearAllPoints()
                    r:SetPoint("CENTER", UIParent, "CENTER", 9999, 9999)
                end
            end
        end
        
        -- Clean icon border
        local iconBorder = frame:CreateTexture(nil, "ARTWORK")
        iconBorder:SetTexture("Interface\\Buttons\\WHITE8X8")
        iconBorder:SetVertexColor(0.4, 0.4, 0.45, 1)
        iconBorder:SetPoint("TOPLEFT", iconFrame, "TOPLEFT", -2, 2)
        iconBorder:SetPoint("BOTTOMRIGHT", iconFrame, "BOTTOMRIGHT", 2, -2)
        iconBorder.sfKeep = true

        local qualGlow = frame:CreateTexture(nil, "OVERLAY")
        qualGlow:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
        qualGlow:SetBlendMode("ADD")
        qualGlow:SetAlpha(0.8)
        qualGlow:SetWidth(68)
        qualGlow:SetHeight(68)
        qualGlow:SetPoint("CENTER", iconFrame, "CENTER", 0, 0)
        qualGlow:Hide()
        qualGlow.sfKeep = true
        frame.sfQualGlow = qualGlow
    end
    
    -- 7) Item Name (shorter width to make room for buttons)
    local itemNameFS = _G[fname.."Name"]
    if itemNameFS then
        itemNameFS:ClearAllPoints()
        itemNameFS:SetPoint("LEFT", iconFrame, "RIGHT", 10, 0)
        itemNameFS:SetWidth(145)
        itemNameFS:SetHeight(36)
        itemNameFS:SetJustifyH("LEFT")
        itemNameFS:SetJustifyV("MIDDLE")
    end
    
    -- 8) Buttons: right side, vertically centered with icon
    local need = _G[fname.."NeedButton"]
    local greed = _G[fname.."GreedButton"]
    local pass = _G[fname.."PassButton"]
    
    -- Create our own close/pass button since Blizz keeps hiding PassButton
    local closeBtn = CreateFrame("Button", nil, frame)
    closeBtn:SetWidth(20)
    closeBtn:SetHeight(20)
    closeBtn:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -6, -6)
    closeBtn:SetFrameLevel(frame:GetFrameLevel() + 10)
    
    -- Rounded backdrop matching UI
    closeBtn:SetBackdrop({
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 8, edgeSize = 8,
        insets = { left = 2, right = 2, top = 2, bottom = 2 }
    })
    local _cbg = _A and _A.closeBtnBg or { 0.5, 0.1, 0.1, 0.85 }
    local _cbd = _A and _A.closeBtnBorder or { 0.6, 0.2, 0.2, 0.8 }
    local _cbgH = _A and _A.closeBtnHoverBg or { 0.7, 0.15, 0.15, 1 }
    local _cbdH = _A and _A.closeBtnHoverBorder or { 0.9, 0.3, 0.3, 1 }
    closeBtn:SetBackdropColor(_cbg[1], _cbg[2], _cbg[3], _cbg[4])
    closeBtn:SetBackdropBorderColor(_cbd[1], _cbd[2], _cbd[3], _cbd[4])
    
    -- "X" text
    local closeText = closeBtn:CreateFontString(nil, "OVERLAY")
    closeText:SetFont(SFrames:GetFont() or "Fonts\\ARKai_T.ttf", 11, "OUTLINE")
    closeText:SetPoint("CENTER", closeBtn, "CENTER", 0, 0)
    closeText:SetText("X")
    closeText:SetTextColor(0.9, 0.8, 0.8)
    
    closeBtn:SetScript("OnClick", function()
        local parent = this:GetParent()
        if parent and parent.rollID then
            ConfirmLootRoll(parent.rollID, 0)
        end
    end)
    closeBtn:SetScript("OnEnter", function()
        this:SetBackdropColor(_cbgH[1], _cbgH[2], _cbgH[3], _cbgH[4])
        this:SetBackdropBorderColor(_cbdH[1], _cbdH[2], _cbdH[3], _cbdH[4])
        GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
        GameTooltip:SetText("放弃 / Pass")
        GameTooltip:Show()
    end)
    closeBtn:SetScript("OnLeave", function()
        this:SetBackdropColor(_cbg[1], _cbg[2], _cbg[3], _cbg[4])
        this:SetBackdropBorderColor(_cbd[1], _cbd[2], _cbd[3], _cbd[4])
        GameTooltip:Hide()
    end)
    
    -- Position need/greed to the left of close button
    if need and greed then
        greed:ClearAllPoints()
        greed:SetPoint("RIGHT", closeBtn, "LEFT", -6, 0)
        greed:SetWidth(22); greed:SetHeight(22)
        greed:Show()
        
        need:ClearAllPoints()
        need:SetPoint("RIGHT", greed, "LEFT", -4, 0)
        need:SetWidth(22); need:SetHeight(22)
        need:Show()
    end
    
    -- Hide Blizz pass button
    if pass then
        pass:ClearAllPoints()
        pass:SetPoint("CENTER", UIParent, "CENTER", 9999, 9999)
        pass:SetAlpha(0)
    end
    
    -- 9) HIDE Blizz timer completely
    local blizzTimer = _G[fname.."Timer"]
    if blizzTimer then
        blizzTimer:SetAlpha(0)
        blizzTimer:ClearAllPoints()
        blizzTimer:SetPoint("BOTTOMLEFT", frame, "TOPLEFT", 0, 500)
    end
    
    -- 10) Our own timer bar
    local myTimer = CreateFrame("StatusBar", nil, frame)
    myTimer:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 12, 8)
    myTimer:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -12, 8)
    myTimer:SetHeight(6)
    myTimer:SetMinMaxValues(0, 1)
    myTimer:SetValue(1)
    myTimer:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar")
    myTimer:SetStatusBarColor(0.9, 0.7, 0.15)
    
    local myTimerBg = myTimer:CreateTexture(nil, "BACKGROUND")
    myTimerBg:SetTexture("Interface\\Buttons\\WHITE8X8")
    myTimerBg:SetVertexColor(_A.slotBg[1], _A.slotBg[2], _A.slotBg[3], _A.slotBg[4] or 1)
    myTimerBg:SetAllPoints(myTimer)
    
    frame.sfTimer = myTimer
    frame.sfTimerMax = nil  -- will be set on first OnUpdate
    
    -- 11) OnUpdate: record max time on first tick, then animate
    frame:SetScript("OnUpdate", function()
        if this.rollID and this.sfTimer then
            local timeLeft = GetLootRollTimeLeft(this.rollID)
            if timeLeft and timeLeft > 0 then
                if not this.sfTimerMax or this.sfTimerMax < timeLeft then
                    this.sfTimerMax = timeLeft
                end
                this.sfTimer:SetMinMaxValues(0, this.sfTimerMax)
                this.sfTimer:SetValue(timeLeft)
            else
                this.sfTimer:SetValue(0)
            end
        end
    end)
    
    -- 12) Clean button textures so they don't extend beyond bounds
    if need then
        local nRegions = {need:GetRegions()}
        for _, r in ipairs(nRegions) do
            if r:IsObjectType("Texture") then
                r:ClearAllPoints()
                r:SetAllPoints(need)
            end
        end
    end
    if greed then
        local gRegions = {greed:GetRegions()}
        for _, r in ipairs(gRegions) do
            if r:IsObjectType("Texture") then
                r:ClearAllPoints()
                r:SetAllPoints(greed)
            end
        end
    end
    
    -- 13) Three FontStrings for Need / Greed / Pass (vertical stack, full width)
    local textWidth = 276
    
    local needFS = frame:CreateFontString(nil, "OVERLAY")
    needFS:SetFont(SFrames:GetFont() or "Fonts\\ARKai_T.ttf", 10, "OUTLINE")
    needFS:SetPoint("TOPLEFT", iconFrame, "BOTTOMLEFT", 0, -4)
    needFS:SetWidth(textWidth)
    needFS:SetJustifyH("LEFT")
    needFS:SetJustifyV("TOP")
    needFS:SetTextColor(1, 1, 1)
    frame.sfNeedFS = needFS
    
    local greedFS = frame:CreateFontString(nil, "OVERLAY")
    greedFS:SetFont(SFrames:GetFont() or "Fonts\\ARKai_T.ttf", 10, "OUTLINE")
    greedFS:SetPoint("TOPLEFT", needFS, "BOTTOMLEFT", 0, -1)
    greedFS:SetWidth(textWidth)
    greedFS:SetJustifyH("LEFT")
    greedFS:SetJustifyV("TOP")
    greedFS:SetTextColor(1, 1, 1)
    frame.sfGreedFS = greedFS
    
    local passFS = frame:CreateFontString(nil, "OVERLAY")
    passFS:SetFont(SFrames:GetFont() or "Fonts\\ARKai_T.ttf", 10, "OUTLINE")
    passFS:SetPoint("TOPLEFT", greedFS, "BOTTOMLEFT", 0, -1)
    passFS:SetWidth(textWidth)
    passFS:SetJustifyH("LEFT")
    passFS:SetJustifyV("TOP")
    passFS:SetTextColor(1, 1, 1)
    frame.sfPassFS = passFS
end

-- ============================================================
-- Hooks
-- ============================================================
local function RestoreBackdrop(frame)
    if not frame.sfSkinned then return end
    frame:SetBackdrop({
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 14,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
    })
    frame:SetBackdropColor(_bg[1], _bg[2], _bg[3], _bg[4])
    frame:SetBackdropBorderColor(_bd[1], _bd[2], _bd[3], _bd[4])
end

local function UpdateRollQualityGlow(frame)
    if frame.sfQualGlow and frame.rollID then
        local _, _, _, quality = GetLootRollItemInfo(frame.rollID)
        if quality and quality > 1 then
            local r, g, b = GetItemQualityColor(quality)
            frame.sfQualGlow:SetVertexColor(r, g, b)
            frame.sfQualGlow:Show()
        else
            frame.sfQualGlow:Hide()
        end
    end
end

local Hook_GroupLootFrame_OnShow = GroupLootFrame_OnShow
function GroupLootFrame_OnShow()
    if Hook_GroupLootFrame_OnShow then Hook_GroupLootFrame_OnShow() end
    StyleGroupLootFrame(this)
    NukeBlizzTextures(this)
    RestoreBackdrop(this)
    UpdateRollQualityGlow(this)
    UpdateRollTrackers()
end

local Hook_GroupLootFrame_Update = GroupLootFrame_Update
function GroupLootFrame_Update()
    if Hook_GroupLootFrame_Update then Hook_GroupLootFrame_Update() end
    for idx = 1, 4 do
        local f = _G["GroupLootFrame"..idx]
        if f and f:IsVisible() and f.sfSkinned then
            NukeBlizzTextures(f)
            RestoreBackdrop(f)
            UpdateRollQualityGlow(f)
        end
    end
    UpdateRollTrackers()
end
