-- Server-side command handlers for W900 Semi-Truck
-- Receives client commands and updates vehicle parts

if not isServer() then return end

require "Vehicles/W900_Freezer"
require "rSemiTruck/ArmorSync"

local W900Commands = {}
local ArmorSync = rSemiTruck.ArmorSync

local function isPlayerNearVehicle(player, vehicle, maxDistance)
    if not player or not vehicle then
        return false
    end

    maxDistance = maxDistance or 5
    local dx = player:getX() - vehicle:getX()
    local dy = player:getY() - vehicle:getY()
    return (dx * dx + dy * dy) <= (maxDistance * maxDistance)
end

local function isMoveUpAdminOnly()
    return SandboxVars
        and SandboxVars.rSemiTruck
        and SandboxVars.rSemiTruck.AdminOnlyMoveUp == true
end

local function isPlayerAdmin(player)
    if not player or not player.getAccessLevel then
        return false
    end

    local accessLevel = player:getAccessLevel() or ""
    return string.lower(accessLevel) == "admin"
end

local function canPlayerUseMoveUp(player, vehicle)
    if isPlayerAdmin(player) then
        return true
    end

    if isMoveUpAdminOnly() then
        return false
    end

    return player ~= nil and vehicle ~= nil
end

local function forceDetachTrailer(vehicle)
    if not vehicle or not vehicle.breakConstraint then
        return false
    end

    local hasTowLink = (vehicle.getVehicleTowing and vehicle:getVehicleTowing())
        or (vehicle.getVehicleTowedBy and vehicle:getVehicleTowedBy())

    if not hasTowLink then
        return false
    end

    pcall(vehicle.breakConstraint, vehicle, true, false)
    return true
end

local function isSemiTrailerVehicle(vehicle)
    if not vehicle or not vehicle.getScript then
        return false
    end

    local script = vehicle:getScript()
    if not script or not script.getFullName then
        return false
    end

    local vehicleName = script:getFullName()
    return vehicleName == "Base.SemiTrailerVan"
        or vehicleName == "Base.SemiTrailerVan_mil"
        or vehicleName == "Base.SemiTrailerVanCattle"
        or vehicleName == "Base.SemiTrailerCistern"
end

-- Handle freezer toggle command from client
function W900Commands.toggleFreezer(player, args)
    --print(("W900 Server: Received toggleFreezer command - active: " .. tostring(args.active))
    
    local vehicle = getVehicleById(args.vehicle)
    if not vehicle then 
        --print(("W900 Server: Vehicle not found: " .. tostring(args.vehicle))
        return 
    end
    
    local part = vehicle:getPartById(args.part)
    if not part then 
        --print(("W900 Server: Part not found: " .. tostring(args.part))
        return 
    end
    
    --print(("W900 Server: Found vehicle and part: " .. part:getId())
    
    -- Initialize modData if needed
    local modData = part:getModData()
    if not modData.tsarslib then
        modData.tsarslib = {}
        --print(("W900 Server: Initialized tsarslib table")
    end
    if not modData.tsarslib.freezer then
        modData.tsarslib.freezer = {}
    end
    
    -- Get old state
    local oldState = modData.tsarslib.active or false
    
    -- Set the active state
    modData.tsarslib.active = args.active
    
    --print(("W900 Server: Freezer " .. part:getId() .. " changed from " .. tostring(oldState) .. " to " .. tostring(args.active))
    
    -- Sync to all clients
    vehicle:transmitPartModData(part)
    
    -- If turning on, ensure temperature is set
    if args.active then
        --print(("W900 Server: Turning freezer ON")
        if part:getItemContainer() then
            part:getItemContainer():setType("freezer")
            part:getItemContainer():setCustomTemperature(0.2)
            part:setLightActive(true)
            --print(("W900 Server: Set container temp to 0.2 and light ON")
        end
    else
        --print(("W900 Server: Turning freezer OFF")
        if part:getItemContainer() then
            part:getItemContainer():setType("TruckBed")
            part:getItemContainer():setCustomTemperature(1.0)
            part:setLightActive(false)
            --print(("W900 Server: Set container temp to 1.0 and light OFF")
        end
    end

    if W900FreezerRuntime and W900FreezerRuntime.notifyClients then
        W900FreezerRuntime.notifyClients(vehicle, part)
    end
end

function W900Commands.moveVehicleImpulse(player, args)
    if not args or not args.vehicle then
        return
    end

    local vehicle = getVehicleById(args.vehicle)
    if not vehicle then
        return
    end

    if not isPlayerNearVehicle(player, vehicle, 5) then
        return
    end

    if not canPlayerUseMoveUp(player, vehicle) then
        return
    end

    forceDetachTrailer(vehicle)

    if vehicle.setPhysicsActive then
        pcall(vehicle.setPhysicsActive, vehicle, true)
    end

    if not (vehicle.addImpulse and Vector3f and Vector3f.new) then
        return
    end

    local mass = vehicle.getMass and vehicle:getMass() or 0
    local lift = 800
    local forceVec = Vector3f.new(0, mass * lift, 0)
    local pushPoint = Vector3f.new(0, 0, 0)

    pcall(vehicle.addImpulse, vehicle, forceVec, pushPoint)
end

function W900Commands.setTrailerPhysicsDisabled(player, args)
    if not args or args.vehicle == nil or args.disabled == nil then
        return
    end

    local vehicle = getVehicleById(args.vehicle)
    if not vehicle or not isSemiTrailerVehicle(vehicle) then
        return
    end

    if not isPlayerNearVehicle(player, vehicle, 8) then
        return
    end

    local disabled = args.disabled == true
    vehicle:getModData()["rSemiTruck.TrailerPhysicsDisabled"] = disabled
    if vehicle.setPhysicsActive then
        pcall(vehicle.setPhysicsActive, vehicle, not disabled)
    end
    if vehicle.transmitModData then
        pcall(vehicle.transmitModData, vehicle)
    end
end

function W900Commands.applyArmorRepair(player, args)
    if not args or args.vehicle == nil or not args.part or args.condition == nil then
        return
    end

    local vehicle = getVehicleById(args.vehicle)
    if not vehicle then
        return
    end

    if not isPlayerNearVehicle(player, vehicle, 8) then
        return
    end

    local part = vehicle:getPartById(args.part)
    if not part then
        return
    end

    ArmorSync.applyVehiclePartCondition(vehicle, part, args.condition)
end

-- Register command handlers
local function OnClientCommand(module, command, player, args)
    if module == 'W900' and W900Commands[command] then
        W900Commands[command](player, args)
    end
end

Events.OnClientCommand.Add(OnClientCommand)
--print(("W900: Server commands registered")
