local _, addon = ...
local HLY = addon.HLY

local C_Timer = C_Timer
local C_TooltipInfo = C_TooltipInfo
local CreateFrame = CreateFrame
local GetInventoryItemLink = GetInventoryItemLink
local GetInventorySlotInfo = GetInventorySlotInfo
local IsInInstance = IsInInstance
local PlaySoundFile = PlaySoundFile
local UIParent = UIParent

local DEFAULT_SOUND_NAME = addon.brand .. " Moment"
local NONE_SOUND = "None"
local screenFrame
local hideTimer

local EQUIPMENT_SLOTS = {
    { id = GetInventorySlotInfo("HeadSlot"), label = "Head" },
    { id = GetInventorySlotInfo("NeckSlot"), label = "Neck" },
    { id = GetInventorySlotInfo("ShoulderSlot"), label = "Shoulder" },
    { id = GetInventorySlotInfo("ChestSlot"), label = "Chest" },
    { id = GetInventorySlotInfo("WaistSlot"), label = "Waist" },
    { id = GetInventorySlotInfo("LegsSlot"), label = "Legs" },
    { id = GetInventorySlotInfo("FeetSlot"), label = "Feet" },
    { id = GetInventorySlotInfo("WristSlot"), label = "Wrist" },
    { id = GetInventorySlotInfo("HandsSlot"), label = "Hands" },
    { id = GetInventorySlotInfo("Finger0Slot"), label = "Finger 1" },
    { id = GetInventorySlotInfo("Finger1Slot"), label = "Finger 2" },
    { id = GetInventorySlotInfo("Trinket0Slot"), label = "Trinket 1" },
    { id = GetInventorySlotInfo("Trinket1Slot"), label = "Trinket 2" },
    { id = GetInventorySlotInfo("BackSlot"), label = "Back" },
    { id = GetInventorySlotInfo("MainHandSlot"), label = "Main Hand" },
    { id = GetInventorySlotInfo("SecondaryHandSlot"), label = "Off Hand" },
}

local function GetGearCheckDB(self)
    if self.db and not self.db.gearCheck and addon.P and addon.P.hlyqol and addon.P.hlyqol.gearCheck then
        self.db.gearCheck = self:CopyTable(addon.P.hlyqol.gearCheck)
    end

    return self.db and self.db.gearCheck
end

local function IsPvPTooltipText(text)
    if type(text) ~= "string" or text == "" then
        return false
    end

    local lowerText = text:lower()

    if lowerText:find("pvp item level", 1, true) then
        return true
    end

    if lowerText:find("pvp", 1, true) and lowerText:find("gegenstandsstufe", 1, true) then
        return true
    end

    if lowerText:find("arenas and battlegrounds", 1, true) then
        return true
    end

    if lowerText:find("arenen und schlachtfeldern", 1, true) then
        return true
    end

    if lowerText:find("pvp combat", 1, true) or lowerText:find("pvp%-kampf") or lowerText:find("pvp kampf", 1, true) then
        return true
    end

    if lowerText:find("gegenstandsstufe", 1, true)
        and (lowerText:find("arena", 1, true)
            or lowerText:find("schlachtfeld", 1, true)
            or lowerText:find("pvp", 1, true)) then
        return true
    end

    if lowerText:find("item level", 1, true)
        and (lowerText:find("arena", 1, true)
            or lowerText:find("battleground", 1, true)
            or lowerText:find("pvp", 1, true)) then
        return true
    end

    if lowerText:find("increases to", 1, true)
        and (lowerText:find("arena", 1, true)
            or lowerText:find("battleground", 1, true)
            or lowerText:find("pvp combat", 1, true)) then
        return true
    end

    if lowerText:find("ht sich", 1, true)
        and (lowerText:find("arena", 1, true)
            or lowerText:find("schlachtfeld", 1, true)
            or lowerText:find("pvp", 1, true)) then
        return true
    end

    return false
end

local function IsPvPInventoryItem(slotID)
    if not slotID or not C_TooltipInfo or not C_TooltipInfo.GetInventoryItem then
        return false
    end

    local tooltipData = C_TooltipInfo.GetInventoryItem("player", slotID)
    if not tooltipData or not tooltipData.lines then
        return false
    end

    for _, line in ipairs(tooltipData.lines) do
        if IsPvPTooltipText(line.leftText or line.text) or IsPvPTooltipText(line.rightText) then
            return true
        end
    end

    return false
end

function HLY:EnsureGearCheckDefaults()
    local db = GetGearCheckDB(self)
    if not db then
        return
    end

    if type(db.showChat) ~= "boolean" then
        db.showChat = true
    end

    if type(db.showScreen) ~= "boolean" then
        db.showScreen = true
    end

    if db.defaultSoundMigrated ~= true then
        if type(db.sound) ~= "string" or db.sound == "" or db.sound == NONE_SOUND then
            db.sound = DEFAULT_SOUND_NAME
        end

        db.defaultSoundMigrated = true
    elseif type(db.sound) ~= "string" or db.sound == "" then
        db.sound = DEFAULT_SOUND_NAME
    end

    if type(db.channel) ~= "string" or db.channel == "" then
        db.channel = "Master"
    end

    if type(db.duration) ~= "number" then
        db.duration = 5
    end

    db.text = db.text or {}
    db.text.font = db.text.font or "Homespun"
    db.text.fontSize = db.text.fontSize or 20
    db.text.fontOutline = "SHADOWOUTLINE"
    db.text.color = db.text.color or { r = 1, g = 0.2, b = 0.2 }
    db.point = db.point or "CENTER"
    db.xOffset = db.xOffset or 0
    db.yOffset = db.yOffset or 120
end

function HLY:GetPvPGearItems()
    local items = {}

    for _, slot in ipairs(EQUIPMENT_SLOTS) do
        if IsPvPInventoryItem(slot.id) then
            items[#items + 1] = GetInventoryItemLink("player", slot.id) or slot.label
        end
    end

    return items
end

function HLY:BuildGearCheckMessage(items, screenMessage)
    local count = #items
    local itemLabel = count == 1 and "item" or "items"

    if screenMessage then
        return string.format("PVP gear equipped (%d %s)", count, itemLabel)
    end

    return string.format("%s: PVP gear equipped (%d %s)", addon.displayName, count, itemLabel)
end

function HLY:UpdateGearCheckFrameStyle()
    if not screenFrame then
        return
    end

    self:EnsureGearCheckDefaults()
    local db = GetGearCheckDB(self)
    if not db then
        return
    end

    screenFrame:ClearAllPoints()
    self:SetPoint(screenFrame, db.point, db.xOffset, db.yOffset)
    self:ApplyFont(screenFrame.text, db.text.font, db.text.fontSize, "SHADOWOUTLINE")

    local color = db.text.color
    screenFrame.text:SetTextColor(color.r, color.g, color.b)
end

function HLY:GetGearCheckFrame()
    if screenFrame then
        return screenFrame
    end

    screenFrame = CreateFrame("Frame", "HLYqolGearCheckFrame", UIParent)
    screenFrame:SetSize(900, 80)
    screenFrame:SetFrameStrata("HIGH")
    screenFrame.text = screenFrame:CreateFontString(nil, "OVERLAY")
    screenFrame.text:SetPoint("CENTER")
    screenFrame.text:SetJustifyH("CENTER")
    screenFrame.text:SetJustifyV("MIDDLE")
    screenFrame.text:SetWordWrap(false)
    screenFrame:Hide()

    self:UpdateGearCheckFrameStyle()
    return screenFrame
end

function HLY:ShowGearCheckScreenMessage(message)
    local db = GetGearCheckDB(self)
    if not db or not db.showScreen then
        return
    end

    local frame = self:GetGearCheckFrame()
    self:UpdateGearCheckFrameStyle()
    frame.text:SetText(message)
    frame:Show()

    if hideTimer then
        hideTimer:Cancel()
    end

    hideTimer = C_Timer.NewTimer(db.duration or 5, function()
        if frame then
            frame:Hide()
        end
    end)
end

function HLY:PlayGearCheckSound()
    local db = GetGearCheckDB(self)
    if not db or db.sound == NONE_SOUND then
        return
    end

    local sound = db.sound or DEFAULT_SOUND_NAME
    local path = addon.LSM and addon.LSM:Fetch("sound", sound, true)
    if path then
        PlaySoundFile(path, db.channel or "Master")
    end
end

function HLY:RunGearCheck()
    local db = GetGearCheckDB(self)
    if not db or not db.enabled then
        return
    end

    self:EnsureGearCheckDefaults()

    local inInstance, instanceType = IsInInstance()
    if not inInstance or (instanceType ~= "party" and instanceType ~= "raid") then
        return
    end

    local items = self:GetPvPGearItems()
    if #items == 0 then
        return
    end

    local message = self:BuildGearCheckMessage(items)
    if db.showChat then
        print(message)
    end

    self:ShowGearCheckScreenMessage(self:BuildGearCheckMessage(items, true))
    self:PlayGearCheckSound()
end

function HLY:HandleGearCheckReadyCheck()
    C_Timer.After(0.2, function()
        self:RunGearCheck()
    end)
end

function HLY:ApplyGearCheckPreview()
    local db = GetGearCheckDB(self)
    if db and db.enabled and db.showScreen then
        if self.gearCheckPreviewActive then return end
        self.gearCheckPreviewActive = true
        local frame = self:GetGearCheckFrame()
        self:UpdateGearCheckFrameStyle()
        frame.text:SetText("PVP gear equipped (1 item)")
        frame:Show()
    else
        if not self.gearCheckPreviewActive then return end
        self.gearCheckPreviewActive = false
        if not hideTimer then
            local frame = self:GetGearCheckFrame()
            frame:Hide()
        end
    end
end

function HLY:ShowGearCheckPreview()
    self.gearCheckOptionsOpen = true
    self:ApplyGearCheckPreview()
end

function HLY:HideGearCheckPreview()
    self.gearCheckOptionsOpen = false
    if not self.gearCheckPreviewActive then return end
    self.gearCheckPreviewActive = false
    if hideTimer then return end
    local frame = self:GetGearCheckFrame()
    frame:Hide()
end

function HLY:UpdateGearCheckPreview()
    if self.gearCheckOptionsOpen then
        self:ApplyGearCheckPreview()
    end
end

function HLY:SetupGearCheck()
    if self.gearCheckInitialized then
        return
    end

    self:EnsureGearCheckDefaults()
    self:RegisterEvent("READY_CHECK", "HandleGearCheckReadyCheck")

    self.gearCheckInitialized = true
end

-- LibHLYUI options pane (v2) ------------------------------------------------
local GC_CHANNELS = { "Master", "SFX", "Music", "Ambience", "Dialog" }

function HLY:BuildGearCheckOptions(pane)
    pane:Note("Prüft beim Start eines Bereitschaftschecks die angelegte PvP-Ausrüstung (Jane Mode). Läuft nur in Dungeon- und Raidinstanzen.")
    pane:Checkbox({
        label = "Enable",
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.enabled end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.enabled = v self:UpdateGearCheckPreview() end,
    })
    pane:Section("Output")
    pane:Row({
        function(c) c:Checkbox({ label = "Chat", get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.showChat end, set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.showChat = v end }) end,
        function(c) c:Checkbox({ label = "Screen", get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.showScreen end, set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.showScreen = v self:UpdateGearCheckPreview() end }) end,
    })
    pane:Slider({
        label = "Duration", min = 1, max = 15, step = 0.5,
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.duration end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.duration = v end,
    })
    pane:Section("Sound")
    pane:Dropdown({
        label = "Sound",
        values = function() return self:GetSoundList() end, soundPreview = true,
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.sound end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.sound = v end,
    })
    pane:Dropdown({
        label = "Audio Channel",
        values = GC_CHANNELS,
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.channel end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.channel = v end,
    })
    pane:Section("Screen Text")
    pane:Dropdown({
        label = "Font", fontPreview = true,
        values = function() return self:GetFontList() end,
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.text.font end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.text.font = v self:UpdateGearCheckFrameStyle() end,
    })
    pane:Slider({
        label = "Font Size", min = 8, max = 48, step = 1,
        get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.text.fontSize end,
        set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.text.fontSize = v self:UpdateGearCheckFrameStyle() end,
    })
    pane:Color({
        label = "Color",
        get = function() self:EnsureGearCheckDefaults() local k = self.db.gearCheck.text.color return k.r, k.g, k.b end,
        set = function(r, g, b) self:EnsureGearCheckDefaults() local k = self.db.gearCheck.text.color k.r, k.g, k.b = r, g, b self:UpdateGearCheckFrameStyle() end,
    })
    pane:Row({
        function(c) c:Slider({ label = "X Offset", min = -600, max = 600, step = 1, labelWidth = 90,
            get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.xOffset end,
            set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.xOffset = v self:UpdateGearCheckFrameStyle() end }) end,
        function(c) c:Slider({ label = "Y Offset", min = -400, max = 400, step = 1, labelWidth = 90,
            get = function() self:EnsureGearCheckDefaults() return self.db.gearCheck.yOffset end,
            set = function(v) self:EnsureGearCheckDefaults() self.db.gearCheck.yOffset = v self:UpdateGearCheckFrameStyle() end }) end,
    })
end

addon.options = addon.options or {}
addon.options[#addon.options + 1] = {
    group = "Alerts", groupOrder = 300, name = "PvP Gear Check", order = 4,
    build = "BuildGearCheckOptions",
    onShow = "ShowGearCheckPreview", onHide = "HideGearCheckPreview",
}
