---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)

-- QUESTACCEPT-01..06: akzeptiert eine von einem Gruppenmitglied geteilte Quest
-- automatisch, sofern der Master aktiv ist, der Sharer eine Spielereinheit in der
-- Gruppe ist und (mit "Only from guild members and friends" aktiv) Gilden- oder
-- Freundschaftsmitglied ist. Deckt BEIDE Event-Pfade ab, auf denen eine geteilte
-- Quest ankommen kann. Das Feature ist vollständig lokal-only: keine Kommunikation,
-- kein Broadcast und keine UI-Erzeugung in dieser Datei.
--
-- Private.*-Abhängigkeiten:
--   Private.safecall (Utility.lua) -- Event-Dispatch-Trampolin.
--   Private.IsSecretValue (RosterKeys.lua) -- Schutz gegen Secret Values unter
--   Midnight-Taint: der Name/GUID eines anderen Spielers kann als Secret Value
--   ankommen, und ein Secret String wirft bei Indizierung statt nil zurückzugeben.
--
-- Der TOC-Slot ist load-bearing: Diese Datei muss nach Utility.lua (Private.safecall),
-- RosterKeys.lua (Private.IsSecretValue) und Migrations.lua (der
-- autoquestaccept-SavedVars-Blattknoten) geladen werden. Sie liegt unterhalb der
-- do-not-package-Grenze und bleibt deshalb in jedem Build enthalten; der Solo-Test
-- bleibt damit ebenfalls ungated.

local function ShouldAutoAccept(sharer)
    local settings = WildThingsSavedVars and WildThingsSavedVars.autoquestaccept
    if not settings or not settings.enabled then
        return false, "feature off"
    end

    -- Secret-value guard BEFORE any other use of sharer -- indexing/comparing a
    -- secret string raises instead of returning nil.
    if Private.IsSecretValue(sharer) then
        return false, "secret value"
    end
    if type(sharer) ~= "string" or sharer == "" then
        return false, "invalid sharer"
    end

    -- NPC-offer gate: without this, the master toggle silently becomes
    -- auto-accept-every-quest.
    if not UnitIsPlayer(sharer) then
        return false, "not a player share"
    end
    if not (UnitInParty(sharer) or UnitInRaid(sharer)) then
        return false, "not in group"
    end

    if not settings.friendsOnly then
        return true, "any group member"
    end

    if UnitIsInMyGuild(sharer) then
        return true, "guild member"
    end

    local guid = UnitGUID(sharer)
    if guid and not Private.IsSecretValue(guid) then
        if C_FriendList.IsFriend(guid) then
            return true, "character friend"
        end
        if C_BattleNet.GetAccountInfoByGUID(guid) then
            return true, "battle.net friend"
        end
    end

    return false, "not a guildmate or friend"
end

local questFrame = CreateFrame("Frame")

function questFrame:OnEvent(event, ...)
    Private.safecall(self[event], self, event, ...)
end

questFrame:SetScript("OnEvent", questFrame.OnEvent)
questFrame:RegisterEvent("QUEST_DETAIL")
questFrame:RegisterEvent("QUEST_ACCEPT_CONFIRM")

function questFrame:QUEST_DETAIL(event, ...)
    if not UnitExists("questnpc") then return end

    local sharer = UnitName("questnpc")
    local accept = ShouldAutoAccept(sharer)
    if not accept then return end

    if QuestGetAutoAccept() then
        -- The client already accepted the quest itself; accepting again is wrong.
        CloseQuest()
    else
        AcceptQuest()
    end

    print("|cff99ff00Wild Things:|r auto-accepted a quest shared by " .. tostring(sharer))
end

function questFrame:QUEST_ACCEPT_CONFIRM(event, name, questTitle)
    local accept = ShouldAutoAccept(name)
    if not accept then return end

    ConfirmAcceptQuest()
    -- Blizzard shows QUEST_ACCEPT normally and QUEST_ACCEPT_LOG_FULL when the quest
    -- log is full; hiding only the first leaves a dead popup on screen.
    StaticPopup_Hide("QUEST_ACCEPT")
    StaticPopup_Hide("QUEST_ACCEPT_LOG_FULL")

    print("|cff99ff00Wild Things:|r auto-accepted \"" .. tostring(questTitle)
        .. "\" shared by " .. tostring(name))
end

-- Private:AutoQuestAcceptTest(): unadvertised /wt questtest solo harness. This file
-- ships in every build, so the harness stays ungated; it crosses no trust boundary
-- and sends nothing. Testing against the player's own name makes the ladder
-- reachable by one person: own-name passes UnitIsPlayer, and its group / guild /
-- friend answers vary with real state, so the branches are observable solo.
function Private:AutoQuestAcceptTest()
    local playerName = UnitName("player")
    local accept, reason = ShouldAutoAccept(playerName)
    local settings = WildThingsSavedVars and WildThingsSavedVars.autoquestaccept or {}
    print("|cff99ff00Wild Things:|r questtest -- accept=" .. tostring(accept)
        .. " reason=" .. tostring(reason)
        .. " enabled=" .. tostring(settings.enabled)
        .. " friendsOnly=" .. tostring(settings.friendsOnly))
end
