-- LidCouncil_Editor_ProfileDrag.lua
-- Split from Editor.lua to isolate profile drag interactions.

local API = rawget(_G, "LIDCOUNCIL_API")
local INTERNAL_API = type(API) == "table" and type(API.__internal) == "table" and API.__internal or nil
if type(INTERNAL_API) ~= "table" then
  error("LidCouncil missing internal API registry.")
end

local getDeps = INTERNAL_API.LIDCOUNCIL_GetEditorProfileDragDeps_Impl
if type(getDeps) ~= "function" then
  error("LidCouncil missing editor profile drag dependencies.")
end

local deps = getDeps()
local TrimName = deps.TrimName
local Print = deps.Print
local CreatePurpleOutline = deps.CreatePurpleOutline
local AssignProfileToGroup = deps.AssignProfileToGroup

local function GetEditor()
  return deps.GetEditor()
end

local function MoveProfileToGroup(profileName, sourceGroupName, targetGroupName)
  local name = TrimName(profileName or "")
  local sourceName = TrimName(sourceGroupName or "")
  local targetName = TrimName(targetGroupName or "")
  if name == "" then
    return false
  end

  local editor = GetEditor()
  if sourceName == targetName then
    if editor then
      local needsDetailsRefresh = (editor.selectedProfileName ~= name) or (editor.selectedProfileGroupName ~= nil)
      editor.selectedProfileName = name
      editor.selectedProfileGroupName = nil
      if editor.RestoreProfileCurrentLabel then
        editor:RestoreProfileCurrentLabel()
      end
      if needsDetailsRefresh and editor.RefreshProfilesSection then
        editor:RefreshProfilesSection()
      elseif (not needsDetailsRefresh) and editor.RefreshProfilesListSection then
        editor:RefreshProfilesListSection()
      elseif editor.Refresh then
        editor:Refresh()
      end
    end
    return true
  end

  local ok = AssignProfileToGroup(name, targetName ~= "" and targetName or nil)
  if not ok then
    return false
  end

  if editor then
    local needsDetailsRefresh = (editor.selectedProfileName ~= name) or (editor.selectedProfileGroupName ~= nil)
    editor.selectedProfileName = name
    editor.selectedProfileGroupName = nil
    if editor.RestoreProfileCurrentLabel then
      editor:RestoreProfileCurrentLabel()
    end
    if targetName ~= "" then
      Print("Moved profile \"" .. name .. "\" to group \"" .. targetName .. "\".")
    else
      Print("Removed profile \"" .. name .. "\" from its group.")
    end
    if needsDetailsRefresh and editor.RefreshProfilesSection then
      editor:RefreshProfilesSection()
    elseif (not needsDetailsRefresh) and editor.RefreshProfilesListSection then
      editor:RefreshProfilesListSection()
    elseif editor.Refresh then
      editor:Refresh()
    end
    return true
  end

  if targetName ~= "" then
    Print("Moved profile \"" .. name .. "\" to group \"" .. targetName .. "\".")
  else
    Print("Removed profile \"" .. name .. "\" from its group.")
  end
  return true
end

local function EnsureProfileGroupDragBadge()
  local editor = GetEditor()
  if not editor then
    return nil
  end
  if editor.__profileGroupDragBadge then
    return editor.__profileGroupDragBadge
  end

  local badge = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
  badge:SetFrameStrata("TOOLTIP")
  badge:SetFrameLevel(250)
  badge:SetClampedToScreen(true)
  badge:SetSize(328, 42)
  badge:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 1,
  })
  badge:SetBackdropColor(0.13, 0.08, 0.20, 0.98)
  badge:SetBackdropBorderColor(0.6588, 0.4784, 0.9098, 1.00)
  badge:Hide()

  local text = badge:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  text:SetPoint("LEFT", 12, 0)
  text:SetPoint("RIGHT", -12, 0)
  text:SetJustifyH("LEFT")
  text:SetTextColor(0.98, 0.94, 1.00, 1.00)
  badge.text = text

  editor.__profileGroupDragBadge = badge
  return badge
end

local function ClearProfileGroupDragState()
  local editor = GetEditor()
  if not editor then
    return nil
  end
  local state = editor.__profileGroupDrag
  if not state then
    return nil
  end

  if state.sourceButton and state.sourceButton.SetAlpha then
    state.sourceButton:SetAlpha(1)
  end
  if state.sourceButton and state.sourceButton.__profileDragSourceBorder then
    state.sourceButton.__profileDragSourceBorder:Hide()
  end
  for _, button in ipairs(editor.profGroupButtons or {}) do
    if button and button.__profileDragDropBorder then
      button.__profileDragDropBorder:Hide()
      button.__profileDragDropBorder:SetBackdropBorderColor(0.6588, 0.4784, 0.9098, 0.95)
    end
  end
  if editor.__profileGroupDragBadge then
    editor.__profileGroupDragBadge:Hide()
  end
  if editor.__profileGroupDragMonitor then
    editor.__profileGroupDragMonitor:Hide()
  end

  editor.__profileGroupDrag = nil
  return state
end

local function CancelProfileGroupDrag(skipRefresh)
  local state = ClearProfileGroupDragState()
  if not state then
    return false
  end
  local editor = GetEditor()
  if editor and editor.RestoreProfileCurrentLabel then
    editor:RestoreProfileCurrentLabel()
  end
  if (not skipRefresh) and editor and editor.ApplyTheme then
    editor:ApplyTheme()
  end
  return true
end

local function CompleteProfileGroupDrag(targetGroupName)
  local state = ClearProfileGroupDragState()
  if not state then
    return false
  end
  return MoveProfileToGroup(state.name, state.sourceGroupName, targetGroupName)
end

local function EnsureProfileGroupDragMonitor()
  local editor = GetEditor()
  if not editor then
    return nil
  end
  if editor.__profileGroupDragMonitor then
    return editor.__profileGroupDragMonitor
  end

  local monitor = CreateFrame("Frame", nil, editor)
  local badge = EnsureProfileGroupDragBadge()
  monitor:Hide()
  monitor:SetAllPoints(editor)
  monitor:SetScript("OnUpdate", function(self)
    local currentEditor = GetEditor()
    local state = currentEditor and currentEditor.__profileGroupDrag
    if not state then
      if badge then
        badge:Hide()
      end
      self:Hide()
      return
    end

    local hoveredButton = nil
    if type(MouseIsOver) == "function" then
      for _, button in ipairs(currentEditor.profGroupButtons or {}) do
        if button and button.IsShown and button:IsShown() and MouseIsOver(button) then
          hoveredButton = button
          break
        end
      end
    end

    if hoveredButton ~= state.hoveredButton then
      if state.hoveredButton and state.hoveredButton.__profileDragDropBorder then
        state.hoveredButton.__profileDragDropBorder:SetBackdropBorderColor(0.6588, 0.4784, 0.9098, 0.42)
        state.hoveredButton.__profileDragDropBorder:Show()
      end
      state.hoveredButton = hoveredButton
      if hoveredButton and hoveredButton.__profileDragDropBorder then
        hoveredButton.__profileDragDropBorder:SetBackdropBorderColor(0.6588, 0.4784, 0.9098, 1.00)
        hoveredButton.__profileDragDropBorder:Show()
      end
    end

    local overList = false
    if type(MouseIsOver) == "function" and currentEditor.profListBg and MouseIsOver(currentEditor.profListBg) then
      overList = true
    end

    if badge then
      local scale = (UIParent and UIParent.GetEffectiveScale and UIParent:GetEffectiveScale()) or 1
      if scale == 0 then
        scale = 1
      end
      local cx, cy = GetCursorPosition()
      if cx and cy then
        cx = cx / scale
        cy = cy / scale
        badge:ClearAllPoints()
        badge:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", cx + 18, cy - 16)
      end
      local targetName = hoveredButton and hoveredButton.__profileGroupName or nil
      if targetName and targetName ~= "" then
        badge.text:SetText("Moving: " .. state.name .. "  ->  " .. targetName)
      elseif overList then
        badge.text:SetText("Moving: " .. state.name .. "  ->  No group")
      else
        badge.text:SetText("Moving: " .. state.name .. "  |  Drop it on a group")
      end
      badge:Show()
    end

    local leftDown = (IsMouseButtonDown and IsMouseButtonDown("LeftButton")) or false
    if leftDown then
      return
    end

    self:Hide()
    if hoveredButton and hoveredButton.__profileGroupName then
      CompleteProfileGroupDrag(hoveredButton.__profileGroupName)
    elseif overList then
      CompleteProfileGroupDrag(nil)
    else
      CancelProfileGroupDrag()
    end
  end)

  editor.__profileGroupDragMonitor = monitor
  return monitor
end

local function BeginProfileGroupDrag(profileName, sourceGroupName, sourceButton)
  local editor = GetEditor()
  if not editor or not sourceButton then
    return false
  end
  local name = TrimName(profileName or "")
  if name == "" then
    return false
  end

  CancelProfileGroupDrag(true)

  sourceButton.__profileDragSourceBorder = sourceButton.__profileDragSourceBorder or CreatePurpleOutline(sourceButton)
  sourceButton.__profileDragSourceBorder:Show()
  if sourceButton.SetAlpha then
    sourceButton:SetAlpha(0.72)
  end

  editor.__profileGroupDrag = {
    name = name,
    sourceGroupName = TrimName(sourceGroupName or ""),
    sourceButton = sourceButton,
    hoveredButton = nil,
  }

  for _, button in ipairs(editor.profGroupButtons or {}) do
    if button and button.__profileDragDropBorder then
      button.__profileDragDropBorder:SetBackdropBorderColor(0.6588, 0.4784, 0.9098, 0.42)
      button.__profileDragDropBorder:Show()
    end
  end

  if editor.profileLabel then
    editor.profileLabel:SetText("Dragging: " .. name .. "  |  Drop it on a group or release inside the list to remove the group.")
  end

  local monitor = EnsureProfileGroupDragMonitor()
  if monitor then
    monitor:Show()
  end
  return true
end

INTERNAL_API.LIDCOUNCIL_EditorProfileDrag_Impl = {
  MoveProfileToGroup = MoveProfileToGroup,
  EnsureProfileGroupDragBadge = EnsureProfileGroupDragBadge,
  ClearProfileGroupDragState = ClearProfileGroupDragState,
  CancelProfileGroupDrag = CancelProfileGroupDrag,
  CompleteProfileGroupDrag = CompleteProfileGroupDrag,
  BeginProfileGroupDrag = BeginProfileGroupDrag,
}
