local _, ns = ...
local MythicTools = ns.MythicTools
local UI = ns.UI

local ApplyThinScrollBar = UI.ApplyThinScrollBar
local CHARACTER_DETAIL_CONTENT_HEIGHT = UI.CHARACTER_DETAIL_CONTENT_HEIGHT
local CHARACTER_ROWS = UI.CHARACTER_ROWS
local CHARACTER_ROW_HEIGHT = UI.CHARACTER_ROW_HEIGHT
local COLORS = UI.COLORS
local ClipChildren = UI.ClipChildren
local CreateAceDropdownWidget = UI.CreateAceDropdownWidget
local CreateAceFlowRow = UI.CreateAceFlowRow
local CreateActionButton = UI.CreateActionButton
local CreateCharacterOverviewRow = UI.CreateCharacterOverviewRow
local CreateFont = UI.CreateFont
local CreateMetricCard = UI.CreateMetricCard
local CreatePortraitWidget = UI.CreatePortraitWidget
local FormatKeyLevel = UI.FormatKeyLevel
local GetPlayerNameParts = UI.GetPlayerNameParts
local SEASON_FILTER_OPTIONS = UI.SEASON_FILTER_OPTIONS
local SetAceDropdownValue = UI.SetAceDropdownValue
local SetTextColor = UI.SetTextColor
local StyleAceDropdownWidget = UI.StyleAceDropdownWidget
local WHITE_TEXTURE = UI.WHITE_TEXTURE
local floor = UI.floor
local max = UI.max
local min = UI.min

function MythicTools:GetCharacterDashboardEntries()
    local filters = self.db and self.db.ui and self.db.ui.characterFilters or {}
    local entries = {}

    for _, fullName in ipairs(self:GetOwnedCharacters()) do
        local playerEntry = self.db.playersIndex and self.db.playersIndex[fullName] or nil
        if playerEntry then
            local aggregate = self:BuildFilteredPlayerAggregate(playerEntry, filters)
            if (aggregate.totalRuns or 0) > 0 then
                aggregate.sourceEntry = playerEntry
                aggregate.fullName = fullName
                aggregate.shortName = aggregate.shortName or self:GetShortName(fullName)
                entries[#entries + 1] = aggregate
            end
        end
    end

    table.sort(entries, function(left, right)
        if (left.bestTimedLevel or 0) ~= (right.bestTimedLevel or 0) then
            return (left.bestTimedLevel or 0) > (right.bestTimedLevel or 0)
        end
        if (left.totalRuns or 0) ~= (right.totalRuns or 0) then
            return (left.totalRuns or 0) > (right.totalRuns or 0)
        end
        return (left.shortName or left.fullName or "") < (right.shortName or right.fullName or "")
    end)

    return entries
end

function MythicTools:ShowCharactersIndex()
    self.db.ui.charactersView = "index"
    self.db.ui.selectedCharacter = nil
    self:ShowTab("Characters", true)
end

function MythicTools:OpenCurrentCharacterDetail()
    local fullName = self:GetUnitFullName("player") or self.playerName
    fullName = self:NormalizePlayerName(fullName) or self:TrimText(fullName)
    if not fullName or fullName == "" then
        return false
    end

    if self.RegisterOwnedCharacter then
        self:RegisterOwnedCharacter(fullName)
    end
    self:OpenCharacterDetail(fullName)
    return true
end

function MythicTools:OpenCharacterDetail(fullName)
    fullName = self:NormalizePlayerName(fullName) or self:TrimText(fullName)
    if not fullName or fullName == "" then
        return
    end

    self.db.ui.selectedCharacter = fullName
    self.db.ui.charactersView = "detail"
    self:BuildUI()
    self.ui.frame:Show()
    self:ShowTab("Characters", true)
    if self.ui.characterDetailScrollFrame then
        self.ui.characterDetailScrollFrame:SetVerticalScroll(0)
    end
    if self.ui.characterDetailScrollBar then
        self.ui.characterDetailScrollBar:SetValue(0)
    end
end

function MythicTools:BuildCharactersPage(parent)
    local page = CreateFrame("Frame", nil, parent)
    page:SetAllPoints(parent)
    ClipChildren(page)

    local indexView = CreateFrame("Frame", nil, page)
    indexView:SetAllPoints(page)
    ClipChildren(indexView)
    self.ui.charactersIndexView = indexView

    local filterBar = CreateFrame("Frame", nil, indexView)
    filterBar:SetPoint("TOPLEFT", 12, -12)
    filterBar:SetPoint("TOPRIGHT", -12, -12)
    filterBar:SetHeight(88)
    self:ApplySurface(filterBar, COLORS.sectionBG, COLORS.surface, COLORS.accentSoft)

    local title = CreateFont(filterBar, 13, COLORS.text)
    title:SetPoint("TOPLEFT", 16, -14)
    title:SetText(self:L("UI_MY_CHARACTERS"))

    self.ui.charactersCountLabel = CreateFont(filterBar, 12, COLORS.muted, "RIGHT")
    self.ui.charactersCountLabel:SetPoint("TOPRIGHT", -16, -14)

    local filtersRow = CreateAceFlowRow(filterBar, -34, 50)
    self.ui.charactersSeasonFilter = CreateAceDropdownWidget(self:L("UI_SEASON"), 210, SEASON_FILTER_OPTIONS, (self.db.ui.characterFilters and self.db.ui.characterFilters.season) or "all", function(value)
        self.db.ui.characterFilters.season = value or "all"
        SetAceDropdownValue(self.ui.charactersSeasonFilter, self.db.ui.characterFilters.season)
        self:RefreshCharactersView()
    end)
    StyleAceDropdownWidget(self.ui.charactersSeasonFilter)
    if filtersRow and self.ui.charactersSeasonFilter then
        filtersRow:AddChild(self.ui.charactersSeasonFilter)
    end

    local clearButton = CreateActionButton(filterBar, 104, 28, self:L("UI_CLEAR"))
    clearButton:SetPoint("TOPRIGHT", -16, -52)
    self:ApplyActionButtonIcon(clearButton, "Interface\\AddOns\\SkyMythicHistory\\Media\\Icons\\reset.tga", 12)
    clearButton:SetScript("OnClick", function()
        self.db.ui.characterFilters.season = "all"
        SetAceDropdownValue(self.ui.charactersSeasonFilter, "all")
        self:RefreshCharactersView()
    end)

    local openCurrentButton = CreateActionButton(filterBar, 174, 28, self:L("UI_CURRENT_CHARACTER"))
    openCurrentButton:SetPoint("RIGHT", clearButton, "LEFT", -10, 0)
    self:ApplyActionButtonIcon(openCurrentButton, "Interface\\AddOns\\SkyMythicHistory\\Media\\Icons\\right.tga", 12)
    openCurrentButton:SetScript("OnClick", function()
        MythicTools:OpenCurrentCharacterDetail()
    end)

    local listCard = CreateFrame("Frame", nil, indexView)
    listCard:SetPoint("TOPLEFT", filterBar, "BOTTOMLEFT", 0, -12)
    listCard:SetPoint("BOTTOMRIGHT", indexView, "BOTTOMRIGHT", -12, 12)
    self:ApplySurface(listCard, COLORS.sectionBG, COLORS.surface, COLORS.accentSoft)
    ClipChildren(listCard)

    local listTitle = CreateFont(listCard, 14, COLORS.text)
    listTitle:SetPoint("TOPLEFT", 16, -14)
    listTitle:SetText(self:L("UI_CHARACTER_OVERVIEW"))

    self.ui.charactersEmptyState = CreateFont(listCard, 13, COLORS.muted, "CENTER")
    self.ui.charactersEmptyState:SetPoint("CENTER")
    self.ui.charactersEmptyState:SetText(self:L("UI_NO_OWNED_CHARACTERS"))
    self.ui.charactersEmptyState:Hide()

    local rowsBody = CreateFrame("Frame", nil, listCard)
    rowsBody:SetPoint("TOPLEFT", 12, -44)
    rowsBody:SetPoint("TOPRIGHT", -22, -44)
    rowsBody:SetHeight(CHARACTER_ROWS * CHARACTER_ROW_HEIGHT)
    ClipChildren(rowsBody)

    self.ui.charactersScroll = CreateFrame("ScrollFrame", nil, listCard, "FauxScrollFrameTemplate")
    self.ui.charactersScroll:SetPoint("TOPLEFT", 0, -44)
    self.ui.charactersScroll:SetPoint("BOTTOMRIGHT", -10, 14)
    self.ui.charactersScroll:SetScript("OnVerticalScroll", function(scrollFrame, offset)
        FauxScrollFrame_OnVerticalScroll(scrollFrame, offset, CHARACTER_ROW_HEIGHT, function()
            self:RefreshCharactersView()
        end)
    end)
    ApplyThinScrollBar(self.ui.charactersScroll)

    self.ui.characterRows = {}
    for index = 1, CHARACTER_ROWS do
        local row = CreateCharacterOverviewRow(rowsBody)
        row:SetPoint("TOPLEFT", 0, -((index - 1) * CHARACTER_ROW_HEIGHT))
        row:SetPoint("TOPRIGHT", 0, -((index - 1) * CHARACTER_ROW_HEIGHT))
        row:SetScript("OnClick", function(button)
            if button.fullName then
                MythicTools:OpenCharacterDetail(button.fullName)
            end
        end)
        self.ui.characterRows[index] = row
    end

    local detailView = CreateFrame("Frame", nil, page)
    detailView:SetAllPoints(page)
    ClipChildren(detailView)
    self.ui.charactersDetailView = detailView

    self.ui.characterDetailBackButton = CreateActionButton(detailView, 156, 28, self:L("UI_BACK_TO_CHARACTERS"))
    self.ui.characterDetailBackButton:SetPoint("TOPLEFT", 12, -12)
    self:ApplyActionButtonIcon(self.ui.characterDetailBackButton, "Interface\\AddOns\\SkyMythicHistory\\Media\\Icons\\left.tga", 12)
    self.ui.characterDetailBackButton:SetScript("OnClick", function()
        MythicTools:ShowCharactersIndex()
    end)

    self.ui.characterDetailHeader = CreateFont(detailView, 12, COLORS.muted)
    self.ui.characterDetailHeader:SetPoint("LEFT", self.ui.characterDetailBackButton, "RIGHT", 14, 0)
    self.ui.characterDetailHeader:SetText(self:L("UI_CHARACTER_DETAILS"))

    local detailScrollFrame = CreateFrame("ScrollFrame", nil, detailView)
    detailScrollFrame:SetPoint("TOPLEFT", 12, -52)
    detailScrollFrame:SetPoint("BOTTOMRIGHT", -20, 12)
    detailScrollFrame:EnableMouseWheel(true)
    self.ui.characterDetailScrollFrame = detailScrollFrame

    local frameW = (self.db and self.db.ui and self.db.ui.width) or 1280
    local detailScrollW = max(760, frameW - 245)
    local detailContent = CreateFrame("Frame", nil, detailScrollFrame)
    detailContent:SetSize(detailScrollW, CHARACTER_DETAIL_CONTENT_HEIGHT)
    detailScrollFrame:SetScrollChild(detailContent)
    self.ui.characterDetailContent = detailContent

    local detailScrollBar = CreateFrame("Slider", nil, detailView)
    detailScrollBar:SetOrientation("VERTICAL")
    detailScrollBar:SetWidth(6)
    detailScrollBar:SetPoint("TOPRIGHT", detailView, "TOPRIGHT", -12, -52)
    detailScrollBar:SetPoint("BOTTOMRIGHT", detailView, "BOTTOMRIGHT", -12, 12)
    detailScrollBar:SetMinMaxValues(0, 1)
    detailScrollBar:SetValue(0)
    detailScrollBar:Hide()
    local detailThumb = detailScrollBar:CreateTexture(nil, "ARTWORK")
    detailThumb:SetTexture(WHITE_TEXTURE)
    detailThumb:SetWidth(4)
    detailThumb:SetVertexColor(COLORS.accent[1], COLORS.accent[2], COLORS.accent[3], 0.65)
    detailScrollBar:SetThumbTexture(detailThumb)
    detailScrollBar:SetScript("OnValueChanged", function(_, value)
        detailScrollFrame:SetVerticalScroll(value)
    end)
    detailScrollFrame:SetScript("OnScrollRangeChanged", function(_, _, yRange)
        local range = max(0, yRange or 0)
        detailScrollBar:SetMinMaxValues(0, range)
        detailScrollBar:SetShown(range > 0)
    end)
    detailScrollFrame:SetScript("OnMouseWheel", function(_, delta)
        local current = detailScrollBar:GetValue()
        local _, maxValue = detailScrollBar:GetMinMaxValues()
        detailScrollBar:SetValue(max(0, min(current - delta * 60, maxValue)))
    end)
    self.ui.characterDetailScrollBar = detailScrollBar

    local heroCard = CreateFrame("Frame", nil, detailContent)
    heroCard:SetPoint("TOPLEFT", detailContent, "TOPLEFT", 0, 0)
    heroCard:SetSize(detailScrollW, 304)
    self:ApplySurface(heroCard, COLORS.headerBG, COLORS.surface, COLORS.accent)
    self.ui.characterDetailHero = heroCard

    self.ui.characterDetailPortrait = CreatePortraitWidget(heroCard, 82, {noBorder = true})
    self.ui.characterDetailPortrait:SetPoint("TOPLEFT", 16, -10)

    self.ui.characterDetailRatingBadge = self:CreateHeroRatingBadge(heroCard)
    self.ui.characterDetailRatingBadge:SetPoint("TOPRIGHT", -18, -18)

    self.ui.characterDetailName = CreateFont(heroCard, 22, COLORS.text)
    self.ui.characterDetailName:SetPoint("TOPLEFT", self.ui.characterDetailPortrait, "TOPRIGHT", 16, -8)
    self.ui.characterDetailName:SetPoint("TOPRIGHT", self.ui.characterDetailRatingBadge, "TOPLEFT", -12, 0)

    self.ui.characterDetailRealm = CreateFont(heroCard, 12, COLORS.accentSoft)
    self.ui.characterDetailRealm:SetPoint("TOPLEFT", self.ui.characterDetailName, "BOTTOMLEFT", 0, -6)
    self.ui.characterDetailRealm:SetPoint("TOPRIGHT", self.ui.characterDetailRatingBadge, "BOTTOMLEFT", -12, -6)
    self.ui.characterDetailRealm:SetJustifyH("LEFT")

    self.ui.characterDetailMeta = CreateFont(heroCard, 12, COLORS.muted)
    self.ui.characterDetailMeta:SetPoint("TOPLEFT", self.ui.characterDetailRealm, "BOTTOMLEFT", 0, -6)
    self.ui.characterDetailMeta:SetPoint("TOPRIGHT", heroCard, "TOPRIGHT", -52, -52)

    local metricSpecs = {
        {key = "runs", label = "Runs"},
        {key = "timed", label = "Timed"},
        {key = "bestKey", label = "Best Key"},
        {key = "avgKey", label = "Avg Key"},
        {key = "maxDps", label = "Max DPS"},
        {key = "avgDps", label = "Avg DPS"},
        {key = "maxHps", label = "Max HPS"},
        {key = "avgHps", label = "Avg HPS"},
    }
    self.ui.characterDetailMetricCards = {}
    local metricGap = 8
    local metricCardW = floor((detailScrollW - 36 - (3 * metricGap)) / 4)
    for index, spec in ipairs(metricSpecs) do
        local card = CreateMetricCard(heroCard, spec.label)
        card:SetSize(metricCardW, 58)
        local column = (index - 1) % 4
        local rowIndex = floor((index - 1) / 4)
        card:SetPoint("TOPLEFT", heroCard, "TOPLEFT", 18 + (column * (metricCardW + metricGap)), -104 - (rowIndex * 66))
        self.ui.characterDetailMetricCards[spec.key] = card
    end

    local historyCard = CreateFrame("Frame", nil, detailContent)
    historyCard:SetPoint("TOPLEFT", heroCard, "BOTTOMLEFT", 0, -12)
    historyCard:SetSize(detailScrollW, 326)
    self:ApplySurface(historyCard, COLORS.sectionBG, COLORS.surface, COLORS.accentSoft)
    ClipChildren(historyCard)
    self.ui.characterDetailHistoryCard = historyCard

    local historyTitle = CreateFont(historyCard, 13, COLORS.text)
    historyTitle:SetPoint("TOPLEFT", 16, -14)
    historyTitle:SetText(self:L("UI_RUNS_HISTORY"))

    self.ui.characterDetailHistoryCount = CreateFont(historyCard, 11, COLORS.muted, "RIGHT")
    self.ui.characterDetailHistoryCount:SetPoint("TOPRIGHT", -16, -14)
    self.ui.characterDetailRunsTable = self:CreateDetailRunsTable(historyCard, 14)

    self.ui.characterDetailEmptyHistory = CreateFont(historyCard, 12, COLORS.muted, "CENTER")
    self.ui.characterDetailEmptyHistory:SetPoint("CENTER")
    self.ui.characterDetailEmptyHistory:SetText(self:L("UI_NO_RUNS_CHARACTER"))
    self.ui.characterDetailEmptyHistory:Hide()

    return page
end

function MythicTools:RefreshCharactersView()
    if not self.ui then
        return
    end

    local entries = self:GetCharacterDashboardEntries()
    self.ui.filteredCharacters = entries
    if self.ui.charactersCountLabel then
        self.ui.charactersCountLabel:SetText(("%d characters"):format(#entries))
    end
    if self.ui.charactersEmptyState then
        self.ui.charactersEmptyState:SetShown(#entries == 0)
    end

    if self.ui.charactersScroll then
        FauxScrollFrame_Update(self.ui.charactersScroll, #entries, CHARACTER_ROWS, CHARACTER_ROW_HEIGHT)
    end
    local offset = self.ui.charactersScroll and FauxScrollFrame_GetOffset(self.ui.charactersScroll) or 0
    for rowIndex, row in ipairs(self.ui.characterRows or {}) do
        local character = entries[offset + rowIndex]
        if character then
            local source = character.sourceEntry or character
            row.fullName = character.fullName
            self:SetPortraitWidget(
                row.Portrait,
                character.fullName,
                source.classFilename,
                source.specIconID,
                source.specID,
                {preferClassIcon = true, classIconStyle = "mmt_transparent"}
            )
            row.Name:SetText(character.shortName or self:GetShortName(character.fullName))
            local className = (source.classFilename and LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE[source.classFilename]) or source.classFilename or "Unknown class"
            row.Meta:SetText(("%s  |  %d runs  |  Avg key %.1f"):format(className, character.totalRuns or 0, character.averageLevel or 0))
            row.Detail:SetText(("DPS %s avg / HPS %s avg"):format(self:FormatAmount(character.averageDps or 0), self:FormatAmount(character.averageHps or 0)))
            row.Best:SetText(FormatKeyLevel(character.bestTimedLevel))
            row.Timed:SetText(("%.1f%% timed"):format(character.successRate or 0))
            local cc = source.classFilename and RAID_CLASS_COLORS and RAID_CLASS_COLORS[source.classFilename]
            SetTextColor(row.Name, cc and {cc.r, cc.g, cc.b, 1} or COLORS.text)
            row:Show()
        else
            row.fullName = nil
            row:Hide()
        end
    end

    local selectedCharacter = self.db and self.db.ui and self.db.ui.selectedCharacter
    local selectedEntry = selectedCharacter and (self.db.playersIndex and self.db.playersIndex[selectedCharacter]) or nil
    local showDetail = self.db.ui.charactersView == "detail" and selectedEntry ~= nil

    if self.ui.charactersIndexView then
        self.ui.charactersIndexView:SetShown(not showDetail)
    end
    if self.ui.charactersDetailView then
        self.ui.charactersDetailView:SetShown(showDetail)
    end

    if showDetail then
        self:RefreshCharacterDetailView(selectedEntry)
    elseif self.db.ui.charactersView == "detail" then
        self.db.ui.charactersView = "index"
        self.db.ui.selectedCharacter = nil
    end
end

function MythicTools:RefreshCharacterDetailView(playerEntry)
    if not (self.ui and self.ui.charactersDetailView and playerEntry) then
        return
    end

    local filters = self.db and self.db.ui and self.db.ui.characterFilters or nil
    local analyticsEntry = self:BuildFilteredPlayerAggregate(playerEntry, filters)
    local characterName, realmName = GetPlayerNameParts(playerEntry.fullName)

    self:SetPortraitWidget(
        self.ui.characterDetailPortrait,
        playerEntry.fullName,
        playerEntry.classFilename,
        playerEntry.specIconID,
        playerEntry.specID,
        {preferClassIcon = true, classIconStyle = "mmt_transparent"}
    )
    self:SetHeroRatingBadgeValue(self.ui.characterDetailRatingBadge, playerEntry.averageRating, playerEntry.ratingCount)
    self.ui.characterDetailName:SetText(characterName ~= "" and characterName or (playerEntry.shortName or playerEntry.fullName or "Unknown character"))
    if self.ui.characterDetailRealm then
        self.ui.characterDetailRealm:SetText(realmName ~= "" and realmName or "Unknown realm")
    end
    if self.ui.characterDetailMeta then
        self.ui.characterDetailMeta:SetText("")
        self.ui.characterDetailMeta:Hide()
    end

    if self.ui.characterDetailMetricCards then
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.runs, tostring(analyticsEntry.totalRuns or 0), "Total runs")
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.timed, tostring(analyticsEntry.timedRuns or 0), ("%.1f%% success"):format(analyticsEntry.successRate or 0), COLORS.success)
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.bestKey, FormatKeyLevel(analyticsEntry.bestTimedLevel), "Best timed")
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.avgKey, string.format("%.1f", analyticsEntry.averageLevel or 0), "Average key")
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.maxDps, self:FormatAmount(analyticsEntry.maxDps or 0), "Maximum DPS", COLORS.accentSoft)
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.avgDps, self:FormatAmount(analyticsEntry.averageDps or 0), "Average DPS")
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.maxHps, self:FormatAmount(analyticsEntry.maxHps or 0), "Maximum HPS", COLORS.accentSoft)
        self:SetMetricCardValue(self.ui.characterDetailMetricCards.avgHps, self:FormatAmount(analyticsEntry.averageHps or 0), "Average HPS")
    end

    local recentRuns = self:GetPlayerRecentRuns(playerEntry.fullName, nil, filters)
    if self.ui.characterDetailHistoryCount then
        self.ui.characterDetailHistoryCount:SetText(("%d run%s total"):format(#recentRuns, #recentRuns == 1 and "" or "s"))
    end
    if self.ui.characterDetailEmptyHistory then
        self.ui.characterDetailEmptyHistory:SetShown(#recentRuns == 0)
    end
    if self.ui.characterDetailRunsTable then
        self.ui.characterDetailRunsTable:SetData(self:BuildDetailRunsTableData(playerEntry.fullName, recentRuns))
        self.ui.characterDetailRunsTable:SortData()
        if self.ui.characterDetailRunsTable.frame then
            self.ui.characterDetailRunsTable.frame:SetShown(#recentRuns > 0)
        end
    end
end

