local PT = AhUI
if not PT then return end


PT.SkinningCheck = PT.SkinningCheck or {}
local SC = PT.SkinningCheck
local L  = PT.L

local function GetSkinningDisabledDB()
    PT.config.skinningDisabledTargets =
        PT.config.skinningDisabledTargets or {}
    return PT.config.skinningDisabledTargets
end

if AhUI_CharConfig and AhUI_CharConfig.skinningDisabledTargets then
    PT.config.skinningDisabledTargets =
        PT.config.skinningDisabledTargets or AhUI_CharConfig.skinningDisabledTargets
    AhUI_CharConfig.skinningDisabledTargets = nil
end

SC.SKINNING_SKILL_LINES = {
	2834, -- Skinning (DF)
    2882, -- Skinning (TWW)
    2917, -- Skinning (MIDNIGHT)
}
SC.ROOT_SKINNING_ID = 393

SC.TARGETS = {
	{
		id = "cobra_skin",
		questId = 74235,
		itemId  = 205413,
		guide = {
			lureItem = 193906,
            craftFrom = {
				{ id = 197741, count = 10 },
				},
			zone = {
                map = 2133,
                x = 0.4400,
                y = 0.4780,
			},
			npc = {
				id       = 204831,
				name     = L["npc_magma_cobra"],
				minLevel = 60,
			},
		},
	},
    {
        id = "slatefang",
        questId = 84259,
        itemId = 219013,
        guide = {
            lureItem = 219008,
            craftFrom = {
				{ id = 222739, count = 1 },
				},
            zone = {
                map = 2214,
                x = 0.5704,
                y = 0.4715,
            },
            npc = {
				id		 = 228439,
                name 	 = L["npc_slatefang"],
                minLevel = 71,
            },
        },
    },

    {
        id = "midnight_eversong_lure",
        questId = 88545,
        itemId  = 238652, -- Majestic Eversong Lure
        minExpansion = 12,
        guide = {
            lureItem = 238652,
            craftFrom = {
                { id = 238371, count = 8 },
                { id = 238366, count = 8 },
            },
            zone = {
                map = 2395, -- Eversong
                x = 0.42,
                y = 0.80,
            },
            npc = {
                id = 245688,
                name = L["npc_gloomclaw"],
                minLevel = 80,
            },
        },
    },

    {
        id = "midnight_zulaman_lure",
        questId = 88526,
        itemId  = 238653, -- Majestic Zul'Aman Lure
        minExpansion = 12,
        guide = {
            lureItem = 238653,
            craftFrom = {
                { id = 238382, count = 8 },
            },
            zone = {
                map = 2437, -- Zul'Aman
                x = 0.48,
                y = 0.54,
            },
            npc = {
                id = 245699,
                name = L["npc_silverscale"],
                minLevel = 80,
            },
        },
    },

    {
        id = "midnight_harandar_lure",
        questId = 88531,
        itemId  = 238654, -- Majestic Harandar Lure
        minExpansion = 12,
        guide = {
            lureItem = 238654,
            craftFrom = {
                { id = 238375, count = 8 },
                { id = 238374, count = 8 },
            },
            zone = {
                map = 2413, -- Harandar
                x = 0.66,
                y = 0.48,
            },
            npc = {
                id = 245690,
                name = L["npc_lumenfin"],
                minLevel = 80,
            },
        },
    },

    {
        id = "midnight_voidstorm_lure",
        questId = 88532,
        itemId  = 238655, -- Majestic Voidstorm Lure
        minExpansion = 12,
        guide = {
            lureItem = 238655,
            craftFrom = {
                { id = 238373, count = 4 },
            },
            zone = {
                map = 2405, -- Voidstorm
                x = 0.54,
                y = 0.65,
            },
            npc = {
                id = 247096,
                name = L["npc_umbrafang"],
                minLevel = 80,
            },
        },
    },


    {
        id = "midnight_grand_beast_lure",
        questId = 88524, -- unknown
        itemId  = 238656, -- Grand Beast Lure
        minExpansion = 12,
        guide = {
            lureItem = 238656,
            craftFrom = {
                { id = 238380, count = 4 },
            },
            zone = {
                map = 2405, -- Voidstorm
                x = 0.4325,
                y = 0.8275,
            },
            npc = {
                id = 247101,
                name = L["npc_netherscythe"],
                minLevel = 80,
            },
        },
    },

}

function SC:IsTargetAvailable(target)
    if not target then
        return false
    end

    if not target.minExpansion then
        return true
    end

    if target.minExpansion == 12 then
        return true
    end

    return GetExpansionLevel() >= target.minExpansion
end

function SC:GetTargetName(target)
    if not target then
        return L["Unknown"] or "Unknown"
    end

    if target.itemId then
        local name = C_Item.GetItemNameByID(target.itemId)
        if name then
            return name
        end
    end

    if target.id and L[target.id] then
        return L[target.id]
    end

    return L["item not loaded"] or "Item not loaded"
end

SC.pendingWaypoint = nil

function SC:SetPendingWaypoint(item)
    if not item or not item.guide or not item.guide.zone then return end
    self.pendingWaypoint = item
end

if not SC._waypointTicker then
    SC._waypointTicker = C_Timer.NewTicker(0.2, function()
        SC:ProcessPendingWaypoint()
    end)
end

function SC:ProcessPendingWaypoint()
    local t = self.pendingWaypoint
    if not t then return end

    local zone = t.guide and t.guide.zone
    if not zone or not zone.map or not zone.x or not zone.y then return end

    if TomTom then
        TomTom:AddWaypoint(zone.map, zone.x, zone.y, {
            title = self:GetTargetName(t),
            persistent = false,
        })
        self.pendingWaypoint = nil
        return
    end

    if not C_Map.CanSetUserWaypointOnMap(zone.map) then
        return
    end

    C_Map.ClearUserWaypoint()

    local point = UiMapPoint.CreateFromCoordinates(zone.map, zone.x, zone.y)
    C_Map.SetUserWaypoint(point)

    if C_SuperTrack then
        C_SuperTrack.SetSuperTrackedUserWaypoint(true)
    end

    self.pendingWaypoint = nil
end

SC._npcNameCache = SC._npcNameCache or {}
SC._mapNameCache = SC._mapNameCache or {}

local function GetNPCName(npc)
    local id, overrideName

    if type(npc) == "table" then
        id = tonumber(npc.id)
        overrideName = npc.name
    else
        id = tonumber(npc)
    end

    if overrideName and overrideName ~= "" then
        return overrideName
    end

    if not id then
        return "Unknown NPC"
    end

    if SC._npcNameCache[id] then
        return SC._npcNameCache[id]
    end

    local name

    if C_CreatureInfo and C_CreatureInfo.GetCreatureInfo then
        local info = C_CreatureInfo.GetCreatureInfo(id)
        name = info and info.name
    end

    if not name then
        local tt = _G.AhUI_NPCTooltipScan
        if not tt then
            tt = CreateFrame("GameTooltip", "AhUI_NPCTooltipScan", UIParent, "GameTooltipTemplate")
            tt:SetOwner(UIParent, "ANCHOR_NONE")
        end

        tt:ClearLines()
        tt:SetHyperlink(("unit:Creature-0-0-0-0-%d-0000000000"):format(id))
        local text = _G.AhUI_NPCTooltipScanTextLeft1
        text = text and text:GetText()
        if text and text ~= "" then
            name = text
        end
    end

    if not name then
        name = "NPC #" .. id
    end

    SC._npcNameCache[id] = name
    return name
end



local function GetMapName(mapID)
    if not mapID then return "Unknown zone" end
    if SC._mapNameCache[mapID] then
        return SC._mapNameCache[mapID]
    end

    local info = C_Map.GetMapInfo(mapID)
    local name = info and info.name or ("Map #" .. mapID)
    SC._mapNameCache[mapID] = name
    return name
end

function SC:GetGuideTooltip(target)
    if not target or not target.guide then return nil end
    local g = target.guide
    local lines = {}

    table.insert(lines, L["SKINNING_HOW_TO_GET"] or "How to obtain:")

    if g.lureItem then
        local itemName = C_Item.GetItemNameByID(g.lureItem) or (L["item not loaded"] or "Item not loaded")
        table.insert(lines, ("– %s: %s"):format(
            L["SKINNING_LURE"] or "Lure",
            itemName
        ))
    end

	if g.craftFrom then
		local items = {}

		local function addItem(id, count)
			local name = C_Item.GetItemNameByID(id)
				or (L["item not loaded"] or ("Item #" .. id))

			if count and count > 1 then
				table.insert(items, string.format("%dx %s", count, name))
			else
				table.insert(items, name)
			end
		end

		if type(g.craftFrom) == "table" then
			for _, entry in ipairs(g.craftFrom) do
				if type(entry) == "table" then
					addItem(entry.id, entry.count)
				else
					addItem(entry, nil)
				end
			end
		else
			addItem(g.craftFrom, nil)
		end

		table.insert(lines, ("– %s: %s"):format(
			L["SKINNING_CRAFT_FROM"] or "Crafted from",
			table.concat(items, ", ")
		))
	end

    if g.zone and g.zone.map then
        local zoneName = GetMapName(g.zone.map)
        if g.zone.x and g.zone.y then
            table.insert(lines, ("– %s: %s (%.1f, %.1f)"):format(
                L["SKINNING_LOCATION"] or "Location",
                zoneName,
                g.zone.x * 100,
                g.zone.y * 100
            ))
        else
            table.insert(lines, ("– %s: %s"):format(
                L["SKINNING_LOCATION"] or "Location",
                zoneName
            ))
        end
    end

    if g.npc and g.npc.id then
        local npcName = GetNPCName(g.npc)
        local npcLine = ("– %s: %s"):format(
            L["SKINNING_TARGET"] or "Target",
            npcName
        )

        if g.npc.minLevel then
            npcLine = npcLine .. (" (%d+ lvl need)"):format(g.npc.minLevel)
        end

        table.insert(lines, npcLine)
    end

    return table.concat(lines, "\n")
end

function SC:IsSkinningLearned()
    if not C_TradeSkillUI
       or not C_TradeSkillUI.GetProfessionInfoBySkillLineID
    then
        return false
    end

    for _, skillLineID in ipairs(self.SKINNING_SKILL_LINES) do
        local info = C_TradeSkillUI.GetProfessionInfoBySkillLineID(skillLineID)

        if info
           and info.skillLevel
           and info.skillLevel > 0
        then
            return true
        end
    end

    return false
end

function SC:HasSkinningProfession()
    if not GetProfessions or not GetProfessionInfo then
        return false
    end

    local prof1, prof2 = GetProfessions()
    if not prof1 and not prof2 then
        return false
    end

    for _, profIndex in ipairs({ prof1, prof2 }) do
        if profIndex then
            local _, _, _, _, _, _, skillLine = GetProfessionInfo(profIndex)
            if skillLine == self.ROOT_SKINNING_ID then
                return true
            end
        end
    end

    return false
end

function SC:IsAvailable()
    return self:HasSkinningProfession() or self:IsSkinningLearned()
end

function SC:IsTargetEnabled(target)
    local db = GetSkinningDisabledDB()
    return not db[target.id]
end

function SC:IsTargetCompleted(target)
    if not target or not target.questId then return false end
    return C_QuestLog.IsQuestFlaggedCompleted(target.questId)
end

function SC:HasMissingItems()
    if not self:IsAvailable() then return false end

	for _, target in ipairs(self.TARGETS) do
		if self:IsTargetAvailable(target)
		   and self:IsTargetEnabled(target)
		   and not self:IsTargetCompleted(target)
		then
			return true
		end
	end

    return false
end

function SC:GetMissingItems()
    local result = {}

    if not self:IsAvailable() then
        return result
    end

	for _, target in ipairs(self.TARGETS) do
		if self:IsTargetAvailable(target)
		   and self:IsTargetEnabled(target)
		   and not self:IsTargetCompleted(target)
		then
			table.insert(result, target)
		end
	end

    return result
end

function SC:GetIconTooltip()
    if not self:IsAvailable() then
        return L["SKINNING_NOT_LEARNED"]
    end

    local missing = self:GetMissingItems()
    if #missing == 0 then
        return L["SKINNING_ALL_DONE"]
    end

    local lines = { L["SKINNING_AVAILABLE"] }
    for _, t in ipairs(missing) do
        table.insert(lines, "• " .. self:GetTargetName(t))
    end

    return table.concat(lines, "\n")
end

function SC:GetProgress()
    if not self:IsAvailable() then
        return nil
    end

    local total, done = 0, 0

    for _, target in ipairs(self.TARGETS) do
        if self:IsTargetAvailable(target)
           and self:IsTargetEnabled(target)
        then
            total = total + 1
            if self:IsTargetCompleted(target) then
                done = done + 1
            end
        end
    end

    if total == 0 then
        return nil
    end

    return done, total
end