-- ---------------------------------------------------------------------------
--  Client half of the request/response bridge.
--  Include with:  client_scripts { '@rp_core/lib/callbacks_client.lua', ... }
--
--  Usage (inside a thread):
--      local result, err = Core.Callback('rp_session', 'auth:login', { ... })
--
--  Reply events are namespaced by the *calling* resource, so two resources
--  can never resolve each other's tokens.
-- ---------------------------------------------------------------------------

Core = Core or {}

local RES     = GetCurrentResourceName()
local pending = {}
local seq     = 0

RegisterNetEvent('rp:cb:res:' .. RES, function(token, result, err)
  local p = pending[token]
  if not p then return end               -- already timed out
  pending[token] = nil
  p:resolve({ result = result, err = err })
end)

--- Blocking request to a server callback. Returns result, err.
--- Always returns; a lost reply surfaces as an error rather than a hang.
function Core.Callback(targetResource, name, payload, timeoutMs)
  seq = seq + 1
  local token = seq
  local p = promise.new()
  pending[token] = p

  TriggerServerEvent('rp:cb:' .. targetResource, RES, name, token, payload)

  CreateThread(function()
    Wait(timeoutMs or 15000)
    local waiting = pending[token]
    if waiting then
      pending[token] = nil
      waiting:resolve({ result = nil, err = 'no response from ' .. targetResource .. '/' .. name })
    end
  end)

  local r = Citizen.Await(p)
  return r.result, r.err
end
