----------------------------------------------------------
-- Category_Weapons.lua
-- Dispatcher + universal weapon rules (v3.9 modular)
----------------------------------------------------------

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

-- token tables
local TOKENS = {
    WeaponPart = { "weaponpart" },
    Cooking    = { "cook", "pan", "skillet", "spatula", "ladle", "spoon", "rolling pin", "rollingpin", "cooking", "kitchen" },
    Household  = { "house", "household", "broom", "mop", "plunger", "brush", "rod", "handle" },
    Writing    = { "pen", "marker", "pencil", "eraser", "crayons" },
    Instrument = { "instrument", "guitar", "banjo", "violin", "bass", "drum", "harmonica", "sax", "saxophone" },
    Gardening  = { "garden", "gardening", "shovel", "hoe", "fork", "trowel" },
    Explosive  = { "bomb", "explosive", "grenade", "dynamite", "c4" },
}

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

-- 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 getDisplayCategory(item)
    return lower(item.getDisplayCategory and item:getDisplayCategory())
end

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

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

local function isWeapon(item)
    if not item then return false end
    local dc = getDisplayCategory(item)
    local cat = getCategory(item)

    -- Evitar clasificar explosivos como armas melee/weapon
    if dc:find("explosive", 1, true) or cat:find("explosive", 1, true) then
        return false
    end

    if instanceof and instanceof(item, "HandWeapon") then return true end

    return dc:find("weapon", 1, true) ~= nil or cat:find("weapon", 1, true) ~= nil
end

C.rules = {
    -- Weapon part detection
    {
        id = "Weapons.Dispatch.WeaponPart",
        priority = 110,
        match = function(item, statMap)
            if not isWeapon(item) then return false end
            return matchTokens(getText(item), TOKENS.WeaponPart)
        end,
        category = "Weapons/WeaponPart",
    },

    -- Universal weapon tokens
    {
        id = "Weapons.ToolWeapon",
        priority = 103,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            local dc = getDisplayCategory(item)
            return dc:find("toolweapon", 1, true) ~= nil
        end,
        category = "Weapons/Household",
    },

    {
        id = "Weapons.Cooking",
        priority = 101,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            return matchTokens(getText(item), TOKENS.Cooking)
        end,
        category = "Weapons/Cooking",
    },

    {
        id = "Weapons.Household",
        priority = 101,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            return matchTokens(getText(item), TOKENS.Household)
        end,
        category = "Weapons/Household",
    },

    {
        id = "Weapons.HouseholdWriting",
        priority = 101,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            local dc = getDisplayCategory(item)
            if dc:find("memento", 1, true) then return true end
            return matchTokens(getText(item), TOKENS.Writing)
        end,
        category = "Weapons/Household/Writing",
    },

    {
        id = "Weapons.InstrumentWeapon",
        priority = 102,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            local dc = getDisplayCategory(item)
            if dc:find("instrument", 1, true) then return true end
            return matchTokens(getText(item), TOKENS.Instrument)
        end,
        category = "Weapons/InstrumentWeapon",
    },

    {
        id = "Weapons.GardeningWeapon",
        priority = 102,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            local dc = getDisplayCategory(item)
            if dc:find("garden", 1, true) then return true end
            return matchTokens(getText(item), TOKENS.Gardening)
        end,
        category = "Weapons/GardeningWeapon",
    },

    -- Dispatcher: firearm vs melee
    {
        id = "Weapons.Dispatch.Firearm",
        priority = 100,
        match = function(item, statMap)
            if not (isWeapon(item) and item.getAmmoType) then return false end
            local ammo = item:getAmmoType()
            return ammo ~= nil and ammo ~= ""
        end,
        category = "Weapons/Firearm",
    },

    {
        id = "Weapons.Dispatch.Melee",
        priority = 95,
        match = function(item, statMap)
            if not (isWeapon(item) and instanceof and instanceof(item, "HandWeapon")) then
                return false
            end
            if item.getAmmoType then
                local ammoType = item:getAmmoType()
                if ammoType and ammoType ~= "" then
                    return false
                end
            end
            return true
        end,
        category = "Weapons/Melee",
    },

    -- Universal explosives
    {
        id = "Weapons.Explosive",
        priority = 90,
        match = function(item, statMap)
            if not isWeapon(item) then return false end
            return matchTokens(getText(item), TOKENS.Explosive)
        end,
        category = "Weapons/Explosive",
    },

    -- Weapons base fallback
    {
        id = "Weapons.Base",
        priority = 50,
        match = function(item, statMap)
            return isWeapon(item)
        end,
        category = "Weapons",
    },
}

return C
