local PT = AhUI
if not PT then return end

PT.ProfessionGuides_Waypoints = {}
local W = PT.ProfessionGuides_Waypoints
local L = PT.L or {}

local function T(key, default)
    return L[key] or default or key
end

local NPC_NAME_MISSING = {}
local npcNameCache = {}

local function ExtractTooltipName(tooltipData)
    if not tooltipData or not tooltipData.lines then
        return nil
    end

    for _, line in ipairs(tooltipData.lines) do
        local text = line.leftText

        if (not text or text == "") and line.args then
            for _, arg in ipairs(line.args) do
                if type(arg) == "table" then
                    text = arg.leftText or arg.text or arg.stringVal or arg.stringValue
                    if text and text ~= "" then
                        break
                    end
                end
            end
        end

        if text and text ~= "" and text ~= UNKNOWN and text ~= UNKNOWNOBJECT then
            return text
        end
    end

    return nil
end

function W:GetNPCNameByID(npcID)
    if not npcID then
        return nil
    end

    local cached = npcNameCache[npcID]
    if cached ~= nil then
        return cached ~= NPC_NAME_MISSING and cached or nil
    end

    local name = nil

    if C_TooltipInfo and C_TooltipInfo.GetHyperlink then
        local links = {
            string.format("unit:Creature-0-0-0-0-%d-0000000000", npcID),
            string.format("unit:Vehicle-0-0-0-0-%d-0000000000", npcID),
            string.format("unit:Creature-0-0-0-0-%d", npcID),
            string.format("unit:Vehicle-0-0-0-0-%d", npcID),
        }

        for _, hyperlink in ipairs(links) do
            local ok, tooltipData = pcall(C_TooltipInfo.GetHyperlink, hyperlink)
            if ok and tooltipData then
                name = ExtractTooltipName(tooltipData)
                if name then
                    break
                end
            end
        end
    end

    npcNameCache[npcID] = name or NPC_NAME_MISSING
    return name
end

function W:GetDisplayNameForRef(ref)
    if not ref then
        return nil
    end

    if ref.npcID then
        local resolved = self:GetNPCNameByID(ref.npcID)
        if resolved then
            ref.name = resolved
            return resolved
        end
    end

    if ref.name and ref.name ~= "" then
        return ref.name
    end

    return nil
end

function W:SetTrainerWaypoint(trainer)
    if not trainer
       or not trainer.mapID
       or not trainer.x
       or not trainer.y
    then
        print(T("PG_WP_ERR_NO_DATA", "AhUI: no data to place a waypoint"))
        return
    end

    local x = trainer.x / 100
    local y = trainer.y / 100

    if C_Map
       and C_Map.SetUserWaypoint
       and UiMapPoint
    then
        local point = UiMapPoint.CreateFromCoordinates(
            trainer.mapID,
            x,
            y
        )

        C_Map.SetUserWaypoint(point)
        C_SuperTrack.SetSuperTrackedUserWaypoint(true)
    end

    local displayName = self:GetDisplayNameForRef(trainer)

    if TomTom and TomTom.AddWaypoint then
        TomTom:AddWaypoint(
            trainer.mapID,
            x,
            y,
            {
                title      = displayName,
                persistent = false,
                minimap    = true,
                world      = true,
            }
        )
    end

    if displayName then
        print(T("PG_WP_SET", "Waypoint placed:"), displayName)
    end
end

function W:SetNPCWaypoint(ref)
    if not ref
       or not ref.mapID
       or not ref.x
       or not ref.y
    then
        print(T("PG_WP_ERR_NO_DATA", "AhUI: no data to place a waypoint"))
        return
    end

    local x = ref.x / 100
    local y = ref.y / 100

    if C_Map and C_Map.SetUserWaypoint and UiMapPoint then
        local point = UiMapPoint.CreateFromCoordinates(
            ref.mapID,
            x,
            y
        )
        C_Map.SetUserWaypoint(point)
        C_SuperTrack.SetSuperTrackedUserWaypoint(true)
    end

    local displayName = self:GetDisplayNameForRef(ref)

    if TomTom and TomTom.AddWaypoint then
        TomTom:AddWaypoint(
            ref.mapID,
            x,
            y,
            {
                title      = displayName,
                persistent = false,
                minimap    = true,
                world      = true,
            }
        )
    end

    if displayName then
        print(T("PG_WP_SET", "Waypoint placed:"), displayName)
    end
end
