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

local PveRaresView = {}
ns.UIPveRaresView = PveRaresView

local BACKDROP_TEMPLATE = BackdropTemplateMixin and "BackdropTemplate" or nil

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

local ROW_HEIGHT = 34
local ROW_GAP = 7
local ZONE_PANEL_WIDTH = 180

local function callHelper(helpers, name, ...)
    local fn = helpers and helpers[name]
    if type(fn) == "function" then
        return fn(...)
    end
    return nil
end

local function createLabel(parent, fontObject, justify)
    local text = parent:CreateFontString(nil, "OVERLAY", fontObject)
    text:SetJustifyH(justify or "LEFT")
    text:SetJustifyV("MIDDLE")
    return text
end

local function setTextureColor(texture, color, alpha)
    if not texture or type(color) ~= "table" then
        return
    end
    texture:SetVertexColor(color[1], color[2], color[3], alpha == nil and 1 or alpha)
end

local function getStatusColor(status)
    return STATUS_COLORS[status] or STATUS_COLORS.open or { 0.78, 0.70, 0.42 }
end

local function getStatusBadge(status)
    if status == "complete" then
        return PREMIUM.statusBadgeComplete
    end
    if status == "missing" then
        return PREMIUM.statusBadgeMissing
    end
    return PREMIUM.statusBadgeOpen
end

local function createSectionFrame(parent, helpers, variant)
    return callHelper(helpers, "createSectionFrame", parent, variant) or CreateFrame("Frame", nil, parent, BACKDROP_TEMPLATE)
end

local function createMiniActionButton(parent, helpers, text, width)
    return callHelper(helpers, "createMiniActionButton", parent, text, width) or CreateFrame("Button", nil, parent, BACKDROP_TEMPLATE)
end

local function setMiniActionButtonActive(button, active, helpers)
    if helpers and type(helpers.setMiniActionButtonActive) == "function" then
        helpers.setMiniActionButtonActive(button, active)
        return
    end
    if button then
        button:SetAlpha(active and 1 or 0.75)
    end
end

local function setButtonText(button, text, minWidth, maxWidth)
    if not button then
        return
    end
    if button.SetButtonText then
        button:SetButtonText(text or "", minWidth, maxWidth)
    elseif button.label then
        button.label:SetText(text or "")
    elseif button.SetText then
        button:SetText(text or "")
    end
end

local function getRareDisplayName(rare)
    if type(rare) ~= "table" then
        return ""
    end

    local fallback = rare.name or rare.label or ""
    if ns.GetLocalizedMidnightRareName then
        return ns:GetLocalizedMidnightRareName(rare.npcID, fallback)
    end

    return fallback
end

local function getZoneDisplayName(zone)
    if type(zone) ~= "table" then
        return ""
    end

    local fallback = zone.label or zone.key or ""
    if ns.GetLocalizedMidnightRareZoneName then
        return ns:GetLocalizedMidnightRareZoneName(zone.mapID, fallback)
    end

    return fallback
end

local function shouldShowRareTooltipLine(line)
    if type(line) ~= "string" or line == "" then
        return false
    end

    local lower = line:lower()
    if lower:match("^quest%s*id%s*:%s*%d+")
        or lower:match("^quest%-id%s*:%s*%d+")
        or lower:match("^id de quete%s*:%s*%d+")
        or lower:match("^id de mision%s*:%s*%d+")
    then
        return false
    end

    return true
end

local function createRareRow(parent, helpers)
    local row = CreateFrame("Button", nil, parent, BACKDROP_TEMPLATE)
    row:SetHeight(ROW_HEIGHT)
    row:RegisterForClicks("LeftButtonUp")

    if row.SetBackdrop then
        row:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8X8",
            edgeFile = "Interface\\Buttons\\WHITE8X8",
            tile = false,
            edgeSize = 1,
            insets = { left = 1, right = 1, top = 1, bottom = 1 },
        })
        row:SetBackdropColor(THEME.metalDeep[1], THEME.metalDeep[2], THEME.metalDeep[3], 0.94)
        row:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.34)
    end

    row.bg = row:CreateTexture(nil, "BACKGROUND")
    row.bg:SetAllPoints()
    row.bg:SetTexture(PREMIUM.row)
    row.bg:SetTexCoord(0.022, 0.978, 0, 1)
    setTextureColor(row.bg, { 1, 1, 1 }, 0.98)

    row.hover = row:CreateTexture(nil, "BACKGROUND", nil, 1)
    row.hover:SetAllPoints()
    row.hover:SetTexture("Interface\\Buttons\\WHITE8X8")
    row.hover:SetColorTexture(THEME.gold[1], THEME.gold[2], THEME.gold[3], 0.10)
    row.hover:SetAlpha(0)

    row.statusLine = row:CreateTexture(nil, "ARTWORK")
    row.statusLine:SetPoint("TOPLEFT", 4, -4)
    row.statusLine:SetPoint("BOTTOMLEFT", 4, 4)
    row.statusLine:SetWidth(2)

    row.badge = row:CreateTexture(nil, "ARTWORK")
    row.badge:SetSize(22, 22)
    row.badge:SetPoint("LEFT", 13, 0)

    row.name = createLabel(row, "GameFontHighlightSmall", "LEFT")
    row.name:SetPoint("LEFT", row.badge, "RIGHT", 10, 0)
    if row.name.SetWordWrap then
        row.name:SetWordWrap(false)
    end
    if row.name.SetMaxLines then
        row.name:SetMaxLines(1)
    end

    row.status = createLabel(row, "GameFontDisableSmall", "RIGHT")
    row.status:SetPoint("RIGHT", -14, 0)
    row.status:SetWidth(82)
    row.name:SetPoint("RIGHT", row.status, "LEFT", -12, 0)

    row:SetScript("OnEnter", function(self)
        self.hover:SetAlpha(1)
        local rare = self.rare
        if type(rare) == "table" then
            GameTooltip:SetOwner(self, "ANCHOR_CURSOR_RIGHT")
            GameTooltip:AddLine(getRareDisplayName(rare), THEME.gold[1], THEME.gold[2], THEME.gold[3], true)
            for _, line in ipairs(rare.tooltipLines or {}) do
                if shouldShowRareTooltipLine(line) then
                    GameTooltip:AddLine(line, 0.88, 0.88, 0.86, true)
                end
            end
            GameTooltip:Show()
        end
    end)
    row:SetScript("OnLeave", function(self)
        self.hover:SetAlpha(0)
        GameTooltip:Hide()
    end)

    return row
end

local function createMountSlot(parent)
    local slot = CreateFrame("Button", nil, parent, BACKDROP_TEMPLATE)
    slot:SetHeight(46)

    if slot.SetBackdrop then
        slot:SetBackdrop({
            bgFile = "Interface\\Buttons\\WHITE8X8",
            edgeFile = "Interface\\Buttons\\WHITE8X8",
            tile = false,
            edgeSize = 1,
            insets = { left = 1, right = 1, top = 1, bottom = 1 },
        })
        slot:SetBackdropColor(THEME.metalDeep[1], THEME.metalDeep[2], THEME.metalDeep[3], 0.80)
        slot:SetBackdropBorderColor(THEME.goldDim[1], THEME.goldDim[2], THEME.goldDim[3], 0.34)
    end

    slot.icon = slot:CreateTexture(nil, "ARTWORK")
    slot.icon:SetSize(30, 30)
    slot.icon:SetPoint("LEFT", 10, 0)
    slot.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    slot.name = createLabel(slot, "GameFontHighlightSmall", "LEFT")
    slot.name:SetPoint("LEFT", slot.icon, "RIGHT", 8, 7)
    slot.name:SetPoint("RIGHT", -12, 7)
    if slot.name.SetWordWrap then
        slot.name:SetWordWrap(false)
    end
    if slot.name.SetMaxLines then
        slot.name:SetMaxLines(1)
    end

    slot.status = createLabel(slot, "GameFontDisableSmall", "LEFT")
    slot.status:SetPoint("LEFT", slot.icon, "RIGHT", 8, -10)
    slot.status:SetPoint("RIGHT", -12, -10)

    slot:SetScript("OnEnter", function(self)
        local mount = self.mount
        if type(mount) ~= "table" then
            return
        end

        GameTooltip:SetOwner(self, "ANCHOR_CURSOR_RIGHT")
        local usedItemTooltip = false
        if mount.itemID and GameTooltip.SetItemByID then
            usedItemTooltip = pcall(GameTooltip.SetItemByID, GameTooltip, mount.itemID) == true
        end
        if not usedItemTooltip then
            GameTooltip:AddLine(mount.name or "", THEME.gold[1], THEME.gold[2], THEME.gold[3], true)
            GameTooltip:AddLine(mount.text or "", 0.86, 0.86, 0.82, true)
        end
        GameTooltip:Show()
    end)
    slot:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)

    return slot
end

local function ensureRareRows(card, count, helpers)
    card.rareRows = card.rareRows or {}
    while #card.rareRows < count do
        local row = createRareRow(card.scrollChild, helpers)
        local index = #card.rareRows + 1
        if index == 1 then
            row:SetPoint("TOPLEFT", card.scrollChild, "TOPLEFT", 0, 0)
            row:SetPoint("TOPRIGHT", card.scrollChild, "TOPRIGHT", 0, 0)
        else
            row:SetPoint("TOPLEFT", card.rareRows[index - 1], "BOTTOMLEFT", 0, -ROW_GAP)
            row:SetPoint("TOPRIGHT", card.rareRows[index - 1], "BOTTOMRIGHT", 0, -ROW_GAP)
        end
        card.rareRows[index] = row
    end
end

local function refreshMountSlots(card, mounts)
    mounts = type(mounts) == "table" and mounts or {}
    for index = 1, 2 do
        local slot = card.mountSlots[index]
        local mount = mounts[index]
        if slot and mount then
            local color = getStatusColor(mount.status)
            slot.mount = mount
            slot.icon:SetTexture(mount.icon or "Interface\\Icons\\INV_Misc_QuestionMark")
            slot.name:SetText(mount.name or "")
            slot.status:SetText(mount.text or "")
            slot.status:SetTextColor(color[1], color[2], color[3], 1)
            slot:Show()
        elseif slot then
            slot.mount = nil
            slot:Hide()
        end
    end
end

local function refreshRareRows(card, rares)
    rares = type(rares) == "table" and rares or {}
    ensureRareRows(card, #rares, card.helpers)

    for index, row in ipairs(card.rareRows or {}) do
        local rare = rares[index]
        if rare then
            local color = getStatusColor(rare.status)
            row.rare = rare
            row.name:SetText(getRareDisplayName(rare))
            row.status:SetText(rare.text or "")
            row.status:SetTextColor(color[1], color[2], color[3], 1)
            row.statusLine:SetColorTexture(color[1], color[2], color[3], 0.95)
            row.badge:SetTexture(getStatusBadge(rare.status))
            row.badge:SetVertexColor(1, 1, 1, 1)
            row:SetScript("OnClick", function()
                if ns.SetMidnightRareWaypoint then
                    ns:SetMidnightRareWaypoint(rare)
                end
            end)
            row:Show()
        else
            row.rare = nil
            row:SetScript("OnClick", nil)
            row:Hide()
        end
    end

    local totalHeight = math.max(10, (#rares * ROW_HEIGHT) + (math.max(0, #rares - 1) * ROW_GAP))
    card.scrollChild:SetSize(math.max(10, card.scroll:GetWidth() or 10), totalHeight)
    if card.scroll.UpdateScrollChildRect then
        card.scroll:UpdateScrollChildRect()
    end
end

local function refreshZoneButtons(card, view, helpers)
    local zones = view.zones or {}
    for index, button in ipairs(card.zoneButtons or {}) do
        local zone = zones[index]
        if zone then
            button.zoneKey = zone.key
            setButtonText(button, string.format("%s  %s", getZoneDisplayName(zone), zone.text or "0/0"), 142, 168)
            setMiniActionButtonActive(button, zone.key == view.selectedZoneKey, helpers)
            button:SetScript("OnClick", function(selfButton)
                if ns.SetSelectedMidnightRareZoneKey and ns:SetSelectedMidnightRareZoneKey(selfButton.zoneKey) then
                    PveRaresView.RefreshCard(card.ui, nil, card.helpers)
                end
            end)
            button:Show()
        else
            button.zoneKey = nil
            button:Hide()
        end
    end
end

function PveRaresView.CreateCard(parent, helpers)
    helpers = helpers or {}
    local card = createSectionFrame(parent, helpers, "card")
    card.helpers = helpers
    card:Hide()

    card.summary1 = createLabel(card, "GameFontHighlightSmall", "LEFT")
    card.summary1:SetPoint("TOPLEFT", 14, -14)

    card.summary2 = createLabel(card, "GameFontHighlightSmall", "LEFT")
    card.summary2:SetPoint("LEFT", card.summary1, "RIGHT", 26, 0)

    card.summary3 = createLabel(card, "GameFontHighlightSmall", "LEFT")
    card.summary3:SetPoint("LEFT", card.summary2, "RIGHT", 26, 0)

    card.refreshButton = createMiniActionButton(card, helpers, L.PVE_RARES_REFRESH or "Refresh", 82)
    card.refreshButton:SetPoint("TOPRIGHT", -14, -10)

    card.zonePanel = createSectionFrame(card, helpers, "cardInset")
    card.zonePanel:SetPoint("TOPLEFT", 14, -48)
    card.zonePanel:SetPoint("BOTTOMLEFT", 14, 14)
    card.zonePanel:SetWidth(ZONE_PANEL_WIDTH)

    card.zoneTitle = createLabel(card.zonePanel, "GameFontNormal", "LEFT")
    card.zoneTitle:SetPoint("TOPLEFT", 12, -12)
    card.zoneTitle:SetPoint("TOPRIGHT", -12, -12)
    card.zoneTitle:SetText(L.PVE_RARES_ZONES or "Zones")

    card.zoneButtons = {}
    for index = 1, 4 do
        local button = createMiniActionButton(card.zonePanel, helpers, "", 156)
        if index == 1 then
            button:SetPoint("TOPLEFT", card.zoneTitle, "BOTTOMLEFT", 0, -12)
            button:SetPoint("TOPRIGHT", card.zoneTitle, "BOTTOMRIGHT", 0, -12)
        else
            button:SetPoint("TOPLEFT", card.zoneButtons[index - 1], "BOTTOMLEFT", 0, -8)
            button:SetPoint("TOPRIGHT", card.zoneButtons[index - 1], "BOTTOMRIGHT", 0, -8)
        end
        card.zoneButtons[index] = button
    end

    card.detailPanel = createSectionFrame(card, helpers, "cardInset")
    card.detailPanel:SetPoint("TOPLEFT", card.zonePanel, "TOPRIGHT", 14, 0)
    card.detailPanel:SetPoint("BOTTOMRIGHT", -14, 14)

    card.zoneHeader = createLabel(card.detailPanel, "GameFontNormalLarge", "LEFT")
    card.zoneHeader:SetPoint("TOPLEFT", 14, -12)
    card.zoneHeader:SetPoint("TOPRIGHT", -14, -12)

    card.zoneMeta = createLabel(card.detailPanel, "GameFontHighlightSmall", "LEFT")
    card.zoneMeta:SetPoint("TOPLEFT", card.zoneHeader, "BOTTOMLEFT", 0, -7)
    card.zoneMeta:SetPoint("TOPRIGHT", -14, 0)

    card.mountPanel = CreateFrame("Frame", nil, card.detailPanel)
    card.mountPanel:SetPoint("TOPLEFT", card.zoneMeta, "BOTTOMLEFT", 0, -12)
    card.mountPanel:SetPoint("TOPRIGHT", -14, 0)
    card.mountPanel:SetHeight(46)

    card.mountSlots = {}
    for index = 1, 2 do
        local slot = createMountSlot(card.mountPanel)
        if index == 1 then
            slot:SetPoint("TOPLEFT", 0, 0)
            slot:SetPoint("BOTTOMRIGHT", card.mountPanel, "BOTTOM", -6, 0)
        else
            slot:SetPoint("TOPLEFT", card.mountPanel, "TOP", 6, 0)
            slot:SetPoint("BOTTOMRIGHT", 0, 0)
        end
        card.mountSlots[index] = slot
    end

    card.scroll = CreateFrame("ScrollFrame", nil, card.detailPanel, "UIPanelScrollFrameTemplate")
    card.scroll:SetPoint("TOPLEFT", card.mountPanel, "BOTTOMLEFT", 0, -12)
    card.scroll:SetPoint("BOTTOMRIGHT", -28, 12)

    card.scrollChild = CreateFrame("Frame", nil, card.scroll)
    card.scrollChild:SetSize(10, 10)
    card.scroll:SetScrollChild(card.scrollChild)
    callHelper(helpers, "styleScrollFrame", card.scroll)

    card.empty = createLabel(card.detailPanel, "GameFontDisableLarge", "LEFT")
    card.empty:SetPoint("TOPLEFT", card.scroll, "TOPLEFT", 8, -8)
    card.empty:SetPoint("BOTTOMRIGHT", card.scroll, "BOTTOMRIGHT", -8, 8)
    card.empty:SetJustifyV("TOP")
    card.empty:SetWordWrap(true)
    card.empty:SetText(L.PVE_RARES_NO_DATA or "No rare data available yet.")
    card.empty:Hide()

    return card
end

function PveRaresView.RefreshCard(ui, snapshot, helpers)
    if not ui or not ui.frame or not ui.frame.pveRaresCard then
        return
    end

    local card = ui.frame.pveRaresCard
    card.ui = ui
    card.helpers = helpers or card.helpers or {}

    local character = ns:GetSelectedCharacter()
    local view = callHelper(card.helpers, "buildPveRaresView", character, snapshot) or {}
    local zone = view.selectedZone or {}
    local rares = type(zone.rares) == "table" and zone.rares or {}
    local selectedKey = type(character) == "table" and character.key or character
    local isCurrentCharacter = type(ns.IsCurrentCharacterKey) == "function" and ns:IsCurrentCharacterKey(selectedKey) or false

    card.summary1:SetText(view.summary1 or "")
    card.summary2:SetText(view.summary2 or "")
    card.summary3:SetText(view.summary3 or "")
    card.zoneHeader:SetText(getZoneDisplayName(zone) ~= "" and getZoneDisplayName(zone) or (L.PVE_RARES_TITLE or "Rare Mobs"))
    card.zoneMeta:SetText(string.format(
        L.PVE_RARES_ZONE_PROGRESS_FORMAT or "Today: %d/%d rare mobs",
        tonumber(zone.completed) or 0,
        tonumber(zone.total) or 0
    ))

    setButtonText(card.refreshButton, L.PVE_RARES_REFRESH or "Refresh", 82, 104)
    card.refreshButton:SetShown(isCurrentCharacter)
    card.refreshButton:SetScript("OnClick", function()
        if ns.RefreshCurrentCharacterMidnightRareData then
            ns:RefreshCurrentCharacterMidnightRareData()
        end
        PveRaresView.RefreshCard(ui, snapshot, card.helpers)
    end)

    refreshZoneButtons(card, view, card.helpers)
    refreshMountSlots(card, zone.mounts)
    refreshRareRows(card, rares)
    card.empty:SetShown(#rares == 0)
end
