local _, ns = ...
local L = ns.L or {}
local Quest = ns.Quest or {}

local FEATURE_ID = "auto_accept_quests"
local SELECT_DELAY_SECONDS = 0.06
local ACCEPT_DELAY_SECONDS = 0.05
local TURNIN_DELAY_SECONDS = 0.05
local DECLINE_PAUSE_SECONDS = 10
local GOSSIP_RETRY_SECONDS = 0.20
local GOSSIP_ATTEMPT_TTL_SECONDS = 3
local TURNIN_ATTEMPT_TTL_SECONDS = 3

local AutoAcceptQuestsRuntime = {
    enabled = false,
    eventFrame = nil,
    selectToken = 0,
    acceptToken = 0,
    progressToken = 0,
    rewardToken = 0,
    hookedDecline = false,
    declinePauseUntil = 0,
    attemptedGossipQuestIDs = {},
    attemptedTurnInQuestIDs = {},
}

local function now()
    return (GetTime and GetTime()) or 0
end

local function toNumber(value)
    if value == nil then
        return nil
    end

    return tonumber(value)
end

local function isAltPauseActive()
    return type(IsAltKeyDown) == "function" and IsAltKeyDown() == true
end

local function shouldSkipTrivialQuests()
    return (ns.GetFeatureOptionValue and ns:GetFeatureOptionValue(FEATURE_ID, "trivial_quests") or "include") == "skip"
end

local function shouldAutoTurnInQuests()
    return (ns.GetFeatureOptionValue and ns:GetFeatureOptionValue(FEATURE_ID, "turn_in") or "off") == "on"
end

local function shouldPauseAutomation()
    if isAltPauseActive() then
        return true
    end

    return now() < (tonumber(AutoAcceptQuestsRuntime.declinePauseUntil) or 0)
end

local function getCurrentQuestID()
    if type(GetQuestID) ~= "function" then
        return nil
    end

    local ok, questID = pcall(GetQuestID)
    questID = ok and tonumber(questID) or nil
    return questID and questID > 0 and questID or nil
end

local function isQuestAlreadyAccepted(questID)
    questID = tonumber(questID)
    if not questID or questID <= 0 then
        return false
    end

    if C_QuestLog and type(C_QuestLog.IsOnQuest) == "function" then
        local ok, isOnQuest = pcall(C_QuestLog.IsOnQuest, questID)
        return ok and isOnQuest == true
    end

    return false
end

local function isQuestIgnored(questInfo)
    return type(questInfo) == "table" and (questInfo.isIgnored == true or questInfo.isHidden == true)
end

local function getQuestLogIndex(questID)
    questID = tonumber(questID)
    if not questID or questID <= 0 or not C_QuestLog or type(C_QuestLog.GetLogIndexForQuestID) ~= "function" then
        return nil
    end

    local ok, logIndex = pcall(C_QuestLog.GetLogIndexForQuestID, questID)
    logIndex = ok and tonumber(logIndex) or nil
    return logIndex and logIndex > 0 and logIndex or nil
end

local function getQuestLogInfo(questID)
    local logIndex = getQuestLogIndex(questID)
    if not logIndex or not C_QuestLog or type(C_QuestLog.GetInfo) ~= "function" then
        return nil
    end

    local ok, info = pcall(C_QuestLog.GetInfo, logIndex)
    return ok and type(info) == "table" and info or nil
end

local function getQuestFrequencyDefault()
    if Enum and Enum.QuestFrequency and tonumber(Enum.QuestFrequency.Default) then
        return tonumber(Enum.QuestFrequency.Default)
    end

    return 1
end

local function questInfoLooksRepeatable(questInfo)
    if type(questInfo) ~= "table" then
        return false
    end

    if questInfo.repeatable == true
        or questInfo.isRepeatable == true
        or questInfo.isDaily == true
        or questInfo.isWeekly == true
    then
        return true
    end

    local frequency = tonumber(questInfo.frequency or questInfo.questFrequency)
    if frequency and frequency > 0 and frequency ~= getQuestFrequencyDefault() then
        return true
    end

    return false
end

local function questLooksRepeatableOrNonDefault(questID, questInfo)
    if questInfoLooksRepeatable(questInfo) then
        return true
    end

    return questInfoLooksRepeatable(getQuestLogInfo(questID))
end

local function callNumber(fn, ...)
    if type(fn) ~= "function" then
        return nil
    end

    local ok, value = pcall(fn, ...)
    value = ok and tonumber(value) or nil
    return value
end

local function hasQuestRequiredMoney(questID)
    local currentRequiredMoney = callNumber(GetQuestMoneyToGet)
    if currentRequiredMoney and currentRequiredMoney > 0 then
        return true
    end

    if type(GetQuestLogRequiredMoney) == "function" then
        local logIndex = getQuestLogIndex(questID)
        local requiredMoney = logIndex and callNumber(GetQuestLogRequiredMoney, logIndex) or nil
        requiredMoney = requiredMoney or callNumber(GetQuestLogRequiredMoney)
        if requiredMoney and requiredMoney > 0 then
            return true
        end
    end

    return false
end

local function getQuestCount(fn, kind)
    if type(fn) ~= "function" then
        return nil
    end

    local ok, count = pcall(fn, kind)
    count = ok and tonumber(count) or nil
    return count
end

local function hasRequiredQuestItemsOrCurrencies()
    local requiredKinds = { "required", "require", "requiredItem", "requiredCurrency" }
    for _, kind in ipairs(requiredKinds) do
        local itemCount = getQuestCount(GetNumQuestItems, kind)
        if itemCount and itemCount > 0 then
            return true
        end

        local currencyCount = getQuestCount(GetNumQuestCurrencies, kind)
        if currencyCount and currencyCount > 0 then
            return true
        end
    end

    return false
end

local function getNumQuestChoicesSafe()
    if type(GetNumQuestChoices) ~= "function" then
        return nil
    end

    local ok, count = pcall(GetNumQuestChoices)
    return ok and tonumber(count) or nil
end

local function isSafeQuestForAutomation(questID, questInfo)
    questID = tonumber(questID)
    if not questID or questID <= 0 then
        return false
    end

    return not questLooksRepeatableOrNonDefault(questID, questInfo)
end

local function isSafeQuestForAutoTurnIn(questID, questInfo)
    if not isSafeQuestForAutomation(questID, questInfo) then
        return false
    end

    local choiceCount = getNumQuestChoicesSafe()
    if choiceCount and choiceCount > 0 then
        return false
    end

    if hasQuestRequiredMoney(questID) or hasRequiredQuestItemsOrCurrencies() then
        return false
    end

    return true
end

local function isQuestReadyForTurnIn(questID)
    questID = tonumber(questID)
    if not questID or questID <= 0 then
        return false
    end

    if type(Quest.IsQuestTurnInReady) == "function" then
        local okReady, ready = pcall(Quest.IsQuestTurnInReady, questID)
        if okReady and ready == true then
            return true
        end
    end

    if C_QuestLog and type(C_QuestLog.ReadyForTurnIn) == "function" then
        local okReady, ready = pcall(C_QuestLog.ReadyForTurnIn, questID)
        if okReady and ready == true then
            return true
        end
    end

    if C_QuestLog and type(C_QuestLog.GetLogIndexForQuestID) == "function" and type(GetQuestLogIsComplete) == "function" then
        local okIndex, logIndex = pcall(C_QuestLog.GetLogIndexForQuestID, questID)
        logIndex = okIndex and tonumber(logIndex) or nil
        if logIndex and logIndex > 0 then
            local okComplete, isComplete = pcall(GetQuestLogIsComplete, logIndex)
            if okComplete and isComplete == true then
                return true
            end
        end
    end

    return false
end

local function markGossipQuestAttempt(questID)
    questID = tonumber(questID)
    if questID and questID > 0 then
        AutoAcceptQuestsRuntime.attemptedGossipQuestIDs[questID] = now()
    end
end

local function markTurnInQuestAttempt(questID)
    questID = tonumber(questID)
    if questID and questID > 0 then
        AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs[questID] = now()
    end
end

local function clearOldGossipAttempts()
    local currentTime = now()
    for questID, attemptedAt in pairs(AutoAcceptQuestsRuntime.attemptedGossipQuestIDs) do
        if (currentTime - (tonumber(attemptedAt) or 0)) > GOSSIP_ATTEMPT_TTL_SECONDS then
            AutoAcceptQuestsRuntime.attemptedGossipQuestIDs[questID] = nil
        end
    end
end

local function clearOldTurnInAttempts()
    local currentTime = now()
    for questID, attemptedAt in pairs(AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs) do
        if (currentTime - (tonumber(attemptedAt) or 0)) > TURNIN_ATTEMPT_TTL_SECONDS then
            AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs[questID] = nil
        end
    end
end

local function wasGossipQuestRecentlyAttempted(questID)
    questID = tonumber(questID)
    if not questID or questID <= 0 then
        return false
    end

    local attemptedAt = tonumber(AutoAcceptQuestsRuntime.attemptedGossipQuestIDs[questID])
    return attemptedAt ~= nil and (now() - attemptedAt) <= GOSSIP_ATTEMPT_TTL_SECONDS
end

local function wasTurnInQuestRecentlyAttempted(questID)
    questID = tonumber(questID)
    if not questID or questID <= 0 then
        return false
    end

    local attemptedAt = tonumber(AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs[questID])
    return attemptedAt ~= nil and (now() - attemptedAt) <= TURNIN_ATTEMPT_TTL_SECONDS
end

local function questInfoAllowed(questInfo)
    if type(questInfo) ~= "table" then
        return false
    end

    local questID = tonumber(questInfo.questID)
    if not questID or questID <= 0 then
        return false
    end

    if isQuestAlreadyAccepted(questID) or wasGossipQuestRecentlyAttempted(questID) or isQuestIgnored(questInfo) then
        return false
    end

    if shouldSkipTrivialQuests() and questInfo.isTrivial == true then
        return false
    end

    if not isSafeQuestForAutomation(questID, questInfo) then
        return false
    end

    return true
end

local function activeQuestInfoAllowed(questInfo)
    if type(questInfo) ~= "table" then
        return false
    end

    local questID = tonumber(questInfo.questID)
    if not questID or questID <= 0 then
        return false
    end

    if wasTurnInQuestRecentlyAttempted(questID) or isQuestIgnored(questInfo) then
        return false
    end

    if shouldSkipTrivialQuests() and questInfo.isTrivial == true then
        return false
    end

    if not isSafeQuestForAutoTurnIn(questID, questInfo) then
        return false
    end

    return questInfo.isComplete == true or isQuestReadyForTurnIn(questID)
end

local function getAvailableGossipQuests()
    if not C_GossipInfo or type(C_GossipInfo.GetAvailableQuests) ~= "function" then
        return nil
    end

    local ok, quests = pcall(C_GossipInfo.GetAvailableQuests)
    if ok and type(quests) == "table" then
        return quests
    end

    return nil
end

local function getActiveGossipQuests()
    if not C_GossipInfo or type(C_GossipInfo.GetActiveQuests) ~= "function" then
        return nil
    end

    local ok, quests = pcall(C_GossipInfo.GetActiveQuests)
    if ok and type(quests) == "table" then
        return quests
    end

    return nil
end

local function selectAvailableGossipQuest(index, questInfo)
    if type(questInfo) ~= "table" then
        return false
    end

    local questID = tonumber(questInfo.questID)
    if C_GossipInfo and type(C_GossipInfo.SelectAvailableQuest) == "function" and questID and questID > 0 then
        markGossipQuestAttempt(questID)
        local ok = pcall(C_GossipInfo.SelectAvailableQuest, questID)
        if ok then
            return true
        end
    end

    if type(SelectAvailableQuest) == "function" then
        markGossipQuestAttempt(questID)
        local ok = pcall(SelectAvailableQuest, index)
        return ok == true
    end

    return false
end

local function selectActiveGossipQuest(index, questInfo)
    if type(questInfo) ~= "table" then
        return false
    end

    local questID = tonumber(questInfo.questID)
    if C_GossipInfo and type(C_GossipInfo.SelectActiveQuest) == "function" and questID and questID > 0 then
        markTurnInQuestAttempt(questID)
        local ok = pcall(C_GossipInfo.SelectActiveQuest, questID)
        if ok then
            return true
        end
    end

    if type(SelectActiveQuest) == "function" then
        markTurnInQuestAttempt(questID)
        local ok = pcall(SelectActiveQuest, index)
        return ok == true
    end

    return false
end

local function selectLegacyActiveQuest()
    if not shouldAutoTurnInQuests() or type(GetNumActiveQuests) ~= "function" or type(GetActiveQuestID) ~= "function" or type(SelectActiveQuest) ~= "function" then
        return false
    end

    local okCount, count = pcall(GetNumActiveQuests)
    count = okCount and tonumber(count) or 0
    if count <= 0 then
        return false
    end

    local allowedIndex
    local allowedQuestID
    local allowedCount = 0

    for index = 1, count do
        local okQuestID, questID = pcall(GetActiveQuestID, index)
        questID = okQuestID and tonumber(questID) or nil
        if questID
            and questID > 0
            and not wasTurnInQuestRecentlyAttempted(questID)
            and isSafeQuestForAutoTurnIn(questID)
            and isQuestReadyForTurnIn(questID)
        then
            allowedCount = allowedCount + 1
            allowedIndex = index
            allowedQuestID = questID
        end
    end

    if allowedCount ~= 1 or not allowedIndex or not allowedQuestID then
        return false
    end

    markTurnInQuestAttempt(allowedQuestID)
    local okSelect = pcall(SelectActiveQuest, allowedIndex)
    return okSelect == true
end

local function selectLegacyGreetingQuest()
    if type(GetNumAvailableQuests) ~= "function" or type(GetAvailableQuestInfo) ~= "function" or type(SelectAvailableQuest) ~= "function" then
        return false
    end

    local okCount, count = pcall(GetNumAvailableQuests)
    count = okCount and tonumber(count) or 0
    if count <= 0 then
        return false
    end

    for index = 1, count do
        local okInfo, _, isTrivial, _, _, questID = pcall(GetAvailableQuestInfo, index)
        questID = okInfo and tonumber(questID) or nil
        if okInfo
            and (not questID or not isQuestAlreadyAccepted(questID))
            and (not questID or not wasGossipQuestRecentlyAttempted(questID))
            and (not shouldSkipTrivialQuests() or isTrivial ~= true)
            and (not questID or isSafeQuestForAutomation(questID))
        then
            markGossipQuestAttempt(questID)
            local okSelect = pcall(SelectAvailableQuest, index)
            return okSelect == true
        end
    end

    return false
end

function AutoAcceptQuestsRuntime:SelectNextGossipQuest()
    if not self.enabled or shouldPauseAutomation() then
        return false
    end

    clearOldGossipAttempts()
    clearOldTurnInAttempts()

    if shouldAutoTurnInQuests() then
        local activeQuests = getActiveGossipQuests()
        local allowedIndex
        local allowedQuestInfo
        local allowedCount = 0

        for index, questInfo in ipairs(activeQuests or {}) do
            if activeQuestInfoAllowed(questInfo) then
                allowedCount = allowedCount + 1
                allowedIndex = index
                allowedQuestInfo = questInfo
            end
        end

        if allowedCount == 1 and allowedIndex and allowedQuestInfo then
            return selectActiveGossipQuest(allowedIndex, allowedQuestInfo)
        end

        if selectLegacyActiveQuest() then
            return true
        end
    end

    local quests = getAvailableGossipQuests()
    for index, questInfo in ipairs(quests or {}) do
        if questInfoAllowed(questInfo) then
            return selectAvailableGossipQuest(index, questInfo)
        end
    end

    return selectLegacyGreetingQuest()
end

function AutoAcceptQuestsRuntime:QueueSelectGossipQuest(delay)
    if not self.enabled then
        return
    end

    self.selectToken = self.selectToken + 1
    local token = self.selectToken
    local function runIfCurrent()
        if token == AutoAcceptQuestsRuntime.selectToken then
            AutoAcceptQuestsRuntime:SelectNextGossipQuest()
        end
    end

    if C_Timer and type(C_Timer.After) == "function" then
        C_Timer.After(tonumber(delay) or SELECT_DELAY_SECONDS, runIfCurrent)
    else
        runIfCurrent()
    end
end

local function completeProgressQuest()
    if not shouldAutoTurnInQuests() or shouldPauseAutomation() then
        return false
    end

    local questID = getCurrentQuestID()
    if not wasTurnInQuestRecentlyAttempted(questID) or not isSafeQuestForAutoTurnIn(questID) then
        return false
    end

    if type(IsQuestCompletable) == "function" then
        local okCompletable, isCompletable = pcall(IsQuestCompletable)
        if not okCompletable or isCompletable ~= true then
            return false
        end
    end

    if type(CompleteQuest) == "function" then
        local ok = pcall(CompleteQuest)
        return ok == true
    end

    return false
end

function AutoAcceptQuestsRuntime:QueueCompleteProgressQuest(delay)
    if not self.enabled then
        return
    end

    self.progressToken = self.progressToken + 1
    local token = self.progressToken
    local function runIfCurrent()
        if token == AutoAcceptQuestsRuntime.progressToken then
            completeProgressQuest()
        end
    end

    if C_Timer and type(C_Timer.After) == "function" then
        C_Timer.After(tonumber(delay) or TURNIN_DELAY_SECONDS, runIfCurrent)
    else
        runIfCurrent()
    end
end

local function rewardCurrentQuest()
    if not shouldAutoTurnInQuests() or shouldPauseAutomation() then
        return false
    end

    local questID = getCurrentQuestID()
    if not wasTurnInQuestRecentlyAttempted(questID) or not isSafeQuestForAutoTurnIn(questID) then
        return false
    end

    local choiceCount = getNumQuestChoicesSafe()
    if not choiceCount or choiceCount > 0 then
        return false
    end

    if type(GetQuestReward) ~= "function" then
        return false
    end

    local rewardIndex = 1
    local itemChoice = toNumber(QuestInfoFrame and QuestInfoFrame.itemChoice)
    if itemChoice and itemChoice > 0 then
        rewardIndex = math.max(itemChoice, 1)
    end

    local ok = pcall(GetQuestReward, rewardIndex)
    if ok then
        return true
    end

    local okNoArg = pcall(GetQuestReward)
    return okNoArg == true
end

function AutoAcceptQuestsRuntime:QueueRewardQuest(delay)
    if not self.enabled then
        return
    end

    self.rewardToken = self.rewardToken + 1
    local token = self.rewardToken
    local function runIfCurrent()
        if token == AutoAcceptQuestsRuntime.rewardToken then
            rewardCurrentQuest()
        end
    end

    if C_Timer and type(C_Timer.After) == "function" then
        C_Timer.After(tonumber(delay) or TURNIN_DELAY_SECONDS, runIfCurrent)
    else
        runIfCurrent()
    end
end

local function acceptCurrentQuest()
    if shouldPauseAutomation() then
        return false
    end

    local questID = getCurrentQuestID()
    if questID and isQuestAlreadyAccepted(questID) then
        return false
    end

    if questID
        and (not isSafeQuestForAutomation(questID)
            or hasQuestRequiredMoney(questID)
            or hasRequiredQuestItemsOrCurrencies())
    then
        return false
    end

    if type(AcceptQuest) == "function" then
        local ok = pcall(AcceptQuest)
        if ok then
            return true
        end
    end

    if type(QuestDetailAcceptButton_OnClick) == "function" then
        local ok = pcall(QuestDetailAcceptButton_OnClick)
        return ok == true
    end

    return false
end

function AutoAcceptQuestsRuntime:QueueAcceptQuest(delay)
    if not self.enabled then
        return
    end

    self.acceptToken = self.acceptToken + 1
    local token = self.acceptToken
    local function runIfCurrent()
        if token == AutoAcceptQuestsRuntime.acceptToken then
            acceptCurrentQuest()
        end
    end

    if C_Timer and type(C_Timer.After) == "function" then
        C_Timer.After(tonumber(delay) or ACCEPT_DELAY_SECONDS, runIfCurrent)
    else
        runIfCurrent()
    end
end

function AutoAcceptQuestsRuntime:EnsureDeclineHook()
    if self.hookedDecline or type(hooksecurefunc) ~= "function" or type(DeclineQuest) ~= "function" then
        return
    end

    self.hookedDecline = true
    pcall(hooksecurefunc, "DeclineQuest", function()
        AutoAcceptQuestsRuntime.declinePauseUntil = now() + DECLINE_PAUSE_SECONDS
    end)
end

function AutoAcceptQuestsRuntime:EnsureEventFrame()
    if self.eventFrame then
        return self.eventFrame
    end

    self.eventFrame = CreateFrame("Frame")
    self.eventFrame:SetScript("OnEvent", function(_, event, ...)
        if event == "GOSSIP_SHOW" or event == "QUEST_GREETING" then
            AutoAcceptQuestsRuntime:QueueSelectGossipQuest(SELECT_DELAY_SECONDS)
        elseif event == "QUEST_DETAIL" then
            AutoAcceptQuestsRuntime:QueueAcceptQuest(ACCEPT_DELAY_SECONDS)
        elseif event == "QUEST_PROGRESS" then
            AutoAcceptQuestsRuntime:QueueCompleteProgressQuest(TURNIN_DELAY_SECONDS)
        elseif event == "QUEST_COMPLETE" then
            AutoAcceptQuestsRuntime:QueueRewardQuest(TURNIN_DELAY_SECONDS)
        elseif event == "QUEST_ACCEPTED" then
            local firstArg, secondArg = ...
            local questID = toNumber(secondArg) or toNumber(firstArg)
            if questID and questID > 0 then
                AutoAcceptQuestsRuntime.attemptedGossipQuestIDs[questID] = nil
            end
            AutoAcceptQuestsRuntime:QueueSelectGossipQuest(GOSSIP_RETRY_SECONDS)
        elseif event == "QUEST_TURNED_IN" then
            local firstArg = ...
            local questID = toNumber(firstArg)
            if questID and questID > 0 then
                AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs[questID] = nil
            end
        elseif event == "QUEST_FINISHED" then
            AutoAcceptQuestsRuntime.selectToken = AutoAcceptQuestsRuntime.selectToken + 1
            AutoAcceptQuestsRuntime.acceptToken = AutoAcceptQuestsRuntime.acceptToken + 1
            AutoAcceptQuestsRuntime.progressToken = AutoAcceptQuestsRuntime.progressToken + 1
            AutoAcceptQuestsRuntime.rewardToken = AutoAcceptQuestsRuntime.rewardToken + 1
            wipe(AutoAcceptQuestsRuntime.attemptedGossipQuestIDs)
            wipe(AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs)
            AutoAcceptQuestsRuntime:QueueSelectGossipQuest(GOSSIP_RETRY_SECONDS)
        elseif event == "GOSSIP_CLOSED" then
            AutoAcceptQuestsRuntime.selectToken = AutoAcceptQuestsRuntime.selectToken + 1
            AutoAcceptQuestsRuntime.acceptToken = AutoAcceptQuestsRuntime.acceptToken + 1
            AutoAcceptQuestsRuntime.progressToken = AutoAcceptQuestsRuntime.progressToken + 1
            AutoAcceptQuestsRuntime.rewardToken = AutoAcceptQuestsRuntime.rewardToken + 1
            wipe(AutoAcceptQuestsRuntime.attemptedGossipQuestIDs)
            wipe(AutoAcceptQuestsRuntime.attemptedTurnInQuestIDs)
        end
    end)

    return self.eventFrame
end

function AutoAcceptQuestsRuntime:SetEnabled(enabled)
    enabled = enabled == true
    self.enabled = enabled
    self:EnsureDeclineHook()

    local eventFrame = self:EnsureEventFrame()
    eventFrame:UnregisterAllEvents()

    self.selectToken = self.selectToken + 1
    self.acceptToken = self.acceptToken + 1
    self.progressToken = self.progressToken + 1
    self.rewardToken = self.rewardToken + 1
    wipe(self.attemptedGossipQuestIDs)
    wipe(self.attemptedTurnInQuestIDs)

    if not enabled then
        return
    end

    eventFrame:RegisterEvent("GOSSIP_SHOW")
    eventFrame:RegisterEvent("GOSSIP_CLOSED")
    eventFrame:RegisterEvent("QUEST_GREETING")
    eventFrame:RegisterEvent("QUEST_DETAIL")
    eventFrame:RegisterEvent("QUEST_PROGRESS")
    eventFrame:RegisterEvent("QUEST_COMPLETE")
    eventFrame:RegisterEvent("QUEST_ACCEPTED")
    eventFrame:RegisterEvent("QUEST_TURNED_IN")
    eventFrame:RegisterEvent("QUEST_FINISHED")
end

ns:RegisterFeatureDefinition(FEATURE_ID, {
    id = FEATURE_ID,
    order = 29,
    category = "quick_tools",
    title = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TITLE or "Auto-Accept Quests" end,
    description = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_DESCRIPTION or "Automatically accepts available quests from NPCs and quest detail windows." end,
    note = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_NOTE or "Accepts quests automatically. Optional turn-in only completes quests without reward choices. Hold Alt to pause temporarily." end,
    previewLabel = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_PREVIEW_LABEL or "Quest NPC" end,
    previewNote = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_PREVIEW_NOTE or "Opens available NPC quests and accepts the quest detail window automatically." end,
    optionToggle = {
        key = "trivial_quests",
        label = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TRIVIAL_LABEL or "Low Level" end,
        values = { "include", "skip" },
        defaultValue = "include",
        valueLabels = {
            include = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TRIVIAL_INCLUDE or "All" end,
            skip = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TRIVIAL_SKIP or "Skip Gray" end,
        },
    },
    secondaryOptionToggle = {
        key = "turn_in",
        label = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TURNIN_LABEL or "Turn-In" end,
        values = { "off", "on" },
        defaultValue = "off",
        valueLabels = {
            off = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TURNIN_OFF or "Accept Only" end,
            on = function() return L.FEATURE_AUTO_ACCEPT_QUESTS_TURNIN_ON or "Turn-In On" end,
        },
    },
    requiresReload = false,
    apply = function(isEnabled)
        AutoAcceptQuestsRuntime:SetEnabled(isEnabled == true)
    end,
})
