What fee it calculates depends on what transaction outputs it decides to use to fund the new transaction, and (I could be wrong with this point) I don't believe it does so deterministically. So there certainly isn't a way to do it without all the information in wallet.dat, and that might not even be enough.
This is correct.
I believe the solution is providing an RPC call that creates a preliminary transaction (which isn't broadcast yet), but can be inspected. At this point, it can either be committed (broadcast) or reverted through another RPC call.