----------------------------------------------------------
-- Category_Corpse.lua
-- Dead animal carcasses
----------------------------------------------------------

local C = {}
	C.parent = "Corpse"

local TOKENS = {
    DeadAnimal = {
        "corpse", "carcass",
        "boar", "piglet",
        "bull", "cow", "calf",
        "rabbit", "bunny",
        "mouse", "rat",
        "chick", "cockerel", "hen",
        "ewe", "lamb", "ram",
        "raccoon",
        "buck", "doe", "fawn",
    },
    AnimalPart = {
        "animalpart", "animal part",
        "feather", "antler", "horn", "pelt", "hide", "skin",
        "hoof", "claw", "paw", "tail", "wing",
    },
}

local function isWordChar(ch)
    return ch and ch:match("[%w_]") ~= nil
end

local function matchTokens(text, tokens)
    for _, token in ipairs(tokens) do
        local from = 1
        while true do
            local startPos, endPos = text:find(token, from, true)
            if not startPos then break end
            local before = startPos > 1 and text:sub(startPos - 1, startPos - 1) or nil
            local after = endPos < #text and text:sub(endPos + 1, endPos + 1) or nil
            if not isWordChar(before) and not isWordChar(after) then
                return true
            end
            from = endPos + 1
        end
    end
    return false
end

local function lower(val)
    if not val then return "" end
    return string.lower(tostring(val))
end

local function getText(item)
    local name = lower(item.getDisplayName and item:getDisplayName())
    local dc   = lower(item.getDisplayCategory and item:getDisplayCategory())
    local cat  = lower(item.getCategory and item:getCategory())
    return (name or "") .. " " .. (dc or "") .. " " .. (cat or "")
end

local function isCorpse(item)
    -- Solo tratar como cadáver si es perecedero (food/carcass), evitando peluches tipo Spiffo
    local isPerishable = false
    if item then
        if instanceof and instanceof(item, "Food") then
            isPerishable = true
        elseif item.getOffAge and (item:getOffAge() or 0) > 0 then
            isPerishable = true
        elseif item.getAge and (item:getAge() or 0) > 0 then
            isPerishable = true
        end
    end
    if not isPerishable then return false end

    local text = getText(item)
    return matchTokens(text, TOKENS.DeadAnimal)
end

local function isAnimalPart(item)
    return matchTokens(getText(item), TOKENS.AnimalPart)
end

C.rules = {
    {
        id = "Corpse.AnimalPart",
        priority = 95,
        match = function(item, statMap)
            return isAnimalPart(item)
        end,
        category = "Corpse/AnimalPart",
    },

    {
        id = "Corpse.BaseCheck",
        priority = 50,
        match = function(item, statMap)
            return isCorpse(item)
        end,
        category = "Corpse",
    },

    {
        id = "Corpse.DeadAnimal",
        priority = 90,
        match = function(item, statMap)
            if not isCorpse(item) then return false end
            return matchTokens(getText(item), TOKENS.DeadAnimal)
        end,
        category = "Corpse/DeadAnimal",
    },
}

return C
