----------------------------------------------------------
-- Category_Materials.lua
-- Token-based rules (v3.8)
----------------------------------------------------------

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

-- token tables
local TOKENS = {
    CraftingMaterial = { "nail", "screw", "bolt", "adhesive", "glue", "epoxy", "duct", "tape", "rope", "twine", "thread", "wire", "hinge", "fastener", "spring", "clip" },
    WoodMaterial     = { "wood", "wooden", "plank", "tree", "twig", "twigs", "sapling", "handle", "stick", "stack", "log", "branch", "firewood" },
    MetalMaterial    = { "metal", "scrap", "sheet" },
    FabricMaterial   = { "rag", "sheet", "denim", "leather", "cotton", "fabric" },
    Chemical         = { "bleach", "acid", "fertilizer", "chemical", "solution", "cleaner" },
    Fuel             = { "gas", "fuel", "propane", "kerosene" },
    BookItem         = { "book", "magazine" },
    WorldItem        = { "stone", "rock", "brick", "gravel" },
    Repair           = { "tape", "glue", "epoxy" },
    Stone            = { "stone", "nodule", "limestone", "quicklime", "flink" },
    Aluminium        = { "aluminium", "aluminum" },
    Bone             = { "bone" },
    Brass            = { "brass" },
    Charcoal         = { "charcoal", "coke" },
    Clay             = { "clay", "ceramic", "crucible", "jar", "unfired" },
    Copper           = { "copper", "cooper" },
    Cotton           = { "cotton", "rag", "sheet", "bundle" },
    Fibre            = { "fiber", "fibre", "burlap", "flax", "rope", "thread", "yarn", "twine", "hemp", "string", "raw" },
    Glass            = { "glass" },
    Gold             = { "gold" },
    Iron             = { "iron", "plate", "latch", "spike", "link" },
    Leather          = { "leather", "hide", "strips" },
    Silver           = { "silver" },
    Steel            = { "steel", "sword", "blade" },
    ToolHead         = { "head" },
    Wallpaper        = { "wallpaper" },
}

-- Universal token matcher for all categories
local function matchTokens(text, tokens)
    for _, token in ipairs(tokens) do
        if text:find(token, 1, true) then
            return true
        end
    end
    return false
end

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

local function getDisplayCategory(item)
    return lower(item.getDisplayCategory and item:getDisplayCategory())
end

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

local function isMaterial(item, statMap)
    local dc = getDisplayCategory(item)
    local cat = item.getCategory and lower(item:getCategory()) or ""

    -- Excluir armas (evita que "bone"/"steel" en nombres crafted armes caigan aquí)
    if (instanceof and instanceof(item, "HandWeapon")) or dc:find("weapon", 1, true) or cat:find("weapon", 1, true) then
        return false
    end

    -- Excluir comida (evita que peces "flathead" se clasifiquen como ToolHead)
    if (instanceof and instanceof(item, "Food")) or dc:find("food", 1, true) or cat:find("food", 1, true) then
        return false
    end

    if dc:find("medical") or dc:find("first") then
        return false
    end

    local isFluid = (statMap and statMap["fluidCapacity"] ~= nil)
        or (InspectUI_isFluidContainer and InspectUI_isFluidContainer(item))
        or dc:find("water", 1, true) ~= nil
        or dc:find("watercontainer", 1, true) ~= nil
        or dc:find("fuel", 1, true) ~= nil
    if isFluid then
        return false
    end

    return true
end

C.rules = {
    -- Base
    {
        id = "Materials.BaseCheck",
        priority = 50,
        match = function(item, statMap)
            return isMaterial(item, statMap)
        end,
        category = "MaterialsAndMisc",
    },

    -- Subcategories (normalized priorities 90–120)
    {
        id = "Materials.CraftingMaterial",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            local text = getText(item)
            return matchTokens(text, TOKENS.CraftingMaterial) or getDisplayCategory(item):find("craft")
        end,
        category = "MaterialsAndMisc/CraftingMaterial",
    },
    {
        id = "Materials.WoodMaterial",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.WoodMaterial)
        end,
        category = "MaterialsAndMisc/WoodMaterial",
    },
    {
        id = "Materials.MetalMaterial",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.MetalMaterial)
        end,
        category = "MaterialsAndMisc/MetalMaterial",
    },
    {
        id = "Materials.FabricMaterial",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.FabricMaterial)
        end,
        category = "MaterialsAndMisc/FabricMaterial",
    },
    {
        id = "Materials.Chemical",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            local text = getText(item)
            return matchTokens(text, TOKENS.Chemical) or getDisplayCategory(item):find("chem")
        end,
        category = "MaterialsAndMisc/Chemical",
    },
    {
        id = "Materials.Fuel",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Fuel)
        end,
        category = "MaterialsAndMisc/Fuel",
    },
    {
        id = "Materials.BookItem",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            if not matchTokens(getText(item), TOKENS.BookItem) then return false end
            if item.getSkillTrained and item:getSkillTrained() then return false end
            return true
        end,
        category = "MaterialsAndMisc/BookItem",
    },
    {
        id = "Materials.WorldItem",
        priority = 95,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.WorldItem)
        end,
        category = "MaterialsAndMisc/WorldItem",
    },
    {
        id = "Materials.Repair",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Repair)
        end,
        category = "MaterialsAndMisc/Repair",
    },
    {
        id = "Materials.Aluminium",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Aluminium)
        end,
        category = "MaterialsAndMisc/Aluminium",
    },
    {
        id = "Materials.Bone",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Bone)
        end,
        category = "MaterialsAndMisc/Bone",
    },
    {
        id = "Materials.Brass",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Brass)
        end,
        category = "MaterialsAndMisc/Brass",
    },
    {
        id = "Materials.Charcoal",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Charcoal)
        end,
        category = "MaterialsAndMisc/Charcoal",
    },
    {
        id = "Materials.Clay",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Clay)
        end,
        category = "MaterialsAndMisc/Clay",
    },
    {
        id = "Materials.Copper",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Copper)
        end,
        category = "MaterialsAndMisc/Copper",
    },
    {
        id = "Materials.Cotton",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Cotton)
        end,
        category = "MaterialsAndMisc/Cotton",
    },
    {
        id = "Materials.Fibre",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Fibre)
        end,
        category = "MaterialsAndMisc/Fibre",
    },
    {
        id = "Materials.Glass",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Glass)
        end,
        category = "MaterialsAndMisc/Glass",
    },
    {
        id = "Materials.Gold",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Gold)
        end,
        category = "MaterialsAndMisc/Gold",
    },
    {
        id = "Materials.Iron",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Iron)
        end,
        category = "MaterialsAndMisc/Iron",
    },
    {
        id = "Materials.Leather",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Leather)
        end,
        category = "MaterialsAndMisc/Leather",
    },
    {
        id = "Materials.Silver",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Silver)
        end,
        category = "MaterialsAndMisc/Silver",
    },
    {
        id = "Materials.Steel",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Steel)
        end,
        category = "MaterialsAndMisc/Steel",
    },
    {
        id = "Materials.ToolHead",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.ToolHead)
        end,
        category = "MaterialsAndMisc/ToolHead",
    },
    {
        id = "Materials.Wallpaper",
        priority = 110,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Wallpaper)
        end,
        category = "MaterialsAndMisc/Wallpaper",
    },
    {
        id = "Materials.Repair",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Repair)
        end,
        category = "MaterialsAndMisc/Repair",
    },
    {
        id = "Materials.Stone",
        priority = 100,
        match = function(item, statMap)
            if not isMaterial(item, statMap) then return false end
            return matchTokens(getText(item), TOKENS.Stone)
        end,
        category = "MaterialsAndMisc/Stone",
    },
    {
        id = "Materials.MiscUtility",
        priority = 90,
        match = function(item, statMap)
            return isMaterial(item, statMap)
        end,
        category = "MaterialsAndMisc/MiscUtility",
    },

    {
        id = "Materials.Base",
        priority = 40,
        match = function(item, statMap)
            local name = item.getDisplayName and item:getDisplayName() or ""
            name = string.lower(name)
            return name:find("material", 1, true) ~= nil
        end,
        category = "Materials",
    },
}

return C
