-- Adapted from idQuestAutomation
local DGV = DugisGuideViewer
local AQA = DGV:RegisterModule("AutoQuestAccept")
AQA.essential = true
local _

function AQA:Initialize()
	AQA.completed_quests = {}
	AQA.incomplete_quests = {}	
	local RegisterReaction, DebugPrint = DGV.RegisterReaction, DGV.DebugPrint

	function AQA:canAutomate ()
		local target
		
		local guid = UnitGUID("target")
		if guid then
			target = DGV:GuidToNpcId(guid)
		else 
			target = 1
		end 
		
		local questId = GetQuestID()

		if IsShiftKeyDown() then
			return false
		elseif target ~= 45400 and 
			target ~= 64395 and
			target ~= 18166 and
			target ~= 87391 and
			target ~= 88570 and			
			target ~= 20235 and
			target ~= 111243			
			then
			if DGV:IsModuleLoaded("Guides") and DugisGuideViewer:UserSetting(DGV_AUTOQUESTACCEPTALL) and questId then
				local index = DGV:GetGuideIndexByQID(questId, "T") or DGV:GetGuideIndexByQID(questId, "A")
				if questId and index then
					return true
				else 
					return false
				end
			else
				return true
			end
		else
			return false		
		end
	end

	function AQA:strip_text (text)
		if not text then return end
		text = text:gsub('|c%x%x%x%x%x%x%x%x(.-)|r','%1')
		text = text:gsub('%[.*%]%s*','')
		text = text:gsub('(.+) %(.+%)', '%1')
		text = text:trim()
		return text
	end

	local function QUEST_PROGRESS ()
		DebugPrint("###QUEST_PROGRESS")
		if InCombatLockdown() then return end 
		--if not self:canAutomate() then return end
		if IsShiftKeyDown() then return end
		
		if not DugisGuideViewer:UserSetting(DGV_AUTOQUESTTURNIN) then return end
		if IsQuestCompletable() then
			CompleteQuest()
		end
	end

local function QUEST_LOG_UPDATE()
    DebugPrint("###QUEST_LOG_UPDATE")
    if InCombatLockdown() then return end
    if IsShiftKeyDown() then return end
    if not DugisGuideViewer:UserSetting(DGV_AUTOQUESTTURNIN) then return end

    -- Reset tables
    AQA.completed_quests = {}
    AQA.incomplete_quests = {}

    local numEntries = C_QuestLog.GetNumQuestLogEntries()
    if numEntries == 0 then return end

    for i = 1, numEntries do
        local info = C_QuestLog.GetInfo(i)
        if info and info.questID then
            local questID = info.questID
            local title   = info.title

            if title then
                local isComplete = C_QuestLog.IsComplete(questID)

                -- Retail: check objectives properly
                local objectives = C_QuestLog.GetQuestObjectives(questID)
                local noObjectives = (objectives == nil or #objectives == 0)

                -- Retail: some quests have no objectives but are not complete
                if isComplete or (noObjectives and info.isHeader ~= true) then
                    AQA.completed_quests[title] = true
                else
                    AQA.incomplete_quests[title] = true
                end
            end
        end
    end
end

local lastSelectedQuestID = nil
local lastSelectTime = 0

local function GOSSIP_SHOW()
    DebugPrint("###GOSSIP_SHOW")
    if InCombatLockdown() then return end
    if IsShiftKeyDown() then return end

    local now = GetTime()
	
    -- Auto-turn-in completed quests
    if DugisGuideViewer:UserSetting(DGV_AUTOQUESTTURNIN) then
        local active = C_GossipInfo.GetActiveQuests()
        for _, q in ipairs(active) do
            local title = AQA:strip_text(q.title)

            if AQA.completed_quests[title] then
                -- Prevent infinite loops
                if lastSelectedQuestID ~= q.questID or (now - lastSelectTime) > 0.3 then
                    lastSelectedQuestID = q.questID
                    lastSelectTime = now
                    C_GossipInfo.SelectActiveQuest(q.questID)
                end
            end
        end
			-- Auto-select campaign quest completions
		local options = C_GossipInfo.GetOptions()
		for _, opt in ipairs(options) do
			if opt.type == "quest" and opt.status == "complete" then
				C_GossipInfo.SelectOption(opt.gossipOptionID)
				return
			end
		end		
    end

    -- Auto-accept available quests
    if DugisGuideViewer:UserSetting(DGV_AUTOQUESTACCEPT) then
        local available = C_GossipInfo.GetAvailableQuests()
        for _, q in ipairs(available) do
            local title = AQA:strip_text(q.title)
            if not AQA.incomplete_quests[title] then
                C_GossipInfo.SelectAvailableQuest(q.questID)
            end
        end
    end
end


local function QUEST_DETAIL()
    DebugPrint("###QUEST_DETAIL")
    if InCombatLockdown() then return end
    if IsShiftKeyDown() then return end
    if not AQA:canAutomate() then return end
    if not DugisGuideViewer:UserSetting(DGV_AUTOQUESTACCEPT) then return end

    -- Retail: Auto-accept quests that show the detail frame
    local questID = GetQuestID()

    -- Some quests auto-accept without showing the detail window
    if QuestGetAutoAccept() then
        C_QuestLog.SetSelectedQuest(questID)
        CloseQuest()
        return
    end

    -- Standard accept
    AcceptQuest()

    -- Retail sometimes requires this to finalize selection
    if questID then
        C_QuestLog.SetSelectedQuest(questID)
    end
end


local function QUEST_COMPLETE()
    DebugPrint("###QUEST_COMPLETE")
    if InCombatLockdown() then return end
    if IsShiftKeyDown() then return end
    if not AQA:canAutomate() then return end
    if not DugisGuideViewer:UserSetting(DGV_AUTOQUESTTURNIN) then return end

    local numChoices = GetNumQuestChoices()

    -- Retail: If there is exactly 1 reward, auto-select it
    if numChoices == 1 then
        GetQuestReward(1)
        DugisGuideViewer:CompleteQuest()
        return
    end

    -- Retail: If there are no choices, just complete
    if numChoices == 0 then
        GetQuestReward(1) -- Retail still expects index 1 even with no choices
        DugisGuideViewer:CompleteQuest()
        return
    end

    -- Retail: If multiple choices exist, do NOT auto-select
    -- (Blizzard forbids auto-selecting multiple-choice rewards)
    DebugPrint("Multiple quest reward choices detected; waiting for manual selection.")
end

local function QUEST_GREETING()
    DebugPrint("###QUEST_GREETING")
    if InCombatLockdown() then return end
    if IsShiftKeyDown() then return end

    -- Auto-turn-in completed quests (Retail API still works)
    if DugisGuideViewer:UserSetting(DGV_AUTOQUESTTURNIN) then
        local active = C_GossipInfo.GetActiveQuests()
        for _, q in ipairs(active) do
            local title = AQA:strip_text(q.title)
            if AQA.completed_quests[title] then
                C_GossipInfo.SelectActiveQuest(q.questID)
                return
            end
        end
        
        local numActive = GetNumActiveQuests()
        if numActive and numActive > 0 then
            for i = 1, numActive do
                local title, isComplete = GetActiveTitle(i)
                title = AQA:strip_text(title)

                -- Turn-in campaign quest
                if isComplete then
                    DebugPrint("Selecting ACTIVE quest (complete): " .. tostring(title))
                    SelectActiveQuest(i)
                    return
                end
            end
        end        
    end
    if DugisGuideViewer:UserSetting(DGV_AUTOQUESTACCEPT) then
		local numAvailable = GetNumAvailableQuests()
		for i = 1, numAvailable do
			local title, _, _, _, _, questID = GetAvailableQuestInfo(i)
			title = AQA:strip_text(title)
	
			if not AQA.incomplete_quests[title] then
				SelectAvailableQuest(i)
			end
		end
	 	local available = C_GossipInfo.GetAvailableQuests()
        for _, q in ipairs(available) do
            local title = AQA:strip_text(q.title)
            if not AQA.incomplete_quests[title] then
                C_GossipInfo.SelectAvailableQuest(q.questID)
            end
        end			
	end			
end

	local gossipReaction, questCompleteReaction, questDetailReaction, questGreetingReaction, questLogReaction, questProgressReaction
	function AQA:Load( )
		gossipReaction = RegisterReaction('GOSSIP_SHOW', nil, GOSSIP_SHOW) --Fired when you talk to an npc, lists quests
		questCompleteReaction = RegisterReaction('QUEST_COMPLETE', nil, QUEST_COMPLETE) --Fired after the player hits the "Continue" button in the quest-information page, before the "Complete Quest" button.
		questDetailReaction = RegisterReaction('QUEST_DETAIL', nil, QUEST_DETAIL) --Fired when the player is given a more detailed view of his quest.
		questGreetingReaction = RegisterReaction('QUEST_GREETING', nil, QUEST_GREETING) --Fired when talking to an NPC that offers or accepts more than one quest, i.e. has more than one active or available quest. turn in and accept
		questLogReaction = RegisterReaction('QUEST_LOG_UPDATE', nil, QUEST_LOG_UPDATE)
		questProgressReaction = RegisterReaction('QUEST_PROGRESS', nil, QUEST_PROGRESS)--Fired when a player is talking to an NPC about the status of a quest and has not yet clicked the complete button.
	end

	function AQA:Unload( )
		gossipReaction:Dispose()
		questCompleteReaction:Dispose()
		questDetailReaction:Dispose()
		questGreetingReaction:Dispose()
		questLogReaction:Dispose()
		questProgressReaction:Dispose()
	end
end