local _, ns = ...
local L = ns.L or {}

local UIData = ns.UIData or {}
local THEME = UIData.THEME or {}
local STATUS_COLORS = UIData.STATUS_COLORS or {}

local UIJournalView = ns.UIJournalView or {}
local getRaidLootTrackerBadgeVisual = UIJournalView.GetRaidLootTrackerBadgeVisual or function()
    return nil
end

local UIRaidModeCard = {}
ns.UIRaidModeCard = UIRaidModeCard

local function createRaidModeSidebar(parent, helpers)
    local createLabel = helpers.createLabel
    local createMiniActionButton = helpers.createMiniActionButton
    local createSectionFrame = helpers.createSectionFrame
    local getRaidDifficultyLabel = helpers.getRaidDifficultyLabel
    local styleScrollFrame = helpers.styleScrollFrame

    local panel = CreateFrame("Frame", nil, parent)
    panel:SetAllPoints(parent)
    panel:Hide()

    panel.title = createLabel(panel, "GameFontNormalLarge", "LEFT")
    panel.title:SetPoint("TOPLEFT", 16, -16)
    panel.title:SetPoint("TOPRIGHT", -74, -16)
    panel.title:SetText(L.RAID_JOURNAL_LOOT or "Loot")

    local function hideFilterMenus()
        if panel.difficultyMenu then
            panel.difficultyMenu:Hide()
        end
        if panel.classMenu then
            panel.classMenu:Hide()
        end
    end

    panel.difficultyDropdown = createMiniActionButton(panel, "", 214)
    panel.difficultyDropdown:SetPoint("TOPLEFT", panel.title, "BOTTOMLEFT", 0, -26)
    panel.difficultyDropdown:SetHeight(26)
    panel.difficultyDropdown:SetScript("OnClick", function()
        local nextShown = not (panel.difficultyMenu and panel.difficultyMenu:IsShown())
        hideFilterMenus()
        if panel.difficultyMenu then
            panel.difficultyMenu:SetShown(nextShown)
        end
    end)

    panel.classDropdown = createMiniActionButton(panel, "", 214)
    panel.classDropdown:SetPoint("TOPLEFT", panel.difficultyDropdown, "BOTTOMLEFT", 0, -8)
    panel.classDropdown:SetHeight(26)
    panel.classDropdown:SetScript("OnClick", function()
        local nextShown = not (panel.classMenu and panel.classMenu:IsShown())
        hideFilterMenus()
        if panel.classMenu then
            panel.classMenu:SetShown(nextShown)
        end
    end)

    panel.difficultyMenu = createSectionFrame(panel, "cardInset")
    panel.difficultyMenu:SetPoint("TOPLEFT", panel.difficultyDropdown, "BOTTOMLEFT", 0, -4)
    panel.difficultyMenu:SetPoint("TOPRIGHT", panel.difficultyDropdown, "BOTTOMRIGHT", 0, -4)
    panel.difficultyMenu:SetHeight(112)
    panel.difficultyMenu:SetFrameLevel((panel:GetFrameLevel() or 1) + 30)
    panel.difficultyMenu:EnableMouse(true)
    panel.difficultyMenu:Hide()

    panel.difficultyMenuRows = {}
    for index = 1, 4 do
        local row = createMiniActionButton(panel.difficultyMenu, "", 202)
        row:SetPoint("TOPLEFT", 6, -6 - ((index - 1) * 25))
        row:SetPoint("TOPRIGHT", -6, -6 - ((index - 1) * 25))
        row:SetHeight(23)
        row:SetScript("OnClick", function(selfButton)
            local mainTabKey = ns.GetSelectedMainTab and ns:GetSelectedMainTab() or "raids"
            if ns.SetJournalDifficultyKey then
                ns:SetJournalDifficultyKey(mainTabKey, selfButton.difficultyKey)
            else
                ns:SetRaidJournalDifficultyKey(selfButton.difficultyKey)
            end
            hideFilterMenus()
        end)
        panel.difficultyMenuRows[index] = row
    end

    panel.classMenu = createSectionFrame(panel, "cardInset")
    panel.classMenu:SetPoint("TOPLEFT", panel.classDropdown, "BOTTOMLEFT", 0, -4)
    panel.classMenu:SetPoint("TOPRIGHT", panel.classDropdown, "BOTTOMRIGHT", 0, -4)
    panel.classMenu:SetHeight(62)
    panel.classMenu:SetFrameLevel((panel:GetFrameLevel() or 1) + 31)
    panel.classMenu:EnableMouse(true)
    panel.classMenu:Hide()

    panel.classMenuRows = {}
    for index = 1, 2 do
        local row = createMiniActionButton(panel.classMenu, "", 202)
        row:SetPoint("TOPLEFT", 6, -6 - ((index - 1) * 25))
        row:SetPoint("TOPRIGHT", -6, -6 - ((index - 1) * 25))
        row:SetHeight(23)
        row:SetScript("OnClick", function(selfButton)
            local mainTabKey = ns.GetSelectedMainTab and ns:GetSelectedMainTab() or "raids"
            if ns.SetJournalClassFilterKey then
                ns:SetJournalClassFilterKey(mainTabKey, selfButton.classFilterKey)
            else
                ns:SetRaidJournalClassFilterKey(selfButton.classFilterKey)
            end
            hideFilterMenus()
        end)
        panel.classMenuRows[index] = row
    end

    panel.subtitle = createLabel(panel, "GameFontHighlightSmall", "LEFT")
    panel.subtitle:SetPoint("TOPLEFT", panel.classDropdown, "BOTTOMLEFT", 0, -12)
    panel.subtitle:SetPoint("TOPRIGHT", -16, 0)
    panel.subtitle:SetWordWrap(true)
    panel.subtitle:SetText(L.RAID_JOURNAL_LOOT_INFO_PLAYER or "Boss loot for the active filters.")

    panel.context = createLabel(panel, "GameFontDisableSmall", "LEFT")
    panel.context:SetPoint("TOPLEFT", panel.subtitle, "BOTTOMLEFT", 0, -12)
    panel.context:SetPoint("TOPRIGHT", -16, 0)
    panel.context:SetWordWrap(true)
    panel.context:SetText("")

    panel.scroll = CreateFrame("ScrollFrame", nil, panel, "UIPanelScrollFrameTemplate")
    panel.scroll:SetPoint("TOPLEFT", panel.context, "BOTTOMLEFT", 0, -10)
    panel.scroll:SetPoint("BOTTOMRIGHT", -24, 16)

    panel.scrollChild = CreateFrame("Frame", nil, panel.scroll)
    panel.scrollChild:SetSize(214, 10)
    panel.scroll:SetScrollChild(panel.scrollChild)
    styleScrollFrame(panel.scroll)

    panel.empty = createLabel(panel.scrollChild, "GameFontDisable", "LEFT")
    panel.empty:SetPoint("TOPLEFT", 4, -4)
    panel.empty:SetPoint("TOPRIGHT", -4, -4)
    panel.empty:SetJustifyV("TOP")
    panel.empty:SetWordWrap(true)
    panel.empty:SetText(L.RAID_JOURNAL_LOOT_PENDING or "Loot hookup pending")

    panel.lootRows = {}
    return panel
end

local function createRaidModeCenter(parent, helpers)
    local createLabel = helpers.createLabel
    local createSectionFrame = helpers.createSectionFrame
    local styleScrollFrame = helpers.styleScrollFrame

    local card = CreateFrame("Frame", nil, parent)
    card:Hide()

    card.raidPanel = createSectionFrame(card, "cardInset")
    card.raidPanel:SetPoint("TOPLEFT", 14, -14)
    card.raidPanel:SetPoint("BOTTOMLEFT", 14, 14)
    card.raidPanel:SetWidth(252)

    card.raidPanel.title = createLabel(card.raidPanel, "GameFontNormalLarge", "LEFT")
    card.raidPanel.title:SetPoint("TOPLEFT", 14, -14)
    card.raidPanel.title:SetText(L.RAIDS or "Raids")

    card.raidPanel.subtitle = createLabel(card.raidPanel, "GameFontHighlightSmall", "LEFT")
    card.raidPanel.subtitle:SetPoint("TOPLEFT", card.raidPanel.title, "BOTTOMLEFT", 0, -6)
    card.raidPanel.subtitle:SetPoint("TOPRIGHT", -14, 0)
    card.raidPanel.subtitle:SetText(L.MAIN_TAB_RAIDS_MIDNIGHT or "Midnight")

    card.raidPanel.scroll = CreateFrame("ScrollFrame", nil, card.raidPanel, "UIPanelScrollFrameTemplate")
    card.raidPanel.scroll:SetPoint("TOPLEFT", card.raidPanel.subtitle, "BOTTOMLEFT", 0, -12)
    card.raidPanel.scroll:SetPoint("BOTTOMRIGHT", -24, 12)

    card.raidPanel.scrollChild = CreateFrame("Frame", nil, card.raidPanel.scroll)
    card.raidPanel.scrollChild:SetSize(210, 10)
    card.raidPanel.scroll:SetScrollChild(card.raidPanel.scrollChild)
    styleScrollFrame(card.raidPanel.scroll)
    card.raidRows = {}

    card.bossPanel = createSectionFrame(card, "cardInset")
    card.bossPanel:SetPoint("TOPLEFT", card.raidPanel, "TOPRIGHT", 12, 0)
    card.bossPanel:SetPoint("BOTTOMRIGHT", -14, 14)

    card.bossPanel.title = createLabel(card.bossPanel, "GameFontNormalLarge", "LEFT")
    card.bossPanel.title:SetPoint("TOPLEFT", 14, -14)
    card.bossPanel.title:SetText(L.RAID_JOURNAL_BOSSES or "Bosses")

    card.bossPanel.subtitle = createLabel(card.bossPanel, "GameFontHighlightSmall", "LEFT")
    card.bossPanel.subtitle:SetPoint("TOPLEFT", card.bossPanel.title, "BOTTOMLEFT", 0, -6)
    card.bossPanel.subtitle:SetPoint("TOPRIGHT", -14, 0)
    card.bossPanel.subtitle:SetWordWrap(true)
    card.bossPanel.subtitle:SetText(L.RAID_JOURNAL_BOSSLIST_SUBTITLE or "Select a raid first.")

    card.bossPanel.scroll = CreateFrame("ScrollFrame", nil, card.bossPanel, "UIPanelScrollFrameTemplate")
    card.bossPanel.scroll:SetPoint("TOPLEFT", card.bossPanel.subtitle, "BOTTOMLEFT", 0, -12)
    card.bossPanel.scroll:SetPoint("BOTTOMRIGHT", -24, 12)

    card.bossPanel.scrollChild = CreateFrame("Frame", nil, card.bossPanel.scroll)
    card.bossPanel.scrollChild:SetSize(350, 10)
    card.bossPanel.scroll:SetScrollChild(card.bossPanel.scrollChild)
    styleScrollFrame(card.bossPanel.scroll)
    card.bossRows = {}

    return card
end

local function createRaidModeUtility(parent, helpers)
    local createLabel = helpers.createLabel
    local createSectionFrame = helpers.createSectionFrame
    local createUtilityHeader = helpers.createUtilityHeader

    local panel = CreateFrame("Frame", nil, parent)
    panel:SetAllPoints(parent)
    panel:Hide()

    panel.title = createLabel(panel, "GameFontNormalLarge", "LEFT")
    panel.title:SetPoint("TOPLEFT", 16, -16)
    panel.title:SetText(L.RAID_JOURNAL_DETAILS or "Details")

    panel.subtitle = createLabel(panel, "GameFontHighlightSmall", "LEFT")
    panel.subtitle:SetPoint("TOPLEFT", panel.title, "BOTTOMLEFT", 0, -8)
    panel.subtitle:SetPoint("TOPRIGHT", -16, 0)
    panel.subtitle:SetWordWrap(true)
    panel.subtitle:SetText(L.RAID_JOURNAL_DETAILS_SUBTITLE or "Encounter notes and weekly context.")

    panel.summaryHeader = createUtilityHeader(panel, L.RAID_JOURNAL_STATUS_LABEL or "Overview")
    panel.summaryHeader:SetPoint("TOPLEFT", panel.subtitle, "BOTTOMLEFT", 0, -14)
    panel.summaryHeader:SetPoint("TOPRIGHT", -16, 0)

    panel.summaryPanel = createSectionFrame(panel, "cardInset")
    panel.summaryPanel:SetPoint("TOPLEFT", panel.summaryHeader, "BOTTOMLEFT", 0, -8)
    panel.summaryPanel:SetPoint("TOPRIGHT", panel.summaryHeader, "TOPRIGHT", 0, -8)
    panel.summaryPanel:SetHeight(148)

    panel.raidLabel = createLabel(panel.summaryPanel, "GameFontDisableSmall", "LEFT")
    panel.raidLabel:SetPoint("TOPLEFT", 14, -12)
    panel.raidLabel:SetText(L.RAIDS or "Raid")

    panel.raidValue = createLabel(panel.summaryPanel, "GameFontHighlightSmall", "RIGHT")
    panel.raidValue:SetPoint("TOPLEFT", 120, -12)
    panel.raidValue:SetPoint("TOPRIGHT", -14, -12)

    panel.progressLabel = createLabel(panel.summaryPanel, "GameFontDisableSmall", "LEFT")
    panel.progressLabel:SetPoint("TOPLEFT", panel.raidLabel, "BOTTOMLEFT", 0, -14)
    panel.progressLabel:SetText(L.RAID_JOURNAL_PROGRESS or "Progress")

    panel.progressValue = createLabel(panel.summaryPanel, "GameFontHighlightSmall", "RIGHT")
    panel.progressValue:SetPoint("TOPLEFT", 120, -38)
    panel.progressValue:SetPoint("TOPRIGHT", -14, -38)

    panel.statusLabel = createLabel(panel.summaryPanel, "GameFontDisableSmall", "LEFT")
    panel.statusLabel:SetPoint("TOPLEFT", panel.progressLabel, "BOTTOMLEFT", 0, -14)
    panel.statusLabel:SetText(L.RAID_JOURNAL_STATUS_LABEL or "Status")

    panel.statusValue = createLabel(panel.summaryPanel, "GameFontHighlightSmall", "RIGHT")
    panel.statusValue:SetPoint("TOPLEFT", 120, -64)
    panel.statusValue:SetPoint("TOPRIGHT", -14, -64)

    panel.filterLabel = createLabel(panel.summaryPanel, "GameFontDisableSmall", "LEFT")
    panel.filterLabel:SetPoint("TOPLEFT", panel.statusLabel, "BOTTOMLEFT", 0, -14)
    panel.filterLabel:SetText(L.RAID_JOURNAL_FILTERS or "Filters")

    panel.filterValue = createLabel(panel.summaryPanel, "GameFontHighlightSmall", "RIGHT")
    panel.filterValue:SetPoint("TOPLEFT", 120, -90)
    panel.filterValue:SetPoint("TOPRIGHT", -14, -90)

    panel.characterLabel = createLabel(panel.summaryPanel, "GameFontDisableSmall", "LEFT")
    panel.characterLabel:SetPoint("TOPLEFT", panel.filterLabel, "BOTTOMLEFT", 0, -14)
    panel.characterLabel:SetText(L.CHARACTER or "Character")

    panel.characterValue = createLabel(panel.summaryPanel, "GameFontHighlightSmall", "RIGHT")
    panel.characterValue:SetPoint("TOPLEFT", 120, -116)
    panel.characterValue:SetPoint("TOPRIGHT", -14, -116)

    panel.detailHeader = createUtilityHeader(panel, L.RAID_JOURNAL_DETAILS or "Boss details")
    panel.detailHeader:SetPoint("TOPLEFT", panel.summaryPanel, "BOTTOMLEFT", 0, -16)
    panel.detailHeader:SetPoint("TOPRIGHT", -16, 0)

    panel.detailPanel = createSectionFrame(panel, "cardInset")
    panel.detailPanel:SetPoint("TOPLEFT", panel.detailHeader, "BOTTOMLEFT", 0, -8)
    panel.detailPanel:SetPoint("BOTTOMRIGHT", -16, 16)

    panel.detailTitle = createLabel(panel.detailPanel, "GameFontHighlight", "LEFT")
    panel.detailTitle:SetPoint("TOPLEFT", 14, -12)
    panel.detailTitle:SetPoint("TOPRIGHT", -14, -12)

    panel.detailStatus = createLabel(panel.detailPanel, "GameFontDisableSmall", "LEFT")
    panel.detailStatus:SetPoint("TOPLEFT", panel.detailTitle, "BOTTOMLEFT", 0, -8)
    panel.detailStatus:SetPoint("TOPRIGHT", -14, 0)
    panel.detailStatus:SetWordWrap(true)

    panel.detailText = createLabel(panel.detailPanel, "GameFontHighlightSmall", "LEFT")
    panel.detailText:SetPoint("TOPLEFT", panel.detailStatus, "BOTTOMLEFT", 0, -12)
    panel.detailText:SetPoint("BOTTOMRIGHT", -14, 14)
    panel.detailText:SetJustifyV("TOP")
    panel.detailText:SetWordWrap(true)

    return panel
end

local function applyRaidSelectionRow(button, titleText, metaText, statusText, statusColor, isSelected, trackerSummary, iconTexture)
    statusColor = statusColor or STATUS_COLORS.missing
    button.title:SetText(titleText or (L.UNKNOWN or "Unknown"))
    button.title:SetTextColor(THEME.parchment[1], THEME.parchment[2], THEME.parchment[3])
    button.meta:SetText(metaText or "")
    button.status:SetText(statusText or "")
    button.status:SetTextColor(statusColor[1], statusColor[2], statusColor[3])
    button.statusLine:SetColorTexture(statusColor[1], statusColor[2], statusColor[3], 1)
    button.selection:SetShown(isSelected)
    button.fill:SetColorTexture(
        (isSelected and THEME.selected[1]) or THEME.metalInset[1],
        (isSelected and THEME.selected[2]) or THEME.metalInset[2],
        (isSelected and THEME.selected[3]) or THEME.metalInset[3],
        isSelected and 0.07 or 0.03
    )
    if button.SetBackdropBorderColor then
        if isSelected then
            button:SetBackdropBorderColor(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.78)
        else
            button:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.36)
        end
    end

    if button.icon then
        local texturePath = iconTexture or "Interface\\Icons\\INV_Misc_QuestionMark"
        if button.squareMode then
            if button.iconBackplate then
                button.iconBackplate:Hide()
            end
            if button.icon then
                button.icon:Hide()
            end
            if button.iconRing then
                button.iconRing:Hide()
            end
            if button.squareIconFrame then
                button.squareIconFrame:Show()
            end
            if button.squareIcon then
                button.squareIcon:SetTexture(texturePath)
            end
        else
            if button.squareIconFrame then
                button.squareIconFrame:Hide()
            end
            if button.iconBackplate then
                button.iconBackplate:Show()
            end
            if button.icon then
                button.icon:Show()
                button.icon:SetTexture(texturePath)
            end
            if button.iconRing then
                button.iconRing:Show()
            end
        end
    end

    button.trackerSummary = trackerSummary
    if trackerSummary then
        local badgeTexture = getRaidLootTrackerBadgeVisual(trackerSummary)
        if badgeTexture then
            button.trackBadge:SetTexture(badgeTexture)
            button.trackBadge:Show()
        else
            button.trackBadge:Hide()
        end
    else
        button.trackBadge:Hide()
    end
end

local function ensureRaidModeRaidRows(ui, count, helpers)
    while #ui.frame.raidModeCenter.raidRows < count do
        local button = helpers.createRaidJournalRowButton(ui.frame.raidModeCenter.raidPanel.scrollChild)
        button.squareMode = false
        button.icon:SetSize(32, 32)
        button.icon:SetPoint("CENTER", button.iconBackplate, "CENTER", 0, 0)
        button.icon:SetTexCoord(0.28, 0.72, 0.28, 0.72)
        local index = #ui.frame.raidModeCenter.raidRows + 1
        button:SetPoint("TOPLEFT", 0, -((index - 1) * 58))
        button:SetPoint("TOPRIGHT", 0, -((index - 1) * 58))
        button:SetScript("OnClick", function(selfButton)
            if selfButton.raidKey then
                if ns.SetJournalSelection then
                    ns:SetJournalSelection(selfButton.journalMainTab or (ns.GetSelectedMainTab and ns:GetSelectedMainTab()) or "raids", selfButton.raidKey, selfButton.defaultBossKey or "")
                else
                    ns:SetRaidJournalSelection(selfButton.raidKey, selfButton.defaultBossKey or "")
                end
            end
        end)
        ui.frame.raidModeCenter.raidRows[index] = button
    end
end

local function ensureRaidModeBossRows(ui, count, helpers)
    while #ui.frame.raidModeCenter.bossRows < count do
        local button = helpers.createRaidJournalRowButton(ui.frame.raidModeCenter.bossPanel.scrollChild)
        button.squareMode = false
        button.icon:SetSize(30, 30)
        button.icon:SetPoint("CENTER", button.iconBackplate, "CENTER", 1, 0)
        button.icon:SetTexCoord(0.10, 0.90, 0.10, 0.90)
        local index = #ui.frame.raidModeCenter.bossRows + 1
        button:SetPoint("TOPLEFT", 0, -((index - 1) * 58))
        button:SetPoint("TOPRIGHT", 0, -((index - 1) * 58))
        button:SetScript("OnClick", function(selfButton)
            if selfButton.raidKey and selfButton.bossKey then
                if ns.SetJournalSelection then
                    ns:SetJournalSelection(selfButton.journalMainTab or (ns.GetSelectedMainTab and ns:GetSelectedMainTab()) or "raids", selfButton.raidKey, selfButton.bossKey)
                else
                    ns:SetRaidJournalSelection(selfButton.raidKey, selfButton.bossKey)
                end
            end
        end)
        ui.frame.raidModeCenter.bossRows[index] = button
    end
end

local function ensureRaidModeLootRows(ui, count, helpers)
    while #ui.frame.raidModeSidebar.lootRows < count do
        local row = helpers.createRaidJournalLootRow(ui.frame.raidModeSidebar.scrollChild)
        local index = #ui.frame.raidModeSidebar.lootRows + 1
        row:SetPoint("TOPLEFT", 0, -((index - 1) * 64))
        row:SetPoint("TOPRIGHT", 0, -((index - 1) * 64))
        ui.frame.raidModeSidebar.lootRows[index] = row
    end
end

local function refreshRaidMode(ui, character, view, helpers)
    if not ui.frame or not ui.frame.raidModeSidebar or not ui.frame.raidModeCenter or not ui.frame.raidModeUtility then
        return
    end

    local sidebar = ui.frame.raidModeSidebar
    local center = ui.frame.raidModeCenter
    local utility = ui.frame.raidModeUtility
    local raids = view.raids or {}
    local selectedRaidKey = view.selectedRaidKey
    local selectedBossKey = view.selectedBossKey
    local journalMainTab = view.mainTabKey or "raids"
    local difficultyOptions = view.difficultyOptions or helpers.getJournalDifficultyOptions(journalMainTab)
    local isDungeonJournal = journalMainTab == "dungeons"
    local usesDailyDungeonCounter = isDungeonJournal and helpers.usesDungeonDailyCounter(view.difficultyKey)

    center.raidPanel.title:SetText(view.primaryLabelPlural or (L.RAIDS or "Raids"))
    center.raidPanel.subtitle:SetText(view.listSubtitle or (L.RAID_JOURNAL_MIDNIGHT_SUBTITLE or "Choose a Midnight raid."))
    center.bossPanel.title:SetText(view.bossesLabel or (L.RAID_JOURNAL_BOSSES or "Bosses"))
    utility.raidLabel:SetText(view.primaryLabel or view.primaryLabelPlural or (L.RAIDS or "Raid"))

    local difficultyLabel = helpers.getRaidDifficultyLabel(view.difficultyKey, journalMainTab)
    if sidebar.difficultyDropdown and sidebar.difficultyDropdown.label then
        sidebar.difficultyDropdown.label:SetText(string.format(L.RAID_JOURNAL_DIFFICULTY_FILTER or "Difficulty: %s", difficultyLabel))
        sidebar.difficultyDropdown.label:SetTextColor(THEME.gold[1], THEME.gold[2], THEME.gold[3])
        helpers.setMiniActionButtonActive(sidebar.difficultyDropdown, true)
    end
    for index, button in ipairs(sidebar.difficultyMenuRows or {}) do
        local option = difficultyOptions[index]
        if option then
            button.difficultyKey = option.key
            button.label:SetText(option.label())
            button:Show()
            helpers.setMiniActionButtonActive(button, button.difficultyKey == view.difficultyKey)
        else
            button:Hide()
        end
    end
    if sidebar.difficultyMenu then
        sidebar.difficultyMenu:SetHeight(math.max(37, (#difficultyOptions * 25) + 12))
    end

    local classLabel = view.classFilterMode == "all"
        and (L.RAID_JOURNAL_ALL_CLASSES or "All classes")
        or ((character and character.className) or (L.UNKNOWN or "Unknown"))
    if sidebar.classDropdown and sidebar.classDropdown.label then
        sidebar.classDropdown.label:SetText(string.format(L.RAID_JOURNAL_CLASS_FILTER or "Class: %s", classLabel))
        sidebar.classDropdown.label:SetTextColor(THEME.gold[1], THEME.gold[2], THEME.gold[3])
        helpers.setMiniActionButtonActive(sidebar.classDropdown, view.classFilterMode ~= "all")
    end
    local classOptions = {
        { key = "player", label = (character and character.className) or (L.UNKNOWN or "Unknown") },
        { key = "all", label = L.RAID_JOURNAL_ALL_CLASSES or "All classes" },
    }
    for index, button in ipairs(sidebar.classMenuRows or {}) do
        local option = classOptions[index]
        if option then
            button.classFilterKey = option.key
            button.label:SetText(option.label)
            button:Show()
            helpers.setMiniActionButtonActive(button, option.key == view.classFilterKey)
        else
            button:Hide()
        end
    end

    if view.selectedBoss then
        sidebar.subtitle:SetText(string.format(
            L.RAID_JOURNAL_LOOT_PANEL_SUBTITLE or "%s loot for %s",
            view.selectedBoss.name or (L.UNKNOWN or "Unknown"),
            helpers.getRaidDifficultyLabel(view.difficultyKey, journalMainTab)
        ))
    else
        sidebar.subtitle:SetText(L.RAID_JOURNAL_LOOT_INFO_PLAYER or "Boss loot for the active filters.")
    end

    sidebar.context:SetText(string.format(
        L.RAID_JOURNAL_LOOT_CONTEXT or "%d items for %s",
        #(view.loot or {}),
        view.selectedRaid and view.selectedRaid.name or (view.primaryLabelPlural or (L.RAIDS or "Raids"))
    ))

    ensureRaidModeLootRows(ui, #(view.loot or {}), helpers)
    for index, row in ipairs(sidebar.lootRows or {}) do
        local loot = view.loot and view.loot[index]
        if not loot then
            row:Hide()
        else
            row:Show()
            row.characterKey = character and character.key or nil
            row.characterName = character and character.name or nil
            row.difficultyKey = view.difficultyKey
            helpers.applyRaidLootRow(row, loot)
        end
    end
    sidebar.scrollChild:SetHeight(math.max(10, #(view.loot or {}) * 64))
    sidebar.empty:SetShown(#(view.loot or {}) == 0)

    ensureRaidModeRaidRows(ui, #raids, helpers)
    for index, button in ipairs(center.raidRows or {}) do
        local raid = raids[index]
        if not raid then
            button:Hide()
        else
            local stateColor
            local raidStatusText
            if isDungeonJournal and not usesDailyDungeonCounter then
                stateColor = STATUS_COLORS.open
                raidStatusText = L.DUNGEON_JOURNAL_REPEATABLE or "Repeatable"
            else
                stateColor = (raid.totalCount > 0 and raid.killedCount >= raid.totalCount) and STATUS_COLORS.complete
                    or (raid.killedCount > 0 and STATUS_COLORS.turnin)
                    or STATUS_COLORS.open
                raidStatusText = raid.progressText or "--"
            end
            button:Show()
            button.raidKey = raid.key
            button.defaultBossKey = raid.bosses and raid.bosses[1] and raid.bosses[1].key or ""
            button.journalMainTab = journalMainTab
            applyRaidSelectionRow(
                button,
                raid.name,
                "",
                raidStatusText,
                stateColor,
                raid.key == selectedRaidKey,
                raid.trackerSummary,
                raid.icon
            )
        end
    end
    center.raidPanel.scrollChild:SetHeight(math.max(10, #raids * 58))

    local bosses = (view.selectedRaid and view.selectedRaid.bosses) or {}
    ensureRaidModeBossRows(ui, #bosses, helpers)
    for index, button in ipairs(center.bossRows or {}) do
        local boss = bosses[index]
        if not boss then
            button:Hide()
        else
            local statusText
            local stateColor
            if isDungeonJournal and not usesDailyDungeonCounter then
                statusText = L.DUNGEON_JOURNAL_REPEATABLE or "Repeatable"
                stateColor = STATUS_COLORS.open
            elseif isDungeonJournal and boss.status == "complete" then
                statusText = L.DUNGEON_JOURNAL_STATUS_KILLED or "Completed today"
                stateColor = STATUS_COLORS.complete
            elseif isDungeonJournal and boss.status == "open" then
                statusText = L.DUNGEON_JOURNAL_STATUS_OPEN or "Open today"
                stateColor = STATUS_COLORS.open
            elseif boss.status == "complete" then
                statusText = L.STATUS_DONE or "Done"
                stateColor = STATUS_COLORS.complete
            elseif boss.status == "open" then
                statusText = L.PVE_WEEKLY_OPEN or "Open"
                stateColor = STATUS_COLORS.open
            else
                statusText = L.UNKNOWN or "Unknown"
                stateColor = STATUS_COLORS[boss.status or "missing"] or STATUS_COLORS.missing
            end
            button:Show()
            button.raidKey = view.selectedRaidKey
            button.bossKey = boss.key
            button.journalMainTab = journalMainTab
            applyRaidSelectionRow(
                button,
                boss.name,
                (type(boss.description) == "string" and boss.description ~= "" and boss.description)
                    or (view.selectedRaid and view.selectedRaid.subtitle)
                    or (L.RAID_JOURNAL_SOURCE_EJ or "Encounter Journal"),
                statusText,
                stateColor,
                boss.key == selectedBossKey,
                boss.trackerSummary,
                boss.icon
            )
        end
    end
    center.bossPanel.scrollChild:SetHeight(math.max(10, #bosses * 58))
    if isDungeonJournal and not usesDailyDungeonCounter then
        center.bossPanel.subtitle:SetText(L.DUNGEON_JOURNAL_REPEATABLE_SUBTITLE or "This difficulty is repeatable and has no lockout counter.")
    elseif view.selectedRaid and view.selectedRaid.progressText then
        center.bossPanel.subtitle:SetText(string.format(
            (isDungeonJournal and (L.DUNGEON_JOURNAL_BOSS_PROGRESS or "Today's progress: %s"))
                or (L.RAID_JOURNAL_BOSS_PROGRESS or "Weekly progress: %s"),
            view.selectedRaid.progressText
        ))
    else
        center.bossPanel.subtitle:SetText(L.RAID_JOURNAL_BOSSLIST_SUBTITLE or "Choose a boss.")
    end

    local selectedBoss = view.selectedBoss
    local statusText
    if isDungeonJournal and not usesDailyDungeonCounter then
        statusText = L.DUNGEON_JOURNAL_REPEATABLE or "Repeatable"
    elseif isDungeonJournal and selectedBoss and selectedBoss.status == "complete" then
        statusText = L.DUNGEON_JOURNAL_STATUS_KILLED or "Completed today"
    elseif isDungeonJournal and selectedBoss and selectedBoss.status == "open" then
        statusText = L.DUNGEON_JOURNAL_STATUS_OPEN or "Open today"
    elseif selectedBoss and selectedBoss.status == "complete" then
        statusText = L.RAID_JOURNAL_STATUS_KILLED or "Killed this week"
    elseif selectedBoss and selectedBoss.status == "open" then
        statusText = ns:IsCurrentCharacterKey(character and character.key) and (L.RAID_JOURNAL_STATUS_OPEN or "Still open this week")
            or (L.RAID_JOURNAL_STATUS_ALT_PENDING or "Alt snapshots will come in a later pass")
    else
        statusText = L.RAID_JOURNAL_STATUS_PENDING or "Live sync pending"
    end

    utility.raidValue:SetText(view.selectedRaid and view.selectedRaid.name or (view.primaryLabelPlural or (L.RAIDS or "Raids")))
    utility.progressValue:SetText(
        (isDungeonJournal and not usesDailyDungeonCounter and (L.DUNGEON_JOURNAL_REPEATABLE or "Repeatable"))
            or ((view.selectedRaid and view.selectedRaid.progressText) or "--")
    )
    utility.statusValue:SetText(statusText)
    local statusColor = selectedBoss and (STATUS_COLORS[selectedBoss.status or "missing"] or STATUS_COLORS.missing) or STATUS_COLORS.missing
    utility.statusValue:SetTextColor(statusColor[1], statusColor[2], statusColor[3])
    utility.filterValue:SetText(string.format(
        "%s  |  %s",
        helpers.getRaidDifficultyLabel(view.difficultyKey, journalMainTab),
        view.classFilterName or (L.RAID_JOURNAL_ALL_CLASSES or "All classes")
    ))
    utility.characterValue:SetText(character and string.format("%s-%s", character.name or (L.UNKNOWN or "Unknown"), character.realm or (L.UNKNOWN or "Unknown")) or (L.UNKNOWN or "Unknown"))

    utility.detailTitle:SetText(selectedBoss and (selectedBoss.name or (L.UNKNOWN or "Unknown")) or (L.RAID_JOURNAL_DETAILS or "Details"))
    utility.detailStatus:SetText(string.format(
        L.RAID_JOURNAL_STATUS_FORMAT or "%s  |  %s",
        view.selectedRaid and view.selectedRaid.name or (view.primaryLabelPlural or (L.RAIDS or "Raids")),
        statusText
    ))
    utility.detailText:SetText(
        (selectedBoss and type(selectedBoss.description) == "string" and selectedBoss.description ~= "" and selectedBoss.description)
            or ((not selectedBoss) and view.selectedRaid and view.selectedRaid.description)
            or (L.RAID_JOURNAL_DETAILS_SUBTITLE or "Select a boss to inspect its details.")
    )
end

UIRaidModeCard.CreateModeSidebar = createRaidModeSidebar
UIRaidModeCard.CreateModeCenter = createRaidModeCenter
UIRaidModeCard.CreateModeUtility = createRaidModeUtility
UIRaidModeCard.EnsureRaidRows = ensureRaidModeRaidRows
UIRaidModeCard.EnsureBossRows = ensureRaidModeBossRows
UIRaidModeCard.EnsureLootRows = ensureRaidModeLootRows
UIRaidModeCard.Refresh = refreshRaidMode
