if SERVER then
    util.AddNetworkString("ixArsenalOpen")
    util.AddNetworkString("ixArsenalAction")
    util.AddNetworkString("ixWardrobeOpen")
    util.AddNetworkString("ixWardrobeApply")
end

local PLUGIN = PLUGIN
local config = PLUGIN.config



local function IsRecruit(ply)
    local char = ply:GetCharacter()
    if not char then return false end
    local spec = char.GetSpec and char:GetSpec() or 0
    return spec == 1
end

-- Helpers to store complex data as JSON strings because SetData/GetData may not accept tables
local function _loadJSONData(plugin, key)
    -- plugin:GetData() returns the whole plugin store (or default table). We keep subkeys inside that store.
    local store = plugin:GetData() or {}
    if type(store) ~= "table" then return {} end
    local raw = store[key]
    if raw == nil then return {} end
    if type(raw) == "table" then return raw end
    if type(raw) == "string" then
        local ok, tbl = pcall(util.JSONToTable, raw)
        if ok and istable(tbl) then return tbl end
    end
    return {}
end

local function _saveJSONData(plugin, key, tbl)
    if type(tbl) ~= "table" then tbl = {} end
    local store = plugin:GetData() or {}
    if type(store) ~= "table" then store = {} end
    -- store the table directly under the subkey; ix.data.Set will serialize the whole store
    store[key] = tbl
    plugin:SetData(store)
end

-- Faction supply storage helpers
function PLUGIN:GetFactionSupply(faction)
    local store = _loadJSONData(self, "factionSupply") or {}
    local key = tostring(faction)
    local val = store[faction]
    if val == nil then val = store[key] end
    if val == nil then
        -- fallback to configured startSupply or 0
        return config.startSupply[faction] or 0
    end
    local maxSupply = (self.config and self.config.maxSupply) or 20000
    return math.Clamp(tonumber(val) or 0, 0, maxSupply)
end

-- Returns remaining cooldown seconds for free weapons for a specific player (per-player persistent)
function PLUGIN:GetFreeWeaponCooldownForPlayer(client)
    if not IsValid(client) or not client:IsPlayer() then return 0 end
    local stamps = _loadJSONData(self, "freeWeaponTimestamps") or {}
    local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
    local last = tonumber(stamps[steam]) or 0
    local now = os.time()
    local cd = tonumber(config.freeWeaponCooldown) or 0
    if cd <= 0 then return 0 end
    local remain = cd - (now - last)
    if remain < 0 then remain = 0 end
    return math.floor(remain)
end

-- Returns remaining cooldown seconds for donate weapons (10 minutes = 600 seconds)
function PLUGIN:GetDonateWeaponCooldown(client, weaponClass)
    if not IsValid(client) or not client:IsPlayer() then return 0 end
    local stamps = _loadJSONData(self, "donateWeaponTimestamps") or {}
    local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
    if not stamps[steam] then return 0 end
    local last = tonumber(stamps[steam][weaponClass]) or 0
    local now = os.time()
    local cd = 600 -- 10 минут
    local remain = cd - (now - last)
    if remain < 0 then remain = 0 end
    return math.floor(remain)
end

function PLUGIN:SetDonateWeaponCooldown(client, weaponClass)
    if not IsValid(client) or not client:IsPlayer() then return end
    local stamps = _loadJSONData(self, "donateWeaponTimestamps") or {}
    local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
    if not stamps[steam] then stamps[steam] = {} end
    stamps[steam][weaponClass] = os.time()
    _saveJSONData(self, "donateWeaponTimestamps", stamps)
end

function PLUGIN:SetFactionSupply(faction, amount)
    local store = _loadJSONData(self, "factionSupply") or {}
    local key = tostring(faction)
    local value = math.max(tonumber(amount) or 0, 0)
    store[key] = value
    store[faction] = value
    _saveJSONData(self, "factionSupply", store)
end

-- Compatibility helper: add (or subtract) supply for a faction
function PLUGIN:AddFactionSupply(faction, delta)
    local amount = tonumber(delta) or 0
    local cur = tonumber(self:GetFactionSupply(faction)) or 0
    local maxSupply = (self.config and self.config.maxSupply) or 20000
    local new = math.Clamp(cur + amount, 0, maxSupply)
    
    if new == cur then return end -- Если ничего не изменилось (например, уперлись в лимит)

    self:SetFactionSupply(faction, new)
    
    -- Логирование изменения снабжения
    local serverlogsPlugin = ix.plugin.list["serverlogs"]
    if (serverlogsPlugin) then
        local factionName = ix.faction.Get(faction).name or tostring(faction)
        if amount > 0 then
            local message = string.format("Фракция '%s' получила +%d очков снабжения (итого: %d)", factionName, amount, new)
            serverlogsPlugin:AddLog("FACTION_SUPPLY_ADD", message, nil, {
                faction = faction,
                factionName = factionName,
                amount = amount,
                total = new
            })
        elseif amount < 0 then
            local message = string.format("Фракция '%s' потратила %d очков снабжения (итого: %d)", factionName, math.abs(amount), new)
            serverlogsPlugin:AddLog("FACTION_SUPPLY_USE", message, nil, {
                faction = faction,
                factionName = factionName,
                amount = math.abs(amount),
                total = new
            })
        end
    end
    
    return new
end

-- Получить список доступного оружия для персонажа (заглушка)
-- Рекомендуется реализовать: читать FACTION.Spec и FACTION.Podr из ix.faction.Get(faction)
function PLUGIN:GetAvailableWeapons(char)
    local weapons = {}
    local faction = char:GetFaction()
    local factionTable = ix.faction.Get(faction)
    if not factionTable then 
        return weapons 
    end

    local allowed = {}
    local specIndex = tonumber(char:GetSpec()) or 1
    if factionTable.Spec and factionTable.Spec[specIndex] and istable(factionTable.Spec[specIndex].weapons) then
        for _, c in ipairs(factionTable.Spec[specIndex].weapons) do
            allowed[c] = true
        end
    end

    local podrIndex = tonumber(char:GetPodr()) or 1
    if factionTable.Podr and factionTable.Podr[podrIndex] and istable(factionTable.Podr[podrIndex].preset) then
        for _, c in ipairs(factionTable.Podr[podrIndex].preset) do
            allowed[c] = true
        end
    end

    -- donate weapons from character data (with expiration check)
    local donateWeaponsTimed = char:GetData("donate_weapons_timed", {})
    local donateTable = {}
    if donateWeaponsTimed and istable(donateWeaponsTimed) then
        local now = os.time()
        for wepClass, wepData in pairs(donateWeaponsTimed) do
            if istable(wepData) and wepData.expires and tonumber(wepData.expires) > now then
                donateTable[wepClass] = true
            end
        end
    end
    
    -- Поддержка старой системы без срока (если есть)
    local donateList = char:GetData("donate_weapons", false)
    if donateList and istable(donateList) then
        for _, c in ipairs(donateList) do donateTable[c] = true end
    end

    -- IGS integration: check if player has any weapons bought via IGS
    local client = char:GetPlayer()
    if IsValid(client) then
        if IGS then
            if isfunction(IGS.GetItems) then
                local items = IGS.GetItems()
                for _, ITEM in pairs(items) do
                    local uid = (isfunction(ITEM.GetUID) and ITEM:GetUID()) or ITEM.uid
                    if not uid then continue end

                    local has = false
                    if isfunction(client.HasPurchase) then
                        has = client:HasPurchase(uid)
                    elseif isfunction(IGS.PlayerHasItem) then
                        has = IGS.PlayerHasItem(client, uid)
                    end

                    if has then
                        -- Try all possible ways IGS stores the weapon class
                        local weaponClass = nil
                        local weaponCandidates = {
                            (isfunction(ITEM.GetWeapon) and ITEM:GetWeapon()),
                            (isfunction(ITEM.GetMeta) and ITEM:GetMeta("weapon")),
                            ITEM.weapon,
                            ITEM.weapon_class,
                            ITEM.class,
                            ITEM.uniqueID,
                            ITEM.val,
                            uid
                        }
                        for _, candidate in ipairs(weaponCandidates) do
                            if candidate and candidate ~= "" then
                                weaponClass = candidate
                                break
                            end
                        end

                        if weaponClass and type(weaponClass) ~= "string" then
                            weaponClass = tostring(weaponClass)
                        end

                        if not weaponClass then
                            weaponClass = uid
                        end

                        if weaponClass then
                            -- Check if this class or a similar one exists in config
                            if config.weapons[weaponClass] then
                                donateTable[weaponClass] = true
                            else
                                for configClass, _ in pairs(config.weapons) do
                                    if configClass:find(weaponClass, 1, true) then
                                        donateTable[configClass] = true
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end

    -- Build result from config only if class is allowed and exists in config
    local supply = tonumber(self:GetFactionSupply(faction)) or 0
    for class, _ in pairs(allowed) do
        local data = config.weapons[class]
        if not data then continue end -- skip if not configured

        -- Проверяем есть ли оружие в донате у игрока
        local hasDonate = donateTable[class]
        
        if hasDonate then
            -- Если куплено в донате - показываем как донатное (бесплатно, с кулдауном)
            local donateData = table.Copy(data)
            donateData.isDonateVersion = true -- флаг что это донатная версия
            donateData.supplyPrice = 0
            donateData.moneyPrice = 0
            weapons[class] = donateData
        elseif data.donate_only then
            -- Оружие только для доната, но не куплено - не показываем
            continue
        else
            -- Обычное оружие из spec/podr - показываем с ценой из конфига
            if supply <= 0 then
                if (data.supplyPrice or 0) == 0 then weapons[class] = data end
            else
                weapons[class] = data
            end
        end
    end
    
    -- Добавляем оружие которое есть ТОЛЬКО в донате (не в spec/podr)
    for wepClass, _ in pairs(donateTable) do
        if not allowed[wepClass] then
            local data = config.weapons[wepClass]
            if data then
                local donateData = table.Copy(data)
                donateData.isDonateVersion = true
                donateData.supplyPrice = 0
                donateData.moneyPrice = 0
                weapons[wepClass] = donateData
            end
        end
    end

    return weapons
end

-- Заглушки для действий (реализуйте логику по необходимости)
function PLUGIN:BuyWeapon(client, weaponClass, payMethod)
    local char = client:GetCharacter()
    if not char then return false, "Нет персонажа" end
    local available = self:GetAvailableWeapons(char)
    local data = available[weaponClass]
    if not data then return false, "Оружие недоступно для покупки" end
    payMethod = payMethod or "supply"
    local faction = char:GetFaction()

    -- Option A: pay by money (Helix)
    if payMethod == "money" then
        local price = data.moneyPrice or 0
        if price == 0 then return false, "Это оружие нельзя купить за деньги" end
            if not char.HasMoney or not char:HasMoney(price) then return false, "Недостаточно денег" end
        char:TakeMoney(price)
        client:Give(weaponClass)
        return true
    end

    -- Check if this is a donate weapon version
    local isDonateWeapon = (data.isDonateVersion == true)
    
    if isDonateWeapon then
        -- Проверяем что оружие уже есть у игрока
        if client:HasWeapon(weaponClass) then
            return false, "У вас уже есть это оружие"
        end
        
        -- Проверяем кулдаун для донат-оружия (10 минут)
        local cooldown = self:GetDonateWeaponCooldown(client, weaponClass)
        if cooldown > 0 then
            local minutes = math.floor(cooldown / 60)
            local seconds = cooldown % 60
            return false, string.format("Вы недавно брали это оружие. Подождите %02d:%02d", minutes, seconds)
        end
        
        -- Проверяем категорию (донат оружие тоже может иметь категорию)
        local newCat = data.category or ""
        if newCat ~= "" and not newCat:find("^tool") then
            for _, wep in ipairs(client:GetWeapons()) do
                if not IsValid(wep) then continue end
                local wclass = wep:GetClass()
                local wdata = config.weapons[wclass]
                if wdata and wdata.category == newCat then
                    return false, "Вы уже имеете оружие этой категории: " .. newCat
                end
            end
        end

        -- Check max ammo limit for launchers
        if data.maxAmmo then
            local totalAmmo = 0
            if data.ammoType == "PanzerFaust3 Rocket" or data.ammoType == "rpg_round" then
                totalAmmo = client:GetAmmoCount("rpg_round") + client:GetAmmoCount("PanzerFaust3 Rocket")
            else
                totalAmmo = client:GetAmmoCount(data.ammoType or "rpg_round")
            end
            if totalAmmo >= data.maxAmmo then
                return false, "Вы достигли максимального количества снарядов для этого типа оружия (" .. tostring(data.maxAmmo) .. ")"
            end
        end
        
        -- Выдаем оружие и ставим кулдаун
        client:Give(weaponClass)
        
        -- Reset ammo for launchers to prevent extra ammo
        if data.ammoType then
            client:SetAmmo(0, data.ammoType)
        end
        
        self:SetDonateWeaponCooldown(client, weaponClass)
        
        -- Логирование выдачи донат-оружия
    end
    
    -- Default: pay by supply
    local supplyCost = data.supplyPrice or 0
    local factionSupply = self:GetFactionSupply(faction)

    -- If weapon is free (supplyCost == 0), enforce per-player persistent cooldown
    if supplyCost == 0 then
        local stamps = _loadJSONData(self, "freeWeaponTimestamps") or {}
        local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
        local last = tonumber(stamps[steam]) or 0
        local now = os.time()
        local cd = tonumber(config.freeWeaponCooldown) or 0
        if cd > 0 and (now - last) < cd then
            local remain = cd - (now - last)
            return false, "Вы уже брали бесплатное оружие недавно. Подождите " .. tostring(remain) .. " сек."
        end
        -- don't write timestamp yet: write after successful give
    else
        if supplyCost > 0 then
            if factionSupply < supplyCost then return false, "Недостаточно очков снабжения у фракции" end
            self:AddFactionSupply(faction, -supplyCost)
        end
    end
    -- Check category conflict: prevent two weapons from same category
    local newCat = data.category or ""
    if newCat ~= "" and not newCat:find("^tool") then
        for _, wep in ipairs(client:GetWeapons()) do
            if not IsValid(wep) then continue end
            local wclass = wep:GetClass()
            local wdata = config.weapons[wclass]
            if wdata and wdata.category == newCat then
                return false, "Вы уже имеете оружие этой категории: " .. newCat
            end
        end
    end

    -- Check max ammo limit for launchers
    if data.maxAmmo then
        local totalAmmo = client:GetAmmoCount(data.ammoType or "rpg_round")
        if totalAmmo >= data.maxAmmo then
            return false, "Вы достигли максимального количества снарядов для этого типа оружия (" .. tostring(data.maxAmmo) .. ")"
        end
    end
    -- Check max count limit for weapons
    if data.maxCount and client:HasWeapon(weaponClass) then
        return false, "У вас уже есть это оружие"
    end

    client:Give(weaponClass)
    
    -- Reset ammo for launchers to prevent extra ammo
    if data.ammoType then
        client:SetAmmo(0, data.ammoType)
    end
    -- If free weapon granted, save timestamp per-player
    if supplyCost == 0 then
        local stamps = _loadJSONData(self, "freeWeaponTimestamps") or {}
        local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
        stamps[steam] = os.time()
        _saveJSONData(self, "freeWeaponTimestamps", stamps)
    end
    
    -- Логирование выдачи оружия из арсенала
    local serverlogsPlugin = ix.plugin.list["serverlogs"]
    if (serverlogsPlugin) then
        local weaponName = data.name or weaponClass
        local factionName = ix.faction.Get(faction).name or tostring(faction)
        local message = string.format("%s получил оружие '%s' из арсенала (стоимость: %d снабжения)", client:Nick(), weaponName, supplyCost)
        serverlogsPlugin:AddLog("WEAPON_SPAWN", message, client, {
            weaponClass = weaponClass,
            weaponName = weaponName,
            supplyCost = supplyCost,
            faction = faction,
            factionName = factionName
        })
    end
    
    return true
end

function PLUGIN:BuyAmmo(client, ammoType)
    local char = client:GetCharacter()
    if not char then return false, "Нет персонажа" end

    -- Запрет на покупку патронов для ракетниц
    if ammoType == "rpg_round" or ammoType == "PanzerFaust3 Rocket" then
        return false, "Патроны для этого типа оружия недоступны для покупки"
    end

    local ammoData = config.ammo[ammoType]
    if not ammoData then return false, "Тип патронов не найден" end

    local faction = char:GetFaction()
    local supply = self:GetFactionSupply(faction)

    local price = ammoData.price or 0
    if price > 0 then
        if supply < price then return false, "Недостаточно очков снабжения у фракции" end
        self:AddFactionSupply(faction, -price)
    end

    client:GiveAmmo(ammoData.amount or 30, ammoType, true)
    return true
end

function PLUGIN:ReturnWeapon(client, weaponClass)
    local char = client:GetCharacter()
    if not char then return false, "Нет персонажа" end
    local data = config.weapons[weaponClass]
    if not data then return false, "Оружие не найдено" end

    local faction = char:GetFaction()
    -- Remove weapon
    client:StripWeapon(weaponClass)

    -- Reset ammo for launchers to prevent extra ammo
    if data.ammoType then
        client:SetAmmo(0, data.ammoType)
    end

    -- Если это донат-оружие, сбрасываем кулдаун
    if data.donate == true then
        local stamps = _loadJSONData(self, "donateWeaponTimestamps") or {}
        local steam = client:SteamID() or tostring(client:SteamID64() or "unknown")
        if stamps[steam] and stamps[steam][weaponClass] then
            stamps[steam][weaponClass] = nil
            _saveJSONData(self, "donateWeaponTimestamps", stamps)
        end
        return true
    end

    local refund = math.floor((data.supplyPrice or 0) * 0.8)
    if refund > 0 then self:AddFactionSupply(faction, refund) end
    return true
end

function PLUGIN:SaveData()
    local data = self:GetData() or {}
    data.entities = {}

    for _, entity in ipairs(ents.FindByClass("ix_arsenal")) do
        data.entities[#data.entities + 1] = {
            class = "ix_arsenal",
            pos = entity:GetPos(),
            angles = entity:GetAngles()
        }
    end

    for _, entity in ipairs(ents.FindByClass("ix_ammobox")) do
        data.entities[#data.entities + 1] = {
            class = "ix_ammobox",
            pos = entity:GetPos(),
            angles = entity:GetAngles()
        }
    end

    for _, entity in ipairs(ents.FindByClass("ix_wardrobe")) do
        data.entities[#data.entities + 1] = {
            class = "ix_wardrobe",
            pos = entity:GetPos(),
            angles = entity:GetAngles()
        }
    end

    self:SetData(data)
end

function PLUGIN:LoadData()
    local data = self:GetData() or {}
    local entities = data.entities or data -- fallback to compatibility if no 'entities' key

    for _, v in ipairs(entities) do
        if not v.class then continue end
        local entity = ents.Create(v.class or "ix_arsenal")
        entity:SetPos(v.pos)
        entity:SetAngles(v.angles)
        entity:Spawn()
        
        local phys = entity:GetPhysicsObject()
        if IsValid(phys) then
            phys:EnableMotion(false)
        end
    end
end

-- Обработчик сетевых действий от клиента
if SERVER then
    net.Receive("ixArsenalAction", function(len, ply)
        local action = net.ReadString()
        local id = net.ReadString()
        local plugin = ix.plugin.list["arsenal"]
        if not plugin then return end

        if IsRecruit(ply) then
            ply:Notify("Новоприбывший не может пользоваться арсеналом.")
            return
        end

        if action == "buy_weapon" then
            local method = net.ReadString()
            local ok, msg = plugin:BuyWeapon(ply, id, method)
            if not ok then
                ply:Notify(msg or "Ошибка покупки оружия")
            end
        elseif action == "buy_ammo" then
            local ok, msg = plugin:BuyAmmo(ply, id)
            if not ok then
                ply:Notify(msg or "Ошибка покупки патронов")
            end
        elseif action == "return_weapon" then
            local ok, msg = plugin:ReturnWeapon(ply, id)
            if not ok then
                ply:Notify(msg or "Ошибка возврата оружия")
            end
        elseif action == "buy_armor" then
            local method = net.ReadString()
            local ok, msg = plugin:BuyArmor(ply, id, method)
            if not ok then
                ply:Notify(msg or "Ошибка покупки брони")
            end
        end
    end)
end

-- Buy armor implementation
function PLUGIN:BuyArmor(client, armorClass, payMethod)
    local char = client:GetCharacter()
    if not char then return false, "Нет персонажа" end
    local aData = config.armor[armorClass]
    if not aData then return false, "Броня не найдена" end
    payMethod = payMethod or "supply"

    -- Check current armor: Armor() is the player's current armor value
    local curArmor = tonumber(client:Armor()) or 0
    local giveAmount = tonumber(aData.amount) or 0
    if curArmor >= giveAmount then
        return false, "Вы не можете купить броню — у вас уже есть броня этого уровня или выше"
    end

    local faction = char:GetFaction()

    -- money path
    if payMethod == "money" then
        local price = aData.moneyPrice or 0
        if price <= 0 then return false, "Эту броню нельзя купить за деньги" end
        if not char.HasMoney or not char:HasMoney(price) then return false, "Недостаточно денег" end
        char:TakeMoney(price)
        client:SetArmor(giveAmount)
        return true
    end

    -- supply path
    local supplyCost = aData.supplyPrice or 0
    local factionSupply = self:GetFactionSupply(faction)
    if supplyCost > 0 then
        if factionSupply < supplyCost then return false, "Недостаточно очков снабжения у фракции" end
        self:AddFactionSupply(faction, -supplyCost)
    end

    client:SetArmor(giveAmount)
    return true
end

function PLUGIN:PlayerLoadedCharacter(client, character, currentChar)
    if not IsValid(client) then return end
    timer.Simple(0.5, function()
        if not IsValid(client) or not client:GetCharacter() then return end
        local char = client:GetCharacter()
        local bodygroups = char:GetData("bodygroups", {})
        local skin = char:GetData("skin", 0)
        local patch = char:GetData("patchIndex", 1)
        for idx, value in pairs(bodygroups) do
            client:SetBodygroup(idx, value)
        end
        client:SetSkin(skin)
        if self.config.patchIndex and self.config.patchMaterials then
            local pMat = self.config.patchMaterials[patch]
            if pMat then
                client:SetSubMaterial(self.config.patchIndex, pMat)
            else
                client:SetSubMaterial(self.config.patchIndex, "")
            end
        end
        hook.Run("PostPlayerLoadout", client)
    end)
end

function PLUGIN:PostPlayerLoadout(client)
    local char = client:GetCharacter()
    if not char then return end
    local model = client:GetModel()
    local bgs = char:GetData("bodygroups", {})
    local speedMod = 1
    local maxArmor = 100
    local ammoMod = 1
    local stats = self.config.wardrobeStats and self.config.wardrobeStats[model]
    if stats then
        for idx, val in pairs(bgs) do
            if stats[idx] and stats[idx][val] then
                local st = stats[idx][val]
                if st.speed then speedMod = speedMod * st.speed end
                if st.armor then maxArmor = maxArmor + st.armor end
                if st.ammo then ammoMod = ammoMod * st.ammo end
            end
        end
    end
    client:SetWalkSpeed(ix.config.Get("walkSpeed") * speedMod)
    client:SetRunSpeed(ix.config.Get("runSpeed") * speedMod)
    client:SetMaxArmor(maxArmor)
    char:SetData("ammoMod", ammoMod)
end

function PLUGIN:EntityTakeDamage(target, dmginfo)
    if not target:IsPlayer() then return end
    local char = target:GetCharacter()
    if not char then return end
    local model = target:GetModel()
    local bgs = char:GetData("bodygroups", {})
    local resist = 1
    local stats = self.config.wardrobeStats and self.config.wardrobeStats[model]
    if stats then
        for idx, val in pairs(bgs) do
            if stats[idx] and stats[idx][val] then
                local st = stats[idx][val]
                if st.dmgResist then
                    resist = resist * st.dmgResist
                end
            end
        end
    end
    if resist ~= 1 then
        dmginfo:ScaleDamage(resist)
    end
end

function PLUGIN:InitPostEntity()
    -- Уменьшаем задержку до 2 секунд для более быстрой очистки при старте
    timer.Simple(2, function()
        -- Загружаем сырые данные из стора напрямую
        local currentData = _loadJSONData(self, "factionSupply") or {}
        
        -- Перебираем все записи в сторе. Это надежнее, чем идти по индексам фракций,
        -- так как это затронет любые старые или "кривые" ключи в базе.
        local changed = false
        for key, value in pairs(currentData) do
            local factionID = tonumber(key)
            local rawVal = tonumber(value) or 0
            
            if factionID and rawVal > 5000 then
                local startVal = (self.config.startSupply and self.config.startSupply[factionID]) or 2000
                
                -- Устанавливаем новое значение
                currentData[key] = startVal
                currentData[factionID] = startVal
                changed = true
                
                print(string.format("[Arsenal] Автосброс при старте: фракция %s, было %d, стало %d", key, rawVal, startVal))
            end
        end
        
        if changed then
            _saveJSONData(self, "factionSupply", currentData)
        end
    end)
end

function PLUGIN:PlayerSetHandsModel(client, ent)
    local char = client:GetCharacter()
    if not char then return end
    local model = client:GetModel()
    local bgs = char:GetData("bodygroups", {})
    local chands = self.config.wardrobeCHands and self.config.wardrobeCHands[model]
    if chands then
        for idx, val in pairs(bgs) do
            if chands[idx] and chands[idx][val] then
                local hData = chands[idx][val]
                ent:SetModel(hData.model or "models/weapons/c_arms_cstrike.mdl")
                ent:SetSkin(hData.skin or 0)
                ent:SetBodyGroups(hData.bodygroups or "0000000")
                return true
            end
        end
    end
end
