local addonName, NS = ...

-- ============================================================================
-- VAULTSKINS: CONFIRMATION POPUPS
-- ============================================================================
local Skin = NS.Skin
local Shared = NS.SkinShared
local ApplyBackdrop = Shared.ApplyBackdrop
local BlendColor = Shared.BlendColor
local CreateBackdropFrame = Shared.CreateBackdropFrame
local EnsureReadableColor = Shared.EnsureReadableColor
local SafeCall = Shared.SafeCall
local ScheduleOwnedTimer = Shared.ScheduleOwnedTimer
local WHITE_TEXTURE = Shared.WHITE_TEXTURE

-- =========================== POPUP MATCHING DATA ============================
local POPUP_CHROME_KEYS = {
    "Background", "BG", "Border", "BorderFrame", "NineSlice",
    "TopLeftCorner", "TopRightCorner", "BottomLeftCorner", "BottomRightCorner",
    "TopEdge", "BottomEdge", "LeftEdge", "RightEdge",
}
local POPUP_BUTTON_TEXTURE_KEYS = {
    "Left", "Middle", "Right", "LeftDisabled", "MiddleDisabled", "RightDisabled",
}
local POPUP_TEXT_KEYS = {
    "Text", "text", "TitleText", "HeaderText", "Title", "Message", "Description",
}
local WEEKLY_REWARD_CONFIRMATION_PHRASES = {
    "unable to change this reward",
    "select this item",
    "also receive",
    "are you sure you wish to select this item",
}
local WEEKLY_REWARD_CONFIRMATION_FRAME_NAMES = {
    "WeeklyRewardsConfirmSelectionFrame",
    "WeeklyRewardsSelectionConfirmationFrame",
    "WeeklyRewardsConfirmFrame",
    "WeeklyRewardsConfirmSelectionDialog",
    "WeeklyRewardsSelectRewardConfirmationFrame",
    "GreatVaultConfirmSelectionFrame",
}
local POPUP_RESTYLE_DELAYS = { 0, 0.03, 0.10, 0.20 }

-- ========================== STATE CAPTURE HELPERS ===========================
local function CapturePopupRegionState(frame, region)
    if not frame or not region then return end
    frame.VaultSkinsPopupOriginal = frame.VaultSkinsPopupOriginal or {
        regions = setmetatable({}, { __mode = "k" }),
        texts = setmetatable({}, { __mode = "k" }),
        buttons = setmetatable({}, { __mode = "k" }),
        strata = frame.GetFrameStrata and frame:GetFrameStrata() or nil,
    }
    local cache = frame.VaultSkinsPopupOriginal.regions
    if cache[region] == nil then
        cache[region] = {
            alpha = region.GetAlpha and region:GetAlpha() or 1,
            shown = region.IsShown and region:IsShown() or true,
        }
    end
end

local function CapturePopupTextState(frame, region)
    if not frame or not region or not region.GetTextColor then return end
    frame.VaultSkinsPopupOriginal = frame.VaultSkinsPopupOriginal or {
        regions = setmetatable({}, { __mode = "k" }),
        texts = setmetatable({}, { __mode = "k" }),
        buttons = setmetatable({}, { __mode = "k" }),
        strata = frame.GetFrameStrata and frame:GetFrameStrata() or nil,
    }
    local cache = frame.VaultSkinsPopupOriginal.texts
    if cache[region] == nil then
        local r, g, b, a = region:GetTextColor()
        cache[region] = { r = r, g = g, b = b, a = a or 1 }
    end
end

local function CapturePopupButtonState(frame, button)
    if not frame or not button then return end
    frame.VaultSkinsPopupOriginal = frame.VaultSkinsPopupOriginal or {
        regions = setmetatable({}, { __mode = "k" }),
        texts = setmetatable({}, { __mode = "k" }),
        buttons = setmetatable({}, { __mode = "k" }),
        strata = frame.GetFrameStrata and frame:GetFrameStrata() or nil,
    }
    if frame.VaultSkinsPopupOriginal.buttons[button] then return end
    local state = { textures = {}, text = nil }
    for _, key in ipairs(POPUP_BUTTON_TEXTURE_KEYS) do
        local region = button[key]
        if region then
            state.textures[key] = {
                alpha = region.GetAlpha and region:GetAlpha() or 1,
                shown = region.IsShown and region:IsShown() or true,
            }
        end
    end
    local textRegion = button.Text or button.text or _G[button.GetName and button:GetName() and (button:GetName() .. "Text") or ""]
    if textRegion and textRegion.GetTextColor then
        local r, g, b, a = textRegion:GetTextColor()
        state.text = { region = textRegion, r = r, g = g, b = b, a = a or 1 }
    end
    frame.VaultSkinsPopupOriginal.buttons[button] = state
end

local function StylePopupButton(frame, button, theme)
    if not frame or not button or not button.GetObjectType or button:GetObjectType() ~= "Button" then return end
    CapturePopupButtonState(frame, button)
    for _, key in ipairs(POPUP_BUTTON_TEXTURE_KEYS) do
        if button[key] then button[key]:SetAlpha(0) end
    end
    if not button.VaultSkinsPopupBackdrop then
        button.VaultSkinsPopupBackdrop = CreateBackdropFrame(button, 1, -1)
    end
    if button.VaultSkinsPopupBackdrop then
        button.VaultSkinsPopupBackdrop:Show()
        ApplyBackdrop(button.VaultSkinsPopupBackdrop, BlendColor(theme.panel, theme.reward or theme.panel, 0.22, 0.99), {
            r = theme.border.r, g = theme.border.g, b = theme.border.b, a = 0.92,
        }, 1)
    end
    local textRegion = button.Text or button.text or _G[button.GetName and button:GetName() and (button:GetName() .. "Text") or ""]
    if textRegion and textRegion.SetTextColor then
        local readable = EnsureReadableColor(theme.text, 0.84)
        textRegion:SetTextColor(readable.r, readable.g, readable.b, 1)
    end
end

local function PopupTextMatches(region)
    local value = region and region.GetText and region:GetText()
    if type(value) ~= "string" then return false end
    local lower = value:lower()
    for _, phrase in ipairs(WEEKLY_REWARD_CONFIRMATION_PHRASES) do
        if lower:find(phrase, 1, true) then return true end
    end
    return false
end

local function PopupRegionsMatch(...)
    for index = 1, select("#", ...) do
        local region = select(index, ...)
        if region and region.GetObjectType and region:GetObjectType() == "FontString" and PopupTextMatches(region) then
            return true
        end
    end
    return false
end

-- ============================= POPUP DETECTION ==============================
function Skin:IsWeeklyRewardConfirmationFrame(frame)
    if not frame then return false end
    if frame.VaultSkinsPopupBackdrop or frame.VaultSkinsPopupFill then return true end
    local name = frame.GetName and frame:GetName() or ""
    if name and (name:find("WeeklyRewards") or name:find("GreatVault")) then
        return true
    end
    for _, key in ipairs(POPUP_TEXT_KEYS) do
        if PopupTextMatches(frame[key]) then return true end
    end
    if frame.GetRegions and PopupRegionsMatch(frame:GetRegions()) then
        return true
    end
    return false
end

-- ======================== APPLY AND RESTORE STYLING =========================
function Skin:StyleWeeklyRewardConfirmationFrame(frame)
    if not frame or not self:IsEnabled() or not self:IsWeeklyRewardConfirmationFrame(frame) then return end
    local theme = self:GetTheme()
    frame.VaultSkinsPopupOriginal = frame.VaultSkinsPopupOriginal or {
        regions = setmetatable({}, { __mode = "k" }),
        texts = setmetatable({}, { __mode = "k" }),
        buttons = setmetatable({}, { __mode = "k" }),
        strata = frame.GetFrameStrata and frame:GetFrameStrata() or nil,
    }
    frame:SetFrameStrata("DIALOG")
    frame:SetClampedToScreen(true)
    frame:SetAlpha(1)

    if not frame.VaultSkinsPopupBackdrop then
        frame.VaultSkinsPopupBackdrop = CreateBackdropFrame(frame, 1, -1)
    end
    if not frame.VaultSkinsPopupFill then
        frame.VaultSkinsPopupFill = frame:CreateTexture(nil, "BACKGROUND", nil, 1)
        frame.VaultSkinsPopupFill:SetPoint("TOPLEFT", frame, "TOPLEFT", 3, -3)
        frame.VaultSkinsPopupFill:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -3, 3)
        frame.VaultSkinsPopupFill:SetTexture(WHITE_TEXTURE)
    end
    if not frame.VaultSkinsPopupAccent then
        frame.VaultSkinsPopupAccent = frame:CreateTexture(nil, "ARTWORK")
        frame.VaultSkinsPopupAccent:SetTexture(WHITE_TEXTURE)
        frame.VaultSkinsPopupAccent:SetPoint("TOPLEFT", frame, "TOPLEFT", 8, -8)
        frame.VaultSkinsPopupAccent:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -8, -8)
        frame.VaultSkinsPopupAccent:SetHeight(2)
    end

    if frame.VaultSkinsPopupBackdrop then
        frame.VaultSkinsPopupBackdrop:Show()
        ApplyBackdrop(frame.VaultSkinsPopupBackdrop, BlendColor(theme.background, theme.panel, 0.70, 1), {
            r = theme.border.r,
            g = theme.border.g,
            b = theme.border.b,
            a = 1,
        }, 2)
    end
    frame.VaultSkinsPopupFill:SetColorTexture(
        math.max(0.01, theme.background.r * 0.78),
        math.max(0.01, theme.background.g * 0.78),
        math.max(0.01, theme.background.b * 0.78),
        1
    )
    frame.VaultSkinsPopupFill:Show()
    frame.VaultSkinsPopupAccent:SetColorTexture(theme.accent.r, theme.accent.g, theme.accent.b, 0.92)
    frame.VaultSkinsPopupAccent:Show()

    for _, key in ipairs(POPUP_CHROME_KEYS) do
        local region = frame[key]
        if region then
            CapturePopupRegionState(frame, region)
            if region.SetAlpha then region:SetAlpha(0) end
            if region.Hide then region:Hide() end
        end
    end

    local readable = EnsureReadableColor(theme.text, 0.84)
    local muted = EnsureReadableColor(theme.muted or theme.text, 0.70)
    for _, key in ipairs(POPUP_TEXT_KEYS) do
        local region = frame[key]
        if region and region.SetTextColor then
            CapturePopupTextState(frame, region)
            local value = region.GetText and region:GetText() or ""
            local lower = type(value) == "string" and value:lower() or ""
            local color = lower:find("unable to change", 1, true) and muted or readable
            region:SetTextColor(color.r, color.g, color.b, 1)
        end
    end

    if frame.Button1 then StylePopupButton(frame, frame.Button1, theme) end
    if frame.Button2 then StylePopupButton(frame, frame.Button2, theme) end
end

function Skin:RestoreWeeklyRewardConfirmationFrame(frame)
    if not frame then return end
    if frame.VaultSkinsPopupBackdrop then frame.VaultSkinsPopupBackdrop:Hide() end
    if frame.VaultSkinsPopupFill then frame.VaultSkinsPopupFill:Hide() end
    if frame.VaultSkinsPopupAccent then frame.VaultSkinsPopupAccent:Hide() end

    local original = frame.VaultSkinsPopupOriginal
    if not original then return end
    if original.strata and frame.SetFrameStrata then frame:SetFrameStrata(original.strata) end
    for region, state in pairs(original.regions or {}) do
        if region then
            if region.SetAlpha then region:SetAlpha(state.alpha or 1) end
            if state.shown then
                if region.Show then region:Show() end
            elseif region.Hide then
                region:Hide()
            end
        end
    end
    for region, color in pairs(original.texts or {}) do
        if region and region.SetTextColor then
            region:SetTextColor(color.r or 1, color.g or 1, color.b or 1, color.a or 1)
        end
    end
    for button, state in pairs(original.buttons or {}) do
        if button and button.VaultSkinsPopupBackdrop then button.VaultSkinsPopupBackdrop:Hide() end
        for key, textureState in pairs(state.textures or {}) do
            local region = button and button[key]
            if region then
                if region.SetAlpha then region:SetAlpha(textureState.alpha or 1) end
                if textureState.shown then
                    if region.Show then region:Show() end
                elseif region.Hide then
                    region:Hide()
                end
            end
        end
        local textState = state.text
        if textState and textState.region and textState.region.SetTextColor then
            textState.region:SetTextColor(textState.r or 1, textState.g or 1, textState.b or 1, textState.a or 1)
        end
    end
end

function Skin:RestoreWeeklyRewardConfirmationPopups()
    for _, name in ipairs(WEEKLY_REWARD_CONFIRMATION_FRAME_NAMES) do
        self:RestoreWeeklyRewardConfirmationFrame(_G[name])
    end
    for i = 1, 4 do
        self:RestoreWeeklyRewardConfirmationFrame(_G["StaticPopup" .. i])
    end
end

-- ============================ HOOK INSTALLATION =============================
function Skin:HookWeeklyRewardConfirmationPopups()
    local function hookFrame(frame)
        if not frame or frame.VaultSkinsWeeklyRewardPopupHook then return false end
        frame.VaultSkinsWeeklyRewardPopupHook = true
        frame:HookScript("OnShow", function(selfFrame)
            for attempt, delay in ipairs(POPUP_RESTYLE_DELAYS) do
                ScheduleOwnedTimer("reward-confirm-popup:" .. tostring(selfFrame) .. ":" .. attempt, delay, function()
                    if selfFrame and selfFrame:IsShown() then
                        if Skin:IsEnabled() then
                            SafeCall("style reward confirmation popup", Skin.StyleWeeklyRewardConfirmationFrame, Skin, selfFrame)
                        else
                            Skin:RestoreWeeklyRewardConfirmationFrame(selfFrame)
                        end
                    end
                end)
            end
        end)
        return true
    end

    local hookedAny = self.confirmationHooksInstalled or false
    for _, name in ipairs(WEEKLY_REWARD_CONFIRMATION_FRAME_NAMES) do
        if hookFrame(_G[name]) then hookedAny = true end
    end
    for i = 1, 4 do
        if hookFrame(_G["StaticPopup" .. i]) then hookedAny = true end
    end
    self.confirmationHooksInstalled = hookedAny
end
