--[[
============================================================================
ERB/UI/MainFrame/Construction.lua  (added in v15.3.0 — Audit Batch 4 Part 3)
============================================================================

Frame-construction methods for the ERB MainFrame orchestrator. Owner-pattern:
each method takes `owner` (the MF orchestrator) as first argument. The
orchestrator keeps thin delegators so the existing call sites
(ERB.MainFrame:Create() etc.) keep working without changes.

Methods owned here (6):
  Create              — top-level frame + event registration
  CreateTopBar        — top-bar buttons (sources toggle, phase tabs)
  CreateLeftSidebar   — slot button column
  CreateItemGrid      — central rows container
  CreateItemRow       — one ranked row (index-aware factory)
  CreateDetailPanel   — right-hand-side detail container

External dependencies pulled from owner (the MF orchestrator):
  owner.frame              — built by Create, read by all other Create* methods
  owner.detailLines        — reused across rebuilds
  owner.slotButtons, owner.itemRows, owner.specButtons, owner.phaseTabs
  owner.PlayerOwnsItem     — accessor for the file-local PlayerOwnsItem fn
  owner.SLOT_ICONS, owner.RANK_COLORS, owner.FRAME_*, owner.SIDEBAR_WIDTH,
  owner.DETAIL_WIDTH, owner.FRAME_MARGIN, owner.TITLE_HEIGHT,
  owner.TOPBAR_HEIGHT, owner.BOTTOMBAR_HEIGHT, owner.CONTENT_Y,
  owner.BOTTOM_MARGIN, owner.ITEM_ROW_HEIGHT, owner.MAX_ITEMS — geometry/visuals
  owner:CreateTopBar, owner:CreateLeftSidebar, owner:CreateItemGrid,
  owner:CreateDetailPanel — internal cross-method calls
  owner:UpdateDisplay      — invoked from event timer when items finish loading
  owner:ShowItemDetail     — invoked from row OnEnter

Closure / shadowing notes:
  - 2 `function(self,...)` script handlers in this cluster (the transmogToggle
    OnEnter at line 52 and the row OnEnter at line 348). In both, the closure
    parameter `self` is the BUTTON/ROW being hovered — NOT the orchestrator.
    Pre-extraction we renamed `self` → `widget` in these closure bodies so the
    global `self → owner` transform stays correct. `widget` is the
    hovered frame; `owner` is the MF orchestrator captured by closure from
    the outer Construction:Create scope.
  - One C_Timer.After callback inside Create's OnEvent (debounced rebuild on
    GET_ITEM_INFO_RECEIVED) — references outer `owner` via closure. No self
    parameter there, no shadowing risk.
============================================================================
]]--
local ADDON_NAME, NS = ...
local ETB = NS.ETB
local ERB = ETB and ETB.ERB
if not ERB then return end

NS.ETB.ERB.MainFrame = NS.ETB.ERB.MainFrame or {}
NS.ETB.ERB.MainFrame.Construction = NS.ETB.ERB.MainFrame.Construction or {}
local Construction = NS.ETB.ERB.MainFrame.Construction

-- =============================================================================
-- METHODS (extracted from ERB/UI/MainFrame.lua in v15.3.0)
-- =============================================================================

function Construction:Create(owner)
    if owner.frame then return owner.frame end

    local f = CreateFrame("Frame", "ETB_ERB_MainFrame", UIParent, "BackdropTemplate")
    f:SetSize(owner.FRAME_WIDTH, owner.FRAME_HEIGHT)
    f:SetPoint("CENTER")
    f:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
        edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Border",
        tile = true, tileSize = 32, edgeSize = 32,
        insets = { left = 8, right = 8, top = 8, bottom = 8 }
    })
    f:SetBackdropColor(0, 0, 0, 1)  -- Fully opaque black
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    f:SetScript("OnDragStart", f.StartMoving)
    f:SetScript("OnDragStop", f.StopMovingOrSizing)
    f:SetFrameStrata("HIGH")
    f:SetFrameLevel(50)
    
    -- Solid blocker to ensure nothing bleeds through
    local blocker = f:CreateTexture(nil, "BACKGROUND", nil, -8)
    blocker:SetAllPoints(f)
    blocker:SetColorTexture(0.02, 0.02, 0.03, 1)
    
    f:Hide()

    -- ESC closes frame.
    -- v14.10.1: was OnKeyDown + pcall(SetPropagateKeyboardInput) which fired
    -- ADDON_ACTION_BLOCKED on MoP Classic 5.4.8. Frame previously had nil name —
    -- gave it "ETB_ERB_MainFrame" so UISpecialFrames can target it.
    if UISpecialFrames then
        local already = false
        for _, name in ipairs(UISpecialFrames) do
            if name == "ETB_ERB_MainFrame" then already = true; break end
        end
        if not already then tinsert(UISpecialFrames, "ETB_ERB_MainFrame") end
    end

    f.closeBtn = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    f.closeBtn:SetPoint("TOPRIGHT", -8, -8)

    -- Toggle button: switch to ETB Transmog Browser
    f.transmogToggle = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
    f.transmogToggle:SetSize(80, 22)
    f.transmogToggle:SetPoint("TOPRIGHT", -38, -16)
    f.transmogToggle:SetText("Transmog")
    f.transmogToggle:SetScript("OnClick", function()
        if ETB and ETB.ToggleUIMode then ETB:ToggleUIMode() end
    end)
    f.transmogToggle:SetScript("OnEnter", function(widget)
        GameTooltip:SetOwner(widget, "ANCHOR_BOTTOM")
        GameTooltip:AddLine("Switch to Transmog Browser")
        GameTooltip:Show()
    end)
    f.transmogToggle:SetScript("OnLeave", function() GameTooltip:Hide() end)

    f.title = f:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    f.title:SetPoint("TOP", 0, -18)
    f.title:SetText("|cffffd100Enhanced Raid Browser|r")

    f.version = f:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.version:SetPoint("TOPRIGHT", -40, -22)
    f.version:SetText("|cff888888v" .. (ERB.version or "0.1") .. "|r")

    owner:CreateTopBar(f)
    owner:CreateLeftSidebar(f)
    owner:CreateItemGrid(f)
    owner:CreateDetailPanel(f)

    owner.frame = f
    
    -- Handle async item info loads
    local eventFrame = CreateFrame("Frame")
    f._refreshPending = false
    f._refreshCount = 0
    
    f:SetScript("OnShow", function()
        f._refreshCount = 0
        f._refreshPending = false
        eventFrame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
    end)
    f:SetScript("OnHide", function()
        eventFrame:UnregisterAllEvents()
        f._refreshPending = false
    end)
    
    eventFrame:SetScript("OnEvent", function(_, event, itemID)
        if not f:IsShown() then return end
        if f._refreshCount >= 4 then
            eventFrame:UnregisterAllEvents()
            return
        end
        if not f._refreshPending then
            f._refreshPending = true
            C_Timer.After(0.3, function()
                f._refreshPending = false
                f._refreshCount = f._refreshCount + 1
                if f:IsShown() then
                    owner:UpdateDisplay()
                end
            end)
        end
    end)
    
    return f
end

-- ============================================================================
-- TOP BAR — Spec, source toggle, phase tabs
-- ============================================================================

function Construction:CreateTopBar(owner, f)
    local bar = CreateFrame("Frame", nil, f, "BackdropTemplate")
    bar:SetPoint("TOPLEFT", owner.FRAME_MARGIN, -owner.TITLE_HEIGHT)
    bar:SetPoint("TOPRIGHT", -owner.FRAME_MARGIN, -owner.TITLE_HEIGHT)
    bar:SetHeight(owner.TOPBAR_HEIGHT)
    bar:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 12,
        insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    f.topBar = bar

    f.specLabel = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    f.specLabel:SetPoint("TOPLEFT", 10, -6)

    -- Spec selector buttons (created dynamically in UpdateSpecButtons)
    f.specButtonContainer = CreateFrame("Frame", nil, bar)
    f.specButtonContainer:SetPoint("LEFT", f.specLabel, "RIGHT", 12, 0)
    f.specButtonContainer:SetSize(400, 22)

    -- Item count (top right)
    f.itemCountLabel = bar:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.itemCountLabel:SetPoint("TOPRIGHT", -10, -8)

    -- Source toggle button (bottom right of top bar).
    -- v15.63.0: WoWHead now carries Siege of Orgrimmar (P5) and WoWTBC carries
    -- Throne of Thunder (P3), so this is a live toggle (was a static label) that
    -- flips between the two curated sources (and any custom BiS lists).
    local srcBtn = CreateFrame("Button", nil, bar, "BackdropTemplate")
    srcBtn:SetSize(112, 20)
    srcBtn:SetPoint("BOTTOMRIGHT", -10, 8)
    srcBtn:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = false, edgeSize = 8,
        insets = { left = 2, right = 2, top = 2, bottom = 2 },
    })
    srcBtn:SetBackdropColor(0.10, 0.10, 0.18, 0.9)
    srcBtn:SetBackdropBorderColor(0.4, 0.4, 0.4)
    local srcTxt = srcBtn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    srcTxt:SetPoint("CENTER")
    srcBtn.txt = srcTxt
    f.sourceToggle = srcBtn
    f.sourceLabel = srcTxt  -- back-compat alias for older references

    local function refreshSrcText()
        local key = ERB.DataBridge and ERB.DataBridge.activeSource
        local label = (ERB.DataBridge and ERB.DataBridge:GetSourceLabel(key)) or "WoWTBC"
        srcTxt:SetText("Source: |cff00ccff" .. label .. "|r")
    end
    refreshSrcText()
    owner.UpdateSourceToggle = refreshSrcText  -- called from UpdatePhaseTabs to stay in sync

    srcBtn:SetScript("OnClick", function()
        if not (ERB.DataBridge and ERB.DataBridge.CycleSource) then return end
        ERB.DataBridge:CycleSource()
        refreshSrcText()
        owner:Refresh()
        owner:UpdatePhaseTabs()
        owner:SelectSlot(ERB.DataBridge.currentSlot or "Head")
    end)
    srcBtn:SetScript("OnEnter", function(self)
        self:SetBackdropBorderColor(0, 0.8, 1)
        GameTooltip:SetOwner(self, "ANCHOR_TOP")
        GameTooltip:AddLine("BiS Data Source — click to flip")
        GameTooltip:AddLine("|cff00ccffWoWHead|r |cff888888Siege of Orgrimmar (P5)|r")
        GameTooltip:AddLine("|cff00ccffWoWTBC|r |cff888888Throne of Thunder (P3)|r")
        GameTooltip:Show()
    end)
    srcBtn:SetScript("OnLeave", function(self) self:SetBackdropBorderColor(0.4, 0.4, 0.4); GameTooltip:Hide() end)

    -- Phase tabs
    f.phaseContainer = CreateFrame("Frame", nil, bar)
    f.phaseContainer:SetPoint("BOTTOMLEFT", 8, 6)
    f.phaseContainer:SetSize(owner.FRAME_WIDTH - 160, 22)
end

-- ============================================================================
-- LEFT SIDEBAR — Slot buttons
-- ============================================================================

function Construction:CreateLeftSidebar(owner, f)
    local sidebar = CreateFrame("Frame", nil, f, "BackdropTemplate")
    sidebar:SetWidth(owner.SIDEBAR_WIDTH)
    sidebar:SetPoint("TOPLEFT", owner.FRAME_MARGIN, owner.CONTENT_Y)
    sidebar:SetPoint("BOTTOMLEFT", owner.FRAME_MARGIN, owner.BOTTOM_MARGIN)
    sidebar:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 12,
        insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    sidebar:SetClipsChildren(true)
    f.sidebar = sidebar

    local title = sidebar:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -8)
    title:SetText("|cff00ffffGear Slots|r")

    local divider = sidebar:CreateTexture(nil, "ARTWORK")
    divider:SetSize(owner.SIDEBAR_WIDTH - 16, 2)
    divider:SetPoint("TOP", 0, -28)
    divider:SetColorTexture(0.5, 0.5, 0.5, 0.5)

    owner.slotButtons = {}
    local yOff = -36
    for _, slot in ipairs(ERB.DataBridge and ERB.DataBridge.SLOT_ORDER or {
        "Head","Neck","Shoulder","Back","Chest","Wrist",
        "Hands","Waist","Legs","Feet","Finger","Trinket",
        "Main Hand","Off Hand","Two Hand","Ranged","Weapon"
    }) do
        local btn = CreateFrame("Button", nil, sidebar)
        btn:SetSize(owner.SIDEBAR_WIDTH - 12, 28)
        btn:SetPoint("TOPLEFT", 6, yOff)

        local bg = btn:CreateTexture(nil, "BACKGROUND")
        bg:SetAllPoints()
        bg:SetColorTexture(0, 0, 0, 0)
        btn.bg = bg

        local icon = btn:CreateTexture(nil, "ARTWORK")
        icon:SetSize(22, 22)
        icon:SetPoint("LEFT", 4, 0)
        icon:SetTexture(owner.SLOT_ICONS[slot] or "Interface\\Icons\\INV_Misc_QuestionMark")
        icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

        local text = btn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        text:SetPoint("LEFT", icon, "RIGHT", 6, 0)
        text:SetText(slot)
        btn.label = text

        local countText = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
        countText:SetPoint("RIGHT", -6, 0)
        btn.countLabel = countText

        btn.selected = btn:CreateTexture(nil, "OVERLAY")
        btn.selected:SetAllPoints()
        btn.selected:SetColorTexture(0, 0.5, 1, 0.3)
        btn.selected:Hide()

        btn:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
        btn.slotName = slot
        btn:SetScript("OnClick", function() owner:SelectSlot(slot) end)

        owner.slotButtons[slot] = btn
        yOff = yOff - 29
    end
end

-- ============================================================================
-- ITEM GRID — shows items for selected slot, ranked with #1 - #6
-- ============================================================================

function Construction:CreateItemGrid(owner, f)
    local grid = CreateFrame("Frame", nil, f, "BackdropTemplate")
    grid:SetPoint("TOPLEFT", f.sidebar, "TOPRIGHT", 8, 0)
    grid:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -(owner.DETAIL_WIDTH + owner.FRAME_MARGIN + 8), owner.BOTTOM_MARGIN)
    grid:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background-Dark",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 12,
        insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    grid:SetBackdropColor(0, 0, 0, 1)
    f.gridFrame = grid

    f.gridLabel = grid:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    f.gridLabel:SetPoint("TOPLEFT", 8, -8)

    -- EQUIPPED SECTION
    f.equippedLabel = grid:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.equippedLabel:SetPoint("TOPLEFT", 8, -26)
    f.equippedLabel:SetText("|cffffd100Currently Equipped:|r")

    -- Equipped item rows (up to 2 for dual slots like Finger/Trinket)
    owner.equippedRows = {}
    for i = 1, 2 do
        local eRow = owner:CreateItemRow(grid, 0)
        -- Positions set dynamically in UpdateDisplay
        eRow:SetPoint("TOPLEFT", 8, -40 - (i-1) * owner.ITEM_ROW_HEIGHT)
        eRow:SetPoint("RIGHT", grid, "RIGHT", -8, 0)
        eRow:Hide()
        owner.equippedRows[i] = eRow
    end

    -- Divider between equipped and BiS (positioned dynamically)
    f.equippedDivider = grid:CreateTexture(nil, "ARTWORK")
    f.equippedDivider:SetSize(10, 2)
    f.equippedDivider:SetPoint("TOPLEFT", 8, -78)
    f.equippedDivider:SetPoint("RIGHT", grid, "RIGHT", -8, 0)
    f.equippedDivider:SetColorTexture(0.4, 0.4, 0.4, 0.5)

    f.bisLabel = grid:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.bisLabel:SetPoint("TOPLEFT", 8, -84)
    f.bisLabel:SetText("|cffffd100BiS Rankings:|r")

    -- BiS item rows (positioned dynamically in UpdateDisplay)
    owner.itemRows = {}
    for i = 1, owner.MAX_ITEMS do
        local row = owner:CreateItemRow(grid, i)
        row:SetPoint("TOPLEFT", 8, -100 - (i-1) * owner.ITEM_ROW_HEIGHT)
        row:SetPoint("RIGHT", grid, "RIGHT", -8, 0)
        row:Hide()
        owner.itemRows[i] = row
    end

    -- "No items" label
    f.noItemsLabel = grid:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    f.noItemsLabel:SetPoint("CENTER", 0, 20)
    f.noItemsLabel:SetText("|cff888888No items for this slot in current phase|r")
    f.noItemsLabel:Hide()

    -- Item count
    f.slotCountLabel = grid:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    f.slotCountLabel:SetPoint("TOPRIGHT", -8, -8)
end

-- ============================================================================
-- ITEM ROW — individual ranked item
-- ============================================================================

function Construction:CreateItemRow(owner, parent, index)
    local row = CreateFrame("Button", nil, parent)
    row:SetHeight(owner.ITEM_ROW_HEIGHT)

    local bg = row:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(0.1, 0.1, 0.12, 0.5)
    row.bg = bg
    row:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")

    -- Rank number (#1, #2, etc.)
    local rankNum = row:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    rankNum:SetPoint("LEFT", 6, 0)
    rankNum:SetWidth(28)
    rankNum:SetJustifyH("CENTER")
    row.rankNum = rankNum

    -- Item icon
    local icon = row:CreateTexture(nil, "ARTWORK")
    icon:SetSize(owner.ITEM_ROW_HEIGHT - 6, owner.ITEM_ROW_HEIGHT - 6)
    icon:SetPoint("LEFT", 36, 0)
    icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    row.icon = icon

    -- Item name (top line)
    local nameText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    nameText:SetPoint("TOPLEFT", icon, "TOPRIGHT", 8, -2)
    nameText:SetPoint("RIGHT", row, "RIGHT", -80, 0)
    nameText:SetJustifyH("LEFT")
    nameText:SetWordWrap(false)
    row.nameText = nameText

    -- Source line (bottom)
    local subText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    subText:SetPoint("BOTTOMLEFT", icon, "BOTTOMRIGHT", 8, 2)
    subText:SetPoint("RIGHT", row, "RIGHT", -80, 0)
    subText:SetJustifyH("LEFT")
    subText:SetWordWrap(false)
    row.subText = subText

    -- Rank label (right side, top)
    local rankLabel = row:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    rankLabel:SetPoint("TOPRIGHT", -6, -4)
    rankLabel:SetJustifyH("RIGHT")
    row.rankLabel = rankLabel

    -- Status (right side, bottom)
    local statusText = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    statusText:SetPoint("BOTTOMRIGHT", -6, 4)
    statusText:SetJustifyH("RIGHT")
    row.statusText = statusText

    -- Tooltip + detail panel on hover
    row:SetScript("OnEnter", function(widget)
        if widget.itemID then
            GameTooltip:SetOwner(widget, "ANCHOR_LEFT")
            GameTooltip:SetItemByID(widget.itemID)
            GameTooltip:Show()
            owner:ShowItemDetail(widget.itemID, widget._itemData)
        end
    end)
    row:SetScript("OnLeave", function() GameTooltip:Hide() end)

    return row
end

-- ============================================================================
-- DETAIL PANEL (right side)
-- ============================================================================

function Construction:CreateDetailPanel(owner, f)
    local panel = CreateFrame("Frame", nil, f, "BackdropTemplate")
    panel:SetWidth(owner.DETAIL_WIDTH)
    panel:SetPoint("TOPRIGHT", -owner.FRAME_MARGIN, owner.CONTENT_Y)
    panel:SetPoint("BOTTOMRIGHT", -owner.FRAME_MARGIN, owner.BOTTOM_MARGIN)
    panel:SetBackdrop({
        bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 12,
        insets = { left = 4, right = 4, top = 4, bottom = 4 }
    })
    f.detailPanel = panel

    local title = panel:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("TOP", 0, -8)
    title:SetText("|cff00ffffItem Details|r")

    local divider = panel:CreateTexture(nil, "ARTWORK")
    divider:SetSize(owner.DETAIL_WIDTH - 16, 2)
    divider:SetPoint("TOP", 0, -28)
    divider:SetColorTexture(0.5, 0.5, 0.5, 0.5)

    local scrollParent = CreateFrame("Frame", nil, panel)
    scrollParent:SetPoint("TOPLEFT", 6, -34)
    scrollParent:SetPoint("BOTTOMRIGHT", -24, 6)
    local scroll = CreateFrame("ScrollFrame", nil, scrollParent, "UIPanelScrollFrameTemplate")
    scroll:SetAllPoints()
    local content = CreateFrame("Frame", nil, scroll)
    content:SetWidth(owner.DETAIL_WIDTH - 40)
    content:SetHeight(1)
    scroll:SetScrollChild(content)
    f.detailContent = content
    owner.detailLines = {}
end

