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

local C_Timer = C_Timer
local C_UnitAuras = C_UnitAuras
local CreateFrame = CreateFrame
local GetTime = GetTime
local PlaySoundFile = PlaySoundFile

local LUST_CHECK_INTERVAL = 0.2
local LUST_TRIGGER_COOLDOWN = 5
local LUST_DURATION = 40
local ZONE_STABLE_CHECKS = 10
local DEFAULT_SOUND = addon.brand .. " Drop It (short)"
local NONE_SOUND = "None"

local lustFrame = CreateFrame("Frame")
local lustElapsed = 0
local lustActive = false
local justZoned = true
local stableCount = 0
local lustStartTime
local lustTimerTestMode = false

local SATED_IDS = {
    [57724] = true,
    [57723] = true,
    [80354] = true,
    [390435] = true,
    [264689] = true,
}

local BUILT_IN_SOUNDS = {
    [addon.brand .. " Drop It (short)"] = "Interface\\AddOns\\HLYqol\\Assets\\LustAlert\\drop_it_short.ogg",
    [addon.brand .. " Drop It (long)"] = "Interface\\AddOns\\HLYqol\\Assets\\LustAlert\\drop_it_long.ogg",
    ["HLYlust: Drop It (short)"] = "Interface\\AddOns\\HLYqol\\Assets\\LustAlert\\drop_it_short.ogg",
    ["HLYlust: Drop It (long)"] = "Interface\\AddOns\\HLYqol\\Assets\\LustAlert\\drop_it_long.ogg",
}

local function GetLustAlertDB(self)
    return self.db and self.db.lustAlert
end

function HLY:EnsureLustAlertDefaults()
    local db = GetLustAlertDB(self)
    if not db then
        return
    end

    db.timer = db.timer or {}
    db.timer.font = db.timer.font or "Homespun"
    db.timer.labelFontSize = db.timer.labelFontSize or 12
    db.timer.timerFontSize = db.timer.timerFontSize or 24
    db.timer.fontOutline = "SHADOWOUTLINE"
    db.timer.labelColor = db.timer.labelColor or db.timer.color or { r = 1, g = 0.819608, b = 0.2 }
    db.timer.timerColor = db.timer.timerColor or db.timer.color or { r = 1, g = 0.819608, b = 0.2 }
    db.timer.color = nil
    db.timer.xOffset = db.timer.xOffset or 0
    db.timer.yOffset = db.timer.yOffset or 180
end

local function HasSatedAura()
    if not C_UnitAuras or not C_UnitAuras.GetPlayerAuraBySpellID then
        return false
    end

    for spellID in pairs(SATED_IDS) do
        if C_UnitAuras.GetPlayerAuraBySpellID(spellID) then
            return true
        end
    end

    return false
end

function HLY:GetLustAlertSoundList()
    local values = {
        [NONE_SOUND] = NONE_SOUND,
    }

    for soundName in pairs(BUILT_IN_SOUNDS) do
        if soundName:find("HLYlust", 1, true) == nil then
            values[soundName] = soundName
        end
    end

    if addon.LSM then
        for soundName in pairs(addon.LSM:HashTable("sound")) do
            values[soundName] = soundName
        end
    end

    return values
end

function HLY:PlayLustAlertSound(forcePlay)
    local db = GetLustAlertDB(self)
    if not db or (not db.enabled and not forcePlay) then
        return
    end

    local sound = db.sound or DEFAULT_SOUND
    if sound == NONE_SOUND then
        return
    end

    local path
    if BUILT_IN_SOUNDS[sound] then
        path = BUILT_IN_SOUNDS[sound]
    elseif addon.LSM then
        path = addon.LSM:Fetch("sound", sound, true)
    end

    if path then
        PlaySoundFile(path, db.channel or "Master")
    end
end

function HLY:GetLustAlertTimerFrame()
    if self.lustAlertTimerFrame then
        return self.lustAlertTimerFrame
    end

    local frame = CreateFrame("Frame", nil, UIParent)
    frame:SetSize(120, 42)
    frame:SetFrameStrata("DIALOG")

    local label = frame:CreateFontString(nil, "OVERLAY")
    label:SetPoint("TOP", frame, "TOP", 0, 0)

    local timer = frame:CreateFontString(nil, "OVERLAY")
    timer:SetPoint("TOP", label, "BOTTOM", 0, -2)

    frame.label = label
    frame.timer = timer
    frame:Hide()
    self.lustAlertTimerFrame = frame
    self:UpdateLustAlertTimerStyle()
    label:SetText("Lust")
    return frame
end

function HLY:UpdateLustAlertTimerStyle()
    local frame = self.lustAlertTimerFrame
    local db = GetLustAlertDB(self)
    if not frame or not db then
        return
    end

    self:EnsureLustAlertDefaults()
    local timerDB = db.timer or {}
    local labelColor = timerDB.labelColor or {}
    local timerColor = timerDB.timerColor or {}

    frame:ClearAllPoints()
    frame:SetPoint("CENTER", UIParent, "CENTER", timerDB.xOffset or 0, timerDB.yOffset or 180)
    self:ApplyFont(frame.label, timerDB.font or "Homespun", timerDB.labelFontSize or 12, "SHADOWOUTLINE")
    self:ApplyFont(frame.timer, timerDB.font or "Homespun", timerDB.timerFontSize or 24, "SHADOWOUTLINE")
    frame.label:SetTextColor(labelColor.r or 1, labelColor.g or 0.819608, labelColor.b or 0.2)
    frame.timer:SetTextColor(timerColor.r or 1, timerColor.g or 0.819608, timerColor.b or 0.2)
end

function HLY:HideLustAlertTimer()
    lustStartTime = nil
    lustTimerTestMode = false
    if self.lustAlertTimerFrame then
        self.lustAlertTimerFrame:Hide()
    end
end

function HLY:StartLustAlertTimer(forceShow, testMode)
    local db = GetLustAlertDB(self)
    if not db or (not db.showTimer and not forceShow) then
        self:HideLustAlertTimer()
        return
    end

    lustTimerTestMode = testMode and true or false
    lustStartTime = GetTime()
    local frame = self:GetLustAlertTimerFrame()
    self:UpdateLustAlertTimerStyle()
    frame.timer:SetText(string.format("%.1f", LUST_DURATION))
    frame:Show()
end

function HLY:UpdateLustAlertTimer(active)
    if not lustStartTime then
        return
    end

    if not active and not lustTimerTestMode then
        self:HideLustAlertTimer()
        return
    end

    local remaining = LUST_DURATION - (GetTime() - lustStartTime)
    if remaining <= 0 then
        self:HideLustAlertTimer()
        return
    end

    local frame = self:GetLustAlertTimerFrame()
    frame.timer:SetText(string.format("%.1f", remaining))
    frame:Show()
end

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

    local now = GetTime()
    if self.lustAlertLastTrigger and (now - self.lustAlertLastTrigger) < LUST_TRIGGER_COOLDOWN then
        return
    end

    self.lustAlertLastTrigger = now
    self:PlayLustAlertSound()
    self:StartLustAlertTimer()
end

function HLY:UpdateLustAlert(delta)
    lustElapsed = lustElapsed + delta
    if lustElapsed < LUST_CHECK_INTERVAL then
        return
    end

    lustElapsed = 0

    local active = HasSatedAura()
    if justZoned then
        lustActive = active
        self:UpdateLustAlertTimer(active)
        stableCount = stableCount + 1
        if stableCount >= ZONE_STABLE_CHECKS then
            justZoned = false
        end
        return
    end

    if active and not lustActive then
        self:TriggerLustAlert()
    end

    self:UpdateLustAlertTimer(active)
    lustActive = active
end

function HLY:TestLustAlert()
    self:PlayLustAlertSound(true)
end

function HLY:TestLustAlertTimer()
    self:StartLustAlertTimer(true, true)
end

function HLY:HandleLustAlertEvent(event)
    if event == "PLAYER_ENTERING_WORLD" then
        justZoned = true
        stableCount = 0
        return
    end
end

function HLY:SetupLustAlert()
    if self.lustAlertSetup then
        return
    end

    self:EnsureLustAlertDefaults()
    lustFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
    lustFrame:SetScript("OnEvent", function(_, event)
        self:HandleLustAlertEvent(event)
    end)
    lustFrame:SetScript("OnUpdate", function(_, delta)
        self:UpdateLustAlert(delta)
    end)

    self.lustAlertSetup = true
end

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

function HLY:BuildLustAlertOptions(pane)
    pane:Note("Spielt einen Sound ab, wenn Bloodlust, Heroism, Time Warp, Trommeln oder vergleichbare Effekte genutzt werden.")
    pane:Checkbox({
        label = "Enable",
        get = function() return self.db.lustAlert.enabled end,
        set = function(v) self.db.lustAlert.enabled = v end,
    })
    pane:Section("Sound")
    pane:Dropdown({
        label = "Sound",
        values = function() return self:GetLustAlertSoundList() end, soundPreview = true,
        get = function() return self.db.lustAlert.sound end,
        set = function(v) self.db.lustAlert.sound = v end,
    })
    pane:Dropdown({
        label = "Audio Channel",
        values = LA_CHANNELS,
        get = function() return self.db.lustAlert.channel end,
        set = function(v) self.db.lustAlert.channel = v end,
    })
    pane:Button({ label = "Test Sound", func = function() self:TestLustAlert() end })

    pane:Section("Timer Text")
    pane:Checkbox({
        label = "Show Timer",
        get = function() return self.db.lustAlert.showTimer end,
        set = function(v)
            self.db.lustAlert.showTimer = v
            if not v then self:HideLustAlertTimer() end
        end,
    })
    pane:Dropdown({
        label = "Font", fontPreview = true,
        values = function() return self:GetFontList() end,
        get = function() self:EnsureLustAlertDefaults() return self.db.lustAlert.timer.font end,
        set = function(v) self:EnsureLustAlertDefaults() self.db.lustAlert.timer.font = v self:UpdateLustAlertTimerStyle() end,
    })
    pane:Row({
        function(c) c:Slider({ label = "Label Size", min = 8, max = 36, step = 1, labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() return self.db.lustAlert.timer.labelFontSize end,
            set = function(v) self:EnsureLustAlertDefaults() self.db.lustAlert.timer.labelFontSize = v self:UpdateLustAlertTimerStyle() end }) end,
        function(c) c:Slider({ label = "Timer Size", min = 10, max = 48, step = 1, labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() return self.db.lustAlert.timer.timerFontSize end,
            set = function(v) self:EnsureLustAlertDefaults() self.db.lustAlert.timer.timerFontSize = v self:UpdateLustAlertTimerStyle() end }) end,
    })
    pane:Row({
        function(c) c:Color({ label = "Label Color", labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() local k = self.db.lustAlert.timer.labelColor return k.r, k.g, k.b end,
            set = function(r, g, b) self:EnsureLustAlertDefaults() local k = self.db.lustAlert.timer.labelColor k.r, k.g, k.b = r, g, b self:UpdateLustAlertTimerStyle() end }) end,
        function(c) c:Color({ label = "Timer Color", labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() local k = self.db.lustAlert.timer.timerColor return k.r, k.g, k.b end,
            set = function(r, g, b) self:EnsureLustAlertDefaults() local k = self.db.lustAlert.timer.timerColor k.r, k.g, k.b = r, g, b self:UpdateLustAlertTimerStyle() end }) end,
    })
    pane:Row({
        function(c) c:Slider({ label = "X Offset", min = -600, max = 600, step = 1, labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() return self.db.lustAlert.timer.xOffset end,
            set = function(v) self:EnsureLustAlertDefaults() self.db.lustAlert.timer.xOffset = v self:UpdateLustAlertTimerStyle() end }) end,
        function(c) c:Slider({ label = "Y Offset", min = -400, max = 400, step = 1, labelWidth = 90,
            get = function() self:EnsureLustAlertDefaults() return self.db.lustAlert.timer.yOffset end,
            set = function(v) self:EnsureLustAlertDefaults() self.db.lustAlert.timer.yOffset = v self:UpdateLustAlertTimerStyle() end }) end,
    })
    pane:Button({ label = "Test Timer", func = function() self:TestLustAlertTimer() end })
end

addon.options = addon.options or {}
addon.options[#addon.options + 1] = {
    group = "Alerts", groupOrder = 300, name = "Lust Alert", order = 3,
    build = "BuildLustAlertOptions",
}
