-- VDS_Controller_Browse
-- ============================================================================
-- Row-click delegates for the browse scrollBoxList (cookbook 08: behavior
-- in controllers, chrome in row factories).

VDS = VDS or {}
VDS.Controller_Browse = VDS.Controller_Browse or {}

local C = VDS.Controller_Browse
local A = VDS.Constants.ACTIONS

-- Called from VDS_Rows_Dye.lua's OnClick.
function C:OnDyeRowClick(row, button)
    if not row._dyeID then return end  -- header rows have no _dyeID
    local state  = VDS.Store:GetState()  -- top-level only: dye-row click mode dispatch
    local mode   = state.session.ui.filterMode
    local canvas = state.session.ui.canvas
    local live   = state.session.ui.live

    -- left: select/apply; right (canvas only): clear channel; shift+left: AH search.
    if button == "RightButton" then
        if mode == "canvas" then
            if not canvas.decorID then return end
            VDS.Store:Dispatch({
                type    = A.CANVAS_CLEAR_CHANNEL,
                payload = { ch = canvas.activeChannel },
            })
        end
        return
    end

    -- Live: state intent + imperative API write (reducer doesn't call the API). boundary
    if live and live.active and live.focusedSlot then  -- exception(false-positive): live-mode branch discriminator, not a guard
        VDS.Store:Dispatch({
            type    = VDS.Constants.ACTIONS.LIVE_SET_SLOT_DYE_INTENT,
            payload = { slotID = live.focusedSlot, dyeID = row._dyeID },
        })
        -- Ring-buffer recent dye; reducer caps at LIVE_RECENT_DYES_MAX.
        VDS.Store:Dispatch({
            type    = VDS.Constants.ACTIONS.LIVE_RECENT_DYE_ADD,
            payload = { dyeID = row._dyeID },
        })
        VDS.LiveCustomizeObserver:ApplyDye(live.focusedSlot, row._dyeID)
        return
    end

    if mode == "canvas" then
        if not canvas.decorID then return end  -- channel rows non-interactive without selection
        VDS.Store:Dispatch({
            type    = A.CANVAS_SET_CHANNEL_DYE,
            payload = { ch = canvas.activeChannel, dyeID = row._dyeID },
        })
        return
    end

    -- Palette toggle ONLY when on the Custom tab; without the mode guard, a
    -- lingering editingThemeName hijacks dye clicks on other tabs (no
    -- SET_SELECTED_DYE, empty detail strip).
    local editingThemeName = state.session.ui.byView[mode].editingThemeName
    if mode == "custom" and editingThemeName then
        VDS.Store:Dispatch({
            type    = A.CUSTOM_THEME_TOGGLE_DYE,
            payload = { name = editingThemeName, dyeID = row._dyeID },
        })
        return
    end

    if _G.IsShiftKeyDown() then
        local ahf = _G.AuctionHouseFrame  -- LoD; nil when AH not loaded
        local name = row._nameText and row._nameText:GetText()
        if ahf and name then
            ahf.SearchBar.SearchBox:SetText(name)
        end
        return
    end

    VDS.Store:Dispatch({
        type    = A.SET_SELECTED_DYE,
        payload = { id = row._dyeID },
    })
end

-- Herb row click -- select for detail strip; Shift+click searches AH.
function C:OnHerbRowClick(row, button)
    if not row._herbID then return end  -- header rows have no _herbID

    if _G.IsShiftKeyDown() then
        local ahf = _G.AuctionHouseFrame  -- LoD; nil when AH not loaded
        local name = row._nameText and row._nameText:GetText()
        if ahf and name then
            ahf.SearchBar.SearchBox:SetText(name)
        end
        return
    end

    VDS.Store:Dispatch({
        type    = A.SET_SELECTED_HERB,
        payload = { id = row._herbID },
    })
    VDS.ItemNameResolver:Request(row._herbID)  -- pre-warm so detail strip renders name on first paint
end

-- Palette row click: select as active subfilter. Edit button enters add/remove mode.
function C:OnPaletteRowClick(row, _button)
    local name = row and row._paletteName  -- exception(boundary): click can race pool reconfigure
    if not name then return end
    VDS.Store:Dispatch({
        type    = VDS.Constants.ACTIONS.SET_ACTIVE_SUBFILTER,
        payload = { kind = "theme", value = name },
    })
end

function C:OnCustomNew()
    if _G.StaticPopup_Show then _G.StaticPopup_Show("VDS_CREATE_CUSTOM_THEME") end
end

function C:OnCustomImport()
    if _G.StaticPopup_Show then _G.StaticPopup_Show("VDS_IMPORT_CUSTOM_THEME") end
end

-- Wire static sidebar buttons (row click handlers self-attach in the row factory).
function C:Wire(rootFrame)
    if not (rootFrame and rootFrame.widgets) then return end  -- exception(false-positive): Wire-on-empty-rootFrame is a supported no-op (wire smoke contract)
    local newBtn    = rootFrame.widgets["custom.newBtn"]
    local importBtn = rootFrame.widgets["custom.importBtn"]
    if newBtn then
        newBtn:SetScript("OnClick", function() C:OnCustomNew()    end)
    end
    if importBtn then
        importBtn:SetScript("OnClick", function() C:OnCustomImport() end)
    end
end
