--[[
============================================================
Decor Vendor Addon
© 2026 MidniteDestiny. All Rights Reserved.
============================================================

This file is part of the Decor Vendor addon.

All code, structure, and design are the intellectual
property of MidniteDestiny unless otherwise stated.

You may NOT:
• Copy, reproduce, or redistribute this code
• Modify and redistribute this code
• Use this code in other addons or projects

without explicit permission from the author.

This addon is distributed for personal use only.

============================================================
]]

local addonName, dv = ...

local C = dv.CONSTANTS

if not C then
    print("|cffff4040DecorVendor BossDropRows:|r constants are missing.")
    return
end


function dv.CreateBossDropHeader(parent, group, collected, total, y)
    dv.collapsedHeaders = dv.collapsedHeaders or {}

    local key = "boss_" .. group.name

    if dv.collapsedHeaders[key] == nil then
        dv.collapsedHeaders[key] = true
    end

    local collapsed = dv.collapsedHeaders[key]

    if dv.filtersJustChanged then
        local expSel = dv.filters.bossdrops.expansions

        if not expSel[group.expansion] then
            dv.collapsedHeaders[key] = true
            collapsed = true
        end
    end

    local collected = 0
    local total = 0

    for _, boss in ipairs(group.items or {}) do
        total = total + 1

        if dv.IsItemCollected(boss.id) then
            collected = collected + 1
        end
    end

    local header = CreateFrame("Button", nil, parent)
    header:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, y)
    header:SetPoint("RIGHT", parent, "RIGHT", -6, 0)
    header:SetHeight(C.VENDOR_HEADER_HEIGHT)

    local bg = header:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetTexture("Interface\\Buttons\\WHITE8x8")
    bg:SetGradient("HORIZONTAL",
        CreateColor(.15, .10, .25, .9),
        CreateColor(.05, .05, .15, .9)
    )

    header.icon = header:CreateFontString(nil, "OVERLAY")
    header.icon:SetFont(STANDARD_TEXT_FONT, 13)
    header.icon:SetPoint("LEFT", 10, 0)
    header.icon:SetText(dv.collapsedHeaders[key] and "+" or "-")

    header.text = header:CreateFontString(nil, "OVERLAY")
    header.text:SetFont(STANDARD_TEXT_FONT, 12,"OUTLINE")
    header.text:SetPoint("LEFT", 20, 0)
    header.text:SetText(group.name)

    header.progress = header:CreateFontString(nil, "OVERLAY")
    header.progress:SetFont(STANDARD_TEXT_FONT, 11,"OUTLINE")
    header.progress:SetPoint("RIGHT", -10, 0)
    header.progress:SetText(("%d/%d collected"):format(collected, total))

    if total > 0 and collected == total then
        header.progress:SetTextColor(0.2,1,0.2)
    elseif collected >= total/2 then
        header.progress:SetTextColor(unpack(C.COLORS.GOLD))
    else
        header.progress:SetTextColor(1,1,1)
    end

header:SetScript("OnClick", function()
    dv.ToggleAccordionHeader("bossdrops", key)
end)

    table.insert(dv.activeWidgets, header)

    return dv.collapsedHeaders[key], y - 26
end

function dv.UpdateBossPreview(itemData)
    if not itemData then return end

    local ms = dv.modelScene
    local actor = dv.previewActor
    local texture = dv.texture

    if not ms or not actor then return end

    dv.contentArea._isVendorPreview = false

    -- Title
    local itemObj = Item:CreateFromItemID(itemData.id)
    itemObj:ContinueOnItemLoad(function()
        if dv.modelTitle then
            dv.modelTitle:SetText(itemObj:GetItemName() or "Preview")
            dv.modelTitle:SetTextColor(1, 1, 1)
        end
    end)

    -- =========================
    -- MODEL LOGIC
    -- =========================
    if itemData.model3D then
        if texture then texture:Hide() end
        ms:Show()

        dv:ShowModel(ms, itemData.model3D)

        C_Timer.After(0.01, function()
            local camera = ms:GetActiveCamera()
            if not camera then return end

            local cam = dv.DecorCameraOverrides and dv.DecorCameraOverrides[itemData.model3D]

            if camera.TargetActor then
                camera:TargetActor(actor, true)
            end

            -- slight tilt for decor
            if camera.SetPitch then
                camera:SetPitch(0.2)
            end

            if cam and cam.zoom and camera.SetZoomDistance then
                camera:SetZoomDistance(cam.zoom)
            end
        end)
    else
        ms:Hide()
    end

    -- =========================
    -- BOSS NOTES
    -- Use one wrapping text block with a safe dynamic height.
    -- This prevents one-line ellipses and fixes wrapped locations.
    -- =========================

    if not dv.bossNotes then
        dv.bossNotes = CreateFrame("Frame", nil, dv.itemContainer)
        dv.bossNotes:SetFrameLevel((dv.itemContainer:GetFrameLevel() or 1) + 8)

        dv.bossNotes.bg = dv.bossNotes:CreateTexture(nil, "BACKGROUND")
        dv.bossNotes.bg:SetAllPoints()
        dv.bossNotes.bg:SetColorTexture(0.08, 0.08, 0.08, 0.75)

        dv.bossNotes.text = dv.bossNotes:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        dv.bossNotes.text:SetPoint("TOPLEFT", dv.bossNotes, "TOPLEFT", 10, -10)
        dv.bossNotes.text:SetPoint("BOTTOMRIGHT", dv.bossNotes, "BOTTOMRIGHT", -10, 10)
        dv.bossNotes.text:SetJustifyH("LEFT")
        dv.bossNotes.text:SetJustifyV("TOP")
        dv.bossNotes.text:SetWordWrap(true)
        dv.bossNotes.text:SetNonSpaceWrap(false)
        dv.bossNotes.text:SetFont(STANDARD_TEXT_FONT, 11, "")
    end

    local lines = {}

    if itemData.bossencounter then
        local encounterName = EJ_GetEncounterInfo(itemData.bossencounter)
        table.insert(lines, "|cffFFD200Boss:|r " .. (encounterName or "Unknown Boss"))
    end

    if itemData.instance or itemData.bossevent then
        local loc = itemData.instance or itemData.bossevent
        table.insert(lines, "|cff00fbffEvent:|r " .. tostring(loc))
    end

    if itemData.zone then
        table.insert(lines, "|cff00fbffLocation:|r " .. tostring(itemData.zone))
    end

    if itemData.note and itemData.note ~= "" then
        table.insert(lines, "|cff00ff00Note:|r " .. tostring(itemData.note))
    end

    if #lines == 0 then
        dv.bossNotes:Hide()
        return
    end

    local fullBossInfo = table.concat(lines, "\n")

    -- Rough height estimate that does not depend on GetStringHeight() behaving perfectly during the same frame.
    local plainText = fullBossInfo
        :gsub("|c%x%x%x%x%x%x%x%x", "")
        :gsub("|r", "")
        :gsub("|T.-|t", "")

    local estimatedLines = 0
    local charsPerLine = 36

    for line in string.gmatch(plainText .. "\n", "(.-)\n") do
        if line == "" then
            estimatedLines = estimatedLines + 1
        else
            estimatedLines = estimatedLines + math.max(1, math.ceil(string.len(line) / charsPerLine))
        end
    end

    local noteHeight = math.max(88, estimatedLines * 14 + 24)
    noteHeight = math.min(noteHeight, 210)

    dv.bossNotes:ClearAllPoints()
    dv.bossNotes:SetPoint("TOPLEFT", dv.modelTitle, "BOTTOMLEFT", 0, -8)
    dv.bossNotes:SetPoint("TOPRIGHT", dv.modelTitle, "BOTTOMRIGHT", 0, -8)
    dv.bossNotes:SetHeight(noteHeight)

    dv.bossNotes.text:SetText(fullBossInfo)
    dv.bossNotes:Show()
end

function dv.CreateBossDropLine(parent, itemData, y)
    local line = CreateFrame("Button", nil, parent)
    line:SetPoint("TOPLEFT", parent, "TOPLEFT", 10, y)
    line:SetPoint("RIGHT", parent, "RIGHT", -6, 0)
    line:SetHeight(C.LINE_HEIGHT)
    line:RegisterForClicks("AnyUp")

    -- 🔥 Status icon
	local icon = line:CreateTexture(nil, "OVERLAY")
	icon:SetSize(14, 14)
	icon:SetPoint("LEFT", 0, 0)

    -- Item name
    local nameFS = line:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    nameFS:SetPoint("LEFT", icon, "RIGHT", 4, 0) -- 🔥 shifted right

    local item = Item:CreateFromItemID(itemData.id)
    item:ContinueOnItemLoad(function()
        nameFS:SetText(item:GetItemName() or "Loading...")
    end)

	local isCollected = dv.IsItemCollected(itemData.id)

	if isCollected then
    icon:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
    icon:SetVertexColor(0.2, 1, 0.2) -- green
    icon:SetAlpha(0.9)
    nameFS:SetTextColor(0.2, 1, 0.2)
	else
    icon:SetTexture("Interface\\Buttons\\UI-GroupLoot-Pass-Up")
    icon:SetVertexColor(1, 0.2, 0.2) -- red
    icon:SetAlpha(0.85)
    nameFS:SetTextColor(1, 1, 1) -- keep text white for readability
	end

    -- Click logic (unchanged)
    line:SetScript("OnClick", function(_, button)
        if button == "LeftButton" then
            dv.UpdateBossPreview(itemData)

        elseif button == "RightButton" then
            if InCombatLockdown() then return end

            local rares = dv.rareEvents and dv.rareEvents[itemData.bossevent]

            if rares and #rares > 0 then
                if TomTom then
                    for _, rare in ipairs(rares) do
                        if rare.x and rare.y then
                            TomTom:AddWaypoint(
                                itemData.mapID,
                                rare.x / 100,
                                rare.y / 100,
                                { title = rare.name }
                            )
                        end
                    end
                else
                    local first = rares[1]
                    if first and first.x and first.y then
                        local waypoint = UiMapPoint.CreateFromCoordinates(
                            itemData.mapID,
                            first.x / 100,
                            first.y / 100
                        )
                        C_Map.SetUserWaypoint(waypoint)
                        C_SuperTrack.SetSuperTrackedUserWaypoint(true)
                    end
                end

                if itemData.mapID then
                    C_Map.OpenWorldMap(itemData.mapID)
                end

                return
            end

            if itemData.mapID then
                C_Map.OpenWorldMap(itemData.mapID)
            end
        end
    end)

    table.insert(dv.activeWidgets, line)
    return y - 24
end