local MerfinPlus = LibStub("AceAddon-3.0"):GetAddon("MerfinPlus")

local FONT = MerfinPlus.GetDefaultFont and MerfinPlus.GetDefaultFont() or STANDARD_TEXT_FONT
local FONT_BOLD = FONT

local COLORS = {
  bg = { 0.035, 0.06, 0.095, 0.98 },
  panel = { 0.055, 0.1, 0.15, 0.96 },
  panelAlt = { 0.075, 0.13, 0.19, 0.94 },
  border = { 0.07, 0.48, 1, 0.58 },
  borderSoft = { 0.25, 0.38, 0.54, 0.55 },
  text = { 0.96, 0.98, 1, 1 },
  muted = { 0.72, 0.82, 0.94, 1 },
  accent = { 0.11, 0.56, 1, 1 },
  green = { 0.22, 0.82, 0.44, 1 },
  red = { 0.9, 0.24, 0.26, 1 },
  row = { 0.03, 0.075, 0.115, 0.48 },
  rowAlt = { 0.065, 0.11, 0.16, 0.48 },
}

local selector = {
  frame = nil,
  rows = {},
  headers = {},
  collapsed = {},
  query = "",
  flavor = nil,
  releases = {},
}

local function GetCompanionWeakAurasDB()
  if not MerfinPlus.db or not MerfinPlus.db.global then
    return nil
  end

  local global = MerfinPlus.db.global
  global.companion = global.companion or {}
  global.companion.weakAuras = global.companion.weakAuras or {}

  local weakAuras = global.companion.weakAuras
  weakAuras.selected = weakAuras.selected or {}
  weakAuras.updatedAt = weakAuras.updatedAt or 0
  weakAuras.revision = weakAuras.revision or 0
  weakAuras.source = weakAuras.source or ""

  return weakAuras
end

local function NormalizeWeakAuraId(value)
  if type(value) ~= "string" then
    return ""
  end
  value = value:gsub("^%s+", ""):gsub("%s+$", "")
  return value
end

local function TouchWeakAurasDB(weakAuras, source)
  weakAuras.updatedAt = time()
  weakAuras.revision = (tonumber(weakAuras.revision) or 0) + 1
  weakAuras.source = type(source) == "string" and source or "MerfinUI"
end

local function NormalizeSelection(selection)
  local normalized = {}
  if type(selection) ~= "table" then
    return normalized
  end

  for key, value in pairs(selection) do
    if type(key) == "number" then
      local auraId = NormalizeWeakAuraId(value)
      if auraId ~= "" then
        normalized[auraId] = true
      end
    else
      local auraId = NormalizeWeakAuraId(key)
      if auraId ~= "" and value then
        normalized[auraId] = true
      end
    end
  end

  return normalized
end

function MerfinPlus:SetCompanionWeakAuraSelection(selection, source)
  local weakAuras = GetCompanionWeakAurasDB()
  if not weakAuras then
    return false
  end

  weakAuras.selected = NormalizeSelection(selection)
  TouchWeakAurasDB(weakAuras, source)
  return true
end

function MerfinPlus:SetCompanionWeakAuraSelected(auraId, selected, source)
  local weakAuras = GetCompanionWeakAurasDB()
  auraId = NormalizeWeakAuraId(auraId)
  if not weakAuras or auraId == "" then
    return false
  end

  if selected then
    weakAuras.selected[auraId] = true
  else
    weakAuras.selected[auraId] = nil
  end

  TouchWeakAurasDB(weakAuras, source)
  return true
end

function MerfinPlus:GetCompanionWeakAuraSelection()
  local weakAuras = GetCompanionWeakAurasDB()
  if not weakAuras then
    return {}
  end

  local selected = {}
  for auraId, enabled in pairs(weakAuras.selected) do
    if enabled then
      selected[auraId] = true
    end
  end

  return selected
end

function MerfinPlus:ResetCompanionWeakAuraSelection(source)
  local weakAuras = GetCompanionWeakAurasDB()
  if not weakAuras then
    return false
  end

  weakAuras.selected = {}
  TouchWeakAurasDB(weakAuras, source)
  return true
end

local function RegisterEscClose(frameName)
  if not UISpecialFrames then
    return
  end

  for _, name in ipairs(UISpecialFrames) do
    if name == frameName then
      return
    end
  end

  table.insert(UISpecialFrames, frameName)
end

local function SetTextureColor(texture, color)
  if texture.SetColorTexture then
    texture:SetColorTexture(color[1], color[2], color[3], color[4])
  else
    texture:SetTexture(color[1], color[2], color[3], color[4])
  end
end

local function StyleFont(fontString, size, color, isBold)
  local font = isBold and FONT_BOLD or FONT
  local media = LibStub and LibStub("LibSharedMedia-3.0", true)

  if media and type(media.Fetch) == "function" then
    font = media:Fetch("font", font, true) or font
  end

  if type(font) ~= "string" or not font:find("[\\/]") then
    font = STANDARD_TEXT_FONT
  end

  local ok = pcall(fontString.SetFont, fontString, font, size, "")
  if not ok then
    fontString:SetFont(STANDARD_TEXT_FONT, size, "")
  end
  fontString:SetTextColor(color[1], color[2], color[3], color[4])
end

local function SetPanelBackdrop(frame, bgColor, borderColor)
  if not frame.SetBackdrop then
    return
  end

  frame:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8X8",
    edgeFile = "Interface\\Buttons\\WHITE8X8",
    edgeSize = 1,
    insets = { left = 1, right = 1, top = 1, bottom = 1 },
  })
  frame:SetBackdropColor(bgColor[1], bgColor[2], bgColor[3], bgColor[4])

  if borderColor then
    frame:SetBackdropBorderColor(borderColor[1], borderColor[2], borderColor[3], borderColor[4])
  else
    frame:SetBackdropBorderColor(0, 0, 0, 0)
  end
end

local function CreatePanel(parent, name, bgColor, borderColor)
  local frame = CreateFrame("Frame", name, parent, BackdropTemplateMixin and "BackdropTemplate")
  SetPanelBackdrop(frame, bgColor, borderColor)
  return frame
end

local function CreateMerfinButton(parent, text, width, color)
  local button = CreateFrame("Button", nil, parent, BackdropTemplateMixin and "BackdropTemplate")
  button:SetSize(width or 132, 30)
  SetPanelBackdrop(button, color or COLORS.accent, nil)

  button.text = button:CreateFontString(nil, "OVERLAY")
  button.text:SetPoint("CENTER")
  StyleFont(button.text, 12, COLORS.text, true)
  button.text:SetText(text)

  button:SetScript("OnEnter", function(self)
    SetPanelBackdrop(self, COLORS.panelAlt, COLORS.border)
  end)
  button:SetScript("OnLeave", function(self)
    SetPanelBackdrop(self, color or COLORS.accent, nil)
  end)

  return button
end

local function NormalizeFlavor(flavor)
  flavor = tostring(flavor or ""):lower()
  if flavor == "mainline" then
    return "retail"
  end
  if flavor == "mists" or flavor == "mop" then
    return "mists"
  end
  if flavor == "cata" or flavor == "cataclysm" then
    return "cata"
  end
  if flavor == "wrath" or flavor == "wotlk" then
    return "wrath"
  end
  if flavor == "tbc" or flavor == "burningcrusade" then
    return "tbc"
  end
  if flavor == "vanilla" or flavor == "classic" or flavor == "era" then
    return "vanilla"
  end
  return ""
end

local function CurrentFlavor()
  local build = MerfinPlus.BuildInfo or select(4, GetBuildInfo())
  if build and build >= 50000 and build < 60000 then
    return "mists"
  elseif build and build >= 40000 and build < 50000 then
    return "cata"
  elseif build and build >= 30000 and build < 40000 then
    return "wrath"
  elseif build and build >= 20000 and build < 30000 then
    return "tbc"
  elseif build and build < 20000 then
    return "vanilla"
  end
  return "retail"
end

local function CatalogReleaseIsPrivate(release)
  return (
    tostring(release.title or "")
      .. " "
      .. tostring(release.category or "")
      .. " "
      .. tostring(release.expansionLabel or "")
  ):lower():find("private", 1, true) ~= nil
end

local function CatalogReleases(flavor)
  local catalogData = type(MerfinPlusCompanionCatalog) == "table" and MerfinPlusCompanionCatalog or {}
  local catalog = catalogData.releases
  local hidePrivate = catalogData.hidePrivate == true
  local normalizedFlavor = NormalizeFlavor(flavor) ~= "" and NormalizeFlavor(flavor) or CurrentFlavor()
  local releases = {}

  if type(catalog) ~= "table" then
    return releases, normalizedFlavor
  end

  for _, release in pairs(catalog) do
    if type(release) == "table" then
      local id = NormalizeWeakAuraId(release.id)
      local expansion = NormalizeFlavor(release.expansion)

      if id ~= ""
          and (not hidePrivate or not CatalogReleaseIsPrivate(release))
          and (normalizedFlavor == "" or expansion == normalizedFlavor) then
        releases[#releases + 1] = {
          id = id,
          title = tostring(release.title or id),
          category = tostring(release.category or ""),
          expansion = expansion,
          expansionLabel = tostring(release.expansionLabel or release.expansion or normalizedFlavor),
          versionLabel = tostring(release.versionLabel or release.version or "1"),
        }
      end
    end
  end

  table.sort(releases, function(left, right)
    if left.category ~= right.category then
      return left.category < right.category
    end
    return left.title < right.title
  end)

  return releases, normalizedFlavor
end

local function ReleaseMatchesQuery(release)
  local query = selector.query
  if query == "" then
    return true
  end

  return (release.title .. " " .. release.category .. " " .. release.expansionLabel):lower():find(query, 1, true) ~= nil
end

local function CountSelected(releases)
  local selected = MerfinPlus:GetCompanionWeakAuraSelection()
  local count = 0

  for _, release in ipairs(releases or selector.releases) do
    if selected[release.id] then
      count = count + 1
    end
  end

  return count
end

local function PruneSelectionToCatalog(releases)
  local weakAuras = GetCompanionWeakAurasDB()
  if not weakAuras or type(weakAuras.selected) ~= "table" then
    return
  end

  local allowed = {}
  for _, release in ipairs(releases) do
    allowed[release.id] = true
  end

  local changed = false
  for auraId in pairs(weakAuras.selected) do
    if not allowed[auraId] then
      weakAuras.selected[auraId] = nil
      changed = true
    end
  end

  if changed then
    TouchWeakAurasDB(weakAuras, "MerfinPlus Selector")
  end
end

local function UpdateSelectorSummary()
  if not selector.frame then
    return
  end

  local selectedCount = CountSelected(selector.releases)
  selector.frame.countText:SetText(("%d Selected"):format(selectedCount))
end

local function HideChildren(children)
  for _, child in ipairs(children) do
    child:Hide()
  end
end

local function RowOnClick(row)
  local checked = not row.checked
  row.checked = checked
  MerfinPlus:SetCompanionWeakAuraSelected(row.release.id, checked, "MerfinPlus Selector")
  if checked then
    row.checkFill:Show()
  else
    row.checkFill:Hide()
  end
  UpdateSelectorSummary()
end

local RefreshSelectorRows

local function CategoryIsCollapsed(category)
  if selector.query ~= "" then
    return false
  end

  return selector.collapsed[category] ~= false
end

local function ToggleCategory(category)
  selector.collapsed[category] = not CategoryIsCollapsed(category)
  RefreshSelectorRows()
end

local function GetRow(index)
  local row = selector.rows[index]
  if row then
    return row
  end

  row = CreateFrame("Button", nil, selector.frame.content, BackdropTemplateMixin and "BackdropTemplate")
  row:SetHeight(42)
  SetPanelBackdrop(row, COLORS.row, COLORS.borderSoft)

  row.check = CreatePanel(row, nil, COLORS.bg, COLORS.border)
  row.check:SetPoint("LEFT", 12, 0)
  row.check:SetSize(18, 18)
  row.checkFill = row.check:CreateTexture(nil, "ARTWORK")
  row.checkFill:SetPoint("CENTER")
  row.checkFill:SetSize(10, 10)
  SetTextureColor(row.checkFill, COLORS.accent)
  row.checkFill:Hide()
  row.check:EnableMouse(false)

  row.title = row:CreateFontString(nil, "OVERLAY")
  row.title:SetPoint("TOPLEFT", row.check, "TOPRIGHT", 10, -2)
  row.title:SetPoint("RIGHT", row, "RIGHT", -14, 0)
  row.title:SetJustifyH("LEFT")
  StyleFont(row.title, 12, COLORS.text, true)

  row.meta = row:CreateFontString(nil, "OVERLAY")
  row.meta:SetPoint("TOPLEFT", row.title, "BOTTOMLEFT", 0, -3)
  row.meta:SetPoint("RIGHT", row, "RIGHT", -14, 0)
  row.meta:SetJustifyH("LEFT")
  StyleFont(row.meta, 10, COLORS.muted, false)

  row:SetScript("OnClick", RowOnClick)

  selector.rows[index] = row
  return row
end

local function GetHeader(index)
  local header = selector.headers[index]
  if header then
    return header
  end

  header = CreateFrame("Button", nil, selector.frame.content, BackdropTemplateMixin and "BackdropTemplate")
  header:SetHeight(30)
  SetPanelBackdrop(header, COLORS.panelAlt, COLORS.borderSoft)

  header.arrow = header:CreateFontString(nil, "OVERLAY")
  header.arrow:SetPoint("LEFT", 10, 0)
  header.arrow:SetWidth(16)
  header.arrow:SetJustifyH("LEFT")
  StyleFont(header.arrow, 13, COLORS.accent, true)

  header.text = header:CreateFontString(nil, "OVERLAY")
  header.text:SetPoint("LEFT", header.arrow, "RIGHT", 4, 0)
  header.text:SetPoint("RIGHT", header, "RIGHT", -96, 0)
  header.text:SetJustifyH("LEFT")
  StyleFont(header.text, 12, COLORS.accent, true)

  header.count = header:CreateFontString(nil, "OVERLAY")
  header.count:SetPoint("RIGHT", header, "RIGHT", -12, 0)
  header.count:SetWidth(84)
  header.count:SetJustifyH("RIGHT")
  StyleFont(header.count, 11, COLORS.muted, false)

  header:SetScript("OnEnter", function(self)
    SetPanelBackdrop(self, COLORS.panel, COLORS.border)
  end)
  header:SetScript("OnLeave", function(self)
    SetPanelBackdrop(self, COLORS.panelAlt, COLORS.borderSoft)
  end)

  selector.headers[index] = header
  return header
end

RefreshSelectorRows = function()
  if not selector.frame then
    return
  end

  HideChildren(selector.rows)
  HideChildren(selector.headers)

  local selected = MerfinPlus:GetCompanionWeakAuraSelection()
  local categoryCounts = {}
  for _, release in ipairs(selector.releases) do
    local category = release.category ~= "" and release.category or "Other"
    categoryCounts[category] = categoryCounts[category] or { total = 0, selected = 0 }
    categoryCounts[category].total = categoryCounts[category].total + 1
    if selected[release.id] then
      categoryCounts[category].selected = categoryCounts[category].selected + 1
    end
  end

  local visibleIndex = 0
  local headerIndex = 0
  local previousCategory
  local y = -8
  local visibleCategories = 0

  for _, release in ipairs(selector.releases) do
    if ReleaseMatchesQuery(release) then
      local category = release.category ~= "" and release.category or "Other"
      if category ~= previousCategory then
        headerIndex = headerIndex + 1
        visibleCategories = visibleCategories + 1
        local header = GetHeader(headerIndex)
        local collapsed = CategoryIsCollapsed(category)
        local counts = categoryCounts[category] or { total = 0, selected = 0 }
        header.category = category
        header.arrow:SetText(collapsed and "+" or "-")
        header.text:SetText(category)
        if counts.selected > 0 then
          header.count:SetText(("%d/%d"):format(counts.selected, counts.total))
        else
          header.count:SetText(tostring(counts.total))
        end
        header:SetScript("OnClick", function(self)
          ToggleCategory(self.category)
        end)
        header:ClearAllPoints()
        header:SetPoint("TOPLEFT", selector.frame.content, "TOPLEFT", 6, y)
        header:SetWidth(selector.frame.contentWidth - 12)
        header:Show()
        previousCategory = category
        y = y - 34
      end

      if not CategoryIsCollapsed(category) then
        visibleIndex = visibleIndex + 1
        local row = GetRow(visibleIndex)
        row.release = release
        row.checked = selected[release.id] and true or false
        row.title:SetText(release.title)
        row.meta:SetText(("%s - v%s"):format(release.expansionLabel, release.versionLabel))
        if row.checked then
          row.checkFill:Show()
        else
          row.checkFill:Hide()
        end
        SetPanelBackdrop(row, visibleIndex % 2 == 0 and COLORS.rowAlt or COLORS.row, COLORS.borderSoft)
        row:ClearAllPoints()
        row:SetPoint("TOPLEFT", selector.frame.content, "TOPLEFT", 18, y)
        row:SetWidth(selector.frame.contentWidth - 30)
        row:Show()
        y = y - 45
      end
    end
  end

  if visibleCategories == 0 then
    selector.frame.emptyText:Show()
  else
    selector.frame.emptyText:Hide()
  end
  selector.frame.emptyText:SetText(
    #selector.releases == 0
      and "No catalog found yet. Open the MerfinUI Companion once after connecting Discord."
      or "No WeakAuras match this search."
  )
  selector.frame.content:SetWidth(selector.frame.contentWidth)
  selector.frame.content:SetHeight(math.max(330, math.abs(y) + 20))
  UpdateSelectorSummary()
end

local function BuildSelectorFrame()
  if selector.frame then
    return selector.frame
  end

  local frameName = "MerfinPlusCompanionWeakAuraSelector"
  local frame = CreatePanel(UIParent, frameName, COLORS.bg, COLORS.border)
  frame:SetSize(760, 560)
  frame:SetPoint("CENTER")
  frame:SetFrameStrata("DIALOG")
  frame:SetMovable(true)
  frame:EnableMouse(true)
  frame:RegisterForDrag("LeftButton")
  frame:SetScript("OnDragStart", frame.StartMoving)
  frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
  frame:Hide()
  RegisterEscClose(frameName)

  frame.logo = frame:CreateTexture(nil, "ARTWORK")
  frame.logo:SetSize(48, 48)
  frame.logo:SetPoint("TOPLEFT", 18, -16)
  frame.logo:SetTexture("Interface\\AddOns\\MerfinPlus\\Media\\icons\\merfin\\logo_MINI.png")

  frame.title = frame:CreateFontString(nil, "OVERLAY")
  frame.title:SetPoint("TOPLEFT", frame.logo, "TOPRIGHT", 12, -3)
  StyleFont(frame.title, 22, COLORS.text, true)
  frame.title:SetText("Merfin WeakAuras")

  frame.countText = frame:CreateFontString(nil, "OVERLAY")
  frame.countText:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -54, -25)
  frame.countText:SetJustifyH("RIGHT")
  StyleFont(frame.countText, 12, COLORS.green, true)

  frame.close = CreateMerfinButton(frame, "X", 28, COLORS.red)
  frame.close:SetPoint("TOPRIGHT", -16, -16)
  frame.close:SetScript("OnClick", function()
    frame:Hide()
  end)

  frame.search = CreateFrame("EditBox", nil, frame, BackdropTemplateMixin and "BackdropTemplate")
  frame.search:SetSize(430, 30)
  frame.search:SetPoint("TOPLEFT", 22, -88)
  frame.search:SetAutoFocus(false)
  frame.search:SetTextInsets(10, 10, 0, 0)
  frame.search:SetFontObject(GameFontHighlightSmall)
  SetPanelBackdrop(frame.search, COLORS.panel, COLORS.borderSoft)
  frame.search:SetScript("OnTextChanged", function(self)
    selector.query = self:GetText():lower():gsub("^%s+", ""):gsub("%s+$", "")
    RefreshSelectorRows()
  end)

  frame.searchHint = frame.search:CreateFontString(nil, "OVERLAY")
  frame.searchHint:SetPoint("LEFT", frame.search, "LEFT", 10, 0)
  StyleFont(frame.searchHint, 11, COLORS.muted, false)
  frame.searchHint:SetText("Search WeakAuras")
  frame.search:SetScript("OnEditFocusGained", function(self)
    self:GetParent().searchHint:Hide()
  end)
  frame.search:SetScript("OnEditFocusLost", function(self)
    if self:GetText() == "" then
      self:GetParent().searchHint:Show()
    else
      self:GetParent().searchHint:Hide()
    end
  end)

  frame.clear = CreateMerfinButton(frame, "Clear", 90, COLORS.panelAlt)
  frame.clear:SetPoint("LEFT", frame.search, "RIGHT", 10, 0)
  frame.clear:SetScript("OnClick", function()
    frame.search:SetText("")
    selector.query = ""
    frame.searchHint:Show()
    RefreshSelectorRows()
  end)

  frame.done = CreateMerfinButton(frame, "Done", 118, COLORS.accent)
  frame.done:SetPoint("RIGHT", frame, "RIGHT", -22, 0)
  frame.done:SetPoint("TOP", frame.search, "TOP")
  frame.done:SetScript("OnClick", function()
    frame:Hide()
    if DEFAULT_CHAT_FRAME then
      DEFAULT_CHAT_FRAME:AddMessage("|cff40c7ebMerfinPlus:|r WeakAura selection saved. Run MerfinUI Companion sync outside the game.")
    end
  end)

  frame.listPanel = CreatePanel(frame, nil, COLORS.panel, COLORS.borderSoft)
  frame.listPanel:SetPoint("TOPLEFT", 22, -130)
  frame.listPanel:SetPoint("BOTTOMRIGHT", -22, 58)

  frame.contentWidth = 666
  frame.scroll = CreateFrame("ScrollFrame", nil, frame.listPanel)
  frame.scroll:SetPoint("TOPLEFT", 4, -4)
  frame.scroll:SetPoint("BOTTOMRIGHT", -4, 4)
  frame.scroll:EnableMouseWheel(true)
  frame.scroll:SetScript("OnMouseWheel", function(self, delta)
    local maxScroll = math.max(0, (frame.content:GetHeight() or 0) - (self:GetHeight() or 0))
    local nextScroll = (self:GetVerticalScroll() or 0) - (delta * 36)
    if nextScroll < 0 then
      nextScroll = 0
    elseif nextScroll > maxScroll then
      nextScroll = maxScroll
    end
    self:SetVerticalScroll(nextScroll)
  end)

  frame.content = CreateFrame("Frame", nil, frame.scroll)
  frame.content:SetSize(frame.contentWidth, 330)
  frame.scroll:SetScrollChild(frame.content)

  frame.emptyText = frame.listPanel:CreateFontString(nil, "OVERLAY")
  frame.emptyText:SetPoint("CENTER")
  frame.emptyText:SetWidth(520)
  frame.emptyText:SetJustifyH("CENTER")
  StyleFont(frame.emptyText, 13, COLORS.muted, false)

  frame.clearToggles = CreateMerfinButton(frame, "Clear all Toggles", 150, COLORS.panelAlt)
  frame.clearToggles:SetPoint("BOTTOMLEFT", 22, 20)
  frame.clearToggles:SetScript("OnClick", function()
    MerfinPlus:ResetCompanionWeakAuraSelection("MerfinPlus Selector")
    RefreshSelectorRows()
  end)

  selector.frame = frame
  return frame
end

function MerfinPlus:OpenCompanionWeakAuraSelector(flavor)
  local frame = BuildSelectorFrame()
  selector.releases, selector.flavor = CatalogReleases(flavor)
  PruneSelectionToCatalog(selector.releases)
  selector.query = ""
  frame.search:SetText("")
  frame.searchHint:Show()
  RefreshSelectorRows()
  frame:Show()
  return true
end

Merfin = Merfin or {}
Merfin.Companion = Merfin.Companion or {}
Merfin.Companion.SetWeakAuraSelection = function(selection, source)
  return MerfinPlus:SetCompanionWeakAuraSelection(selection, source)
end
Merfin.Companion.SetWeakAuraSelected = function(auraId, selected, source)
  return MerfinPlus:SetCompanionWeakAuraSelected(auraId, selected, source)
end
Merfin.Companion.GetWeakAuraSelection = function()
  return MerfinPlus:GetCompanionWeakAuraSelection()
end
Merfin.Companion.ResetWeakAuraSelection = function(source)
  return MerfinPlus:ResetCompanionWeakAuraSelection(source)
end
Merfin.Companion.OpenWeakAuraSelector = function(flavor)
  return MerfinPlus:OpenCompanionWeakAuraSelector(flavor)
end

SLASH_MERFINPLUSWEAKAURAS1 = "/merfinwa"
SlashCmdList.MERFINPLUSWEAKAURAS = function()
  MerfinPlus:OpenCompanionWeakAuraSelector()
end
