local ADDON, ns = ...
local L = ns.L

local AceAddon = LibStub("AceAddon-3.0")
local Addon = AceAddon:NewAddon(ADDON, "AceEvent-3.0", "AceConsole-3.0", "AceHook-3.0")

local defaults = {
  profile = {
    disableSend = true,          -- (1) Senden über BugSack verhindern
    receiveMode = "ALWAYS",      -- OFF | ALWAYS | COMBAT | OPENWORLD
    replyToSender = true,       -- (3) optionaler Whisper zurück
    replyMessage = "Na na na na, I can't hear you!",          -- fallback auf L["BlockedNotice"]
    replyThrottle = 5,           -- Sekunden pro Sender
    verbose = false,             -- optional: Chat-Ausgaben
    enableAltWipe = true,        -- oder false, je nachdem was du als Standard willst
    extendTooltip = true,        -- erweitert den BugSack MinimapIcon Tooltip um die Alt-Klick Funktion
  }
}

local lastReply = {}
local hooked = false

local function InOpenWorld()
  local inInstance, instanceType = IsInInstance()
  return (not inInstance) or instanceType == "none"
end

function Addon:ShouldBlockReceive()
  local mode = self.db.profile.receiveMode
  if mode == "OFF" then
    return false
  elseif mode == "ALWAYS" then
    return true
  elseif mode == "COMBAT" then
    return UnitAffectingCombat("player") or InCombatLockdown()
  elseif mode == "OPENWORLD" then
    return not InOpenWorld()
  end
  return false
end

function Addon:MaybeReply(sender)
  if not self.db.profile.replyToSender then return end
  if type(sender) ~= "string" or sender == "" then return end

  local now = GetTime()
  local t = lastReply[sender] or 0
  local throttle = tonumber(self.db.profile.replyThrottle) or 5
  if now - t < throttle then return end
  lastReply[sender] = now

  local msg = self.db.profile.replyMessage
  if type(msg) ~= "string" or msg == "" then
    msg = L["BlockedNotice"]
  end

  -- normaler Whisper (kein Addon-Comm), best effort
  pcall(SendChatMessage, msg, "WHISPER", nil, sender)
end

local function DebugPrint(self, ...)
  if self.db and self.db.profile and self.db.profile.verbose then
    self:Print(...)
  end
end

function Addon:PatchBugSack()
  if hooked then return end
  local BugSack = _G.BugSack
  if type(BugSack) ~= "table" then return end

  DebugPrint(self, "BugSack gefunden – Hooks werden gesetzt.")

  -- (1) Senden blockieren: BugSack:SendBugsToUser(player, session)
  -- BugSack nutzt genau diese Funktion zum Versand. [1](https://addons.wago.io/addons/buggrabber)
  if type(BugSack.SendBugsToUser) == "function" and not BugSack.__BugSackBlock_OrigSend then
    BugSack.__BugSackBlock_OrigSend = BugSack.SendBugsToUser
    BugSack.SendBugsToUser = function(selfBS, player, session)
      if Addon.db.profile.disableSend then
        DebugPrint(Addon, "BugSackBlock: Versand blockiert.")
        return
      end
      return BugSack.__BugSackBlock_OrigSend(selfBS, player, session)
    end
  end

  -- (1) Popup-Button "Send" deaktivieren (BugSackSendBugs Popup existiert in BugSack) [1](https://addons.wago.io/addons/buggrabber)
  if type(_G.StaticPopupDialogs) == "table" and type(_G.StaticPopupDialogs.BugSackSendBugs) == "table" then
    local dlg = _G.StaticPopupDialogs.BugSackSendBugs
    if not dlg.__BugSackBlock_Patched then
      dlg.__BugSackBlock_Patched = true
      local origOnShow = dlg.OnShow
      dlg.OnShow = function(selfPopup)
        if origOnShow then pcall(origOnShow, selfPopup) end
        if Addon.db.profile.disableSend and selfPopup.GetButton1 then
          selfPopup:GetButton1():Disable()
        end
      end
    end
  end

  -- (2) Empfang filtern: BugSack:OnBugComm(prefix, message, _, sender)
  -- BugSack registriert RegisterComm("BugSack","OnBugComm") und deserialisiert + StoreError. [1](https://addons.wago.io/addons/buggrabber)
  if type(BugSack.OnBugComm) == "function" and not BugSack.__BugSackBlock_OrigRecv then
    BugSack.__BugSackBlock_OrigRecv = BugSack.OnBugComm
    BugSack.OnBugComm = function(selfBS, prefix, message, dist, sender)
      if prefix == "BugSack" and Addon:ShouldBlockReceive() then
        DebugPrint(Addon, ("BugSackBlock: Empfang blockiert von %s."):format(tostring(sender)))
        Addon:MaybeReply(sender)
        return -- BLOCK: keine Deserialisierung, kein StoreError => Lag-Vermeidung
      end
      return BugSack.__BugSackBlock_OrigRecv(selfBS, prefix, message, dist, sender)
    end
  end

  hooked = true

  self:ApplyBugSackAltWipe()
  self:PatchBugSackTooltip()

  self:RegisterEvent("PLAYER_LOGIN", function()
        self:PatchBugSackTooltip()
    end)
end

function Addon:PatchBugSackTooltip()
  -- Option aus BugSackBlock
  if not (self.db and self.db.profile and self.db.profile.extendTooltip) then
    return
  end

  local ldb = LibStub:GetLibrary("LibDataBroker-1.1", true)
  if not ldb then return end

  -- BugSack erstellt sein DataObject mit Name = addonName ("BugSack") [1](https://www.ssegold.com/wow-midnight-12-0-1-addon-changes)
  local obj = ldb:GetDataObjectByName("BugSack") -- LDB API [2](https://github.com/tekkub/libdatabroker-1-1/blob/master/LibDataBroker-1.1.lua)
  if type(obj) ~= "table" or type(obj.OnTooltipShow) ~= "function" then return end

  if obj.__BugSackBlock_TooltipPatched then return end
  obj.__BugSackBlock_TooltipPatched = true

  local orig = obj.OnTooltipShow

  obj.OnTooltipShow = function(tt, ...)
    -- originaler BugSack Tooltip (inkl. L.minimapHint etc.) [1](https://www.ssegold.com/wow-midnight-12-0-1-addon-changes)
    pcall(orig, tt, ...)

    -- BugSackBlock Zusatzinfos
    local mode = Addon.db.profile.receiveMode
    local blockedNow = Addon:ShouldBlockReceive()

    local function yesno(v)
      return v and "|cff00ff00ON|r" or "|cffff4444OFF|r"
    end

    local function modeLabel(m)
      if m == "OFF" then return "OFF"
      elseif m == "ALWAYS" then return "ALWAYS"
      elseif m == "COMBAT" then return "COMBAT"
      elseif m == "OPENWORLD" then return "OPENWORLD"
      end
      return tostring(m)
    end

    tt:AddLine(" ")
    tt:AddLine("|cff33ff99" .. (ns.L["TooltipHeader"] or "BugSackBlock") .. "|r")

    tt:AddDoubleLine(
      ns.L["TooltipSend"] or "Send",
      Addon.db.profile.disableSend and "|cffff4444BLOCKED|r" or "|cff00ff00ALLOWED|r"
    )

    local nowTxt = blockedNow and (ns.L["TooltipBlockedNow"] or "Blocked now") or (ns.L["TooltipAllowedNow"] or "Allowed now")
    tt:AddDoubleLine(
      (ns.L["TooltipReceive"] or "Receive") .. " (" .. modeLabel(mode) .. ")",
      nowTxt
    )

    tt:AddDoubleLine(
      ns.L["TooltipReply"] or "Reply",
      yesno(Addon.db.profile.replyToSender)
    )

    tt:AddDoubleLine(
      ns.L["TooltipAltWipe"] or "Alt-wipe",
      yesno(Addon.db.profile.enableAltWipe)
    )
  end
end

function Addon:ApplyBugSackAltWipe()
  local enabled = self.db and self.db.profile and self.db.profile.enableAltWipe

  -- BugSack speichert altwipe in seinem SavedVars (BugSackDB.altwipe) und spiegelt es in addon.db.altwipe. [2](https://addons.wago.io/addons/buggrabber)
  if type(_G.BugSackDB) == "table" then
    _G.BugSackDB.altwipe = enabled and true or false
  end

  local BugSack = _G.BugSack
  if type(BugSack) == "table" and type(BugSack.db) == "table" then
    BugSack.db.altwipe = enabled and true or false
  end
end

function Addon:OnInitialize()
  self.db = LibStub("AceDB-3.0"):New("BugSackBlockDB", defaults, true)
  self:ApplyBugSackAltWipe()

  -- Slashcommands (4)
  self:RegisterChatCommand("bsb", "SlashCommand")
  self:RegisterChatCommand("bugsackblock", "SlashCommand")

  -- Falls BugSack schon geladen ist:
  self:PatchBugSack()

  -- Falls BugSack später lädt:
  self:RegisterEvent("ADDON_LOADED", function(_, name)
    if name == "BugSack" then
      self:PatchBugSack()
    end
  end)
end

function Addon:SlashCommand(input)
  input = (input or ""):trim()
  local cmd, rest = input:match("^(%S+)%s*(.-)$")
  cmd = cmd and cmd:lower() or ""
  rest = rest or ""

  if cmd == "" or cmd == "help" then
    self:Print(("/bsb %s:"):format(L["Commands"]))
    self:Print("/bsb status")
    self:Print("/bsb disablesend on|off")
    self:Print("/bsb receive off|always|combat|openworld")
    self:Print("/bsb reply on|off")
    self:Print("/bsb verbose on|off")
    self:Print("/bsb altwipe on|off")
    self:Print("/bsb tooltip on|off")
    return
  end

  if cmd == "status" then
    self:Print(("%s: disableSend=%s, receiveMode=%s, reply=%s"):format(
      L["Status"],
      tostring(self.db.profile.disableSend),
      tostring(self.db.profile.receiveMode),
      tostring(self.db.profile.replyToSender)
    ))
    return
  end

  if cmd == "disablesend" then
    local v = rest:lower()
    self.db.profile.disableSend = (v == "on" or v == "1" or v == "true")
    self:Print("disableSend=" .. tostring(self.db.profile.disableSend))
    return
  end

  if cmd == "receive" then
    local v = rest:lower()
    if v == "off" then self.db.profile.receiveMode = "OFF"
    elseif v == "always" then self.db.profile.receiveMode = "ALWAYS"
    elseif v == "combat" then self.db.profile.receiveMode = "COMBAT"
    elseif v == "openworld" then self.db.profile.receiveMode = "OPENWORLD"
    end
    self:Print("receiveMode=" .. tostring(self.db.profile.receiveMode))
    return
  end

  if cmd == "reply" then
    local v = rest:lower()
    self.db.profile.replyToSender = (v == "on" or v == "1" or v == "true")
    self:Print("replyToSender=" .. tostring(self.db.profile.replyToSender))
    return
  end

  if cmd == "verbose" then
    local v = rest:lower()
    self.db.profile.verbose = (v == "on" or v == "1" or v == "true")
    self:Print("verbose=" .. tostring(self.db.profile.verbose))
    return
  end

  if cmd == "altwipe" then
    local v = rest:lower()
    Addon.db.profile.enableAltWipe = (v == "on" or v == "1" or v == "true")
    Addon:ApplyBugSackAltWipe()
    Addon:Print("enableAltWipe=" .. tostring(Addon.db.profile.enableAltWipe))
    return
  end

  if cmd == "tooltip" then
    local v = rest:lower()
    Addon.db.profile.extendTooltip = (v == "on" or v == "1" or v == "true")
    if Addon.db.profile.extendTooltip then
        Addon:PatchBugSackTooltip()
    end
    Addon:Print("extendTooltip=" .. tostring(Addon.db.profile.extendTooltip))
    return
  end

  self:SlashCommand("help")
end