I do it with two variables:
var cameraAngle = Vector2.ZERO
var cameraZoom = 2.25
cameraAngle is a vector2, X is horizontal rotation and Y is vertical. cameraZoom is the distance the camera should be away from the player.
I clamp them with:
cameraAngle.x = fmod(cameraAngle.x, 2*PI)
cameraAngle.y = clamp(cameraAngle.y, 0.01, PI-0.01)
(X isn't clamped, but if the angle is greater than 360, it goes back to 0. Both 0.01s are just a small margin to prevent error.)
and apply camera position with:
X+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*cos(cameraAngle.x))
Z+=sqrt(cameraZoom)*sin(cameraAngle.y)*(sqrt(cameraZoom)*sin(cameraAngle.x))
Y+=cameraZoom*cos(cameraAngle.y)
XY&Z should be the camera's XY&Z position, I shortened it to make it easier to read.
Then for movement(I use a variable called moveDir, works the same as your direction), instead of something like this:
moveDir.x -= Input.get_action_strength("p1_move_left")
I have this:
moveDir.x -= cos(cameraAngle.x)*Input.get_action_strength("p1_move_forward")
moveDir.z -= sin(cameraAngle.x)*Input.get_action_strength("p1_move_forward")
moveDir.x -= cos(cameraAngle.x+PI)*Input.get_action_strength("p1_move_backward")
moveDir.z -= sin(cameraAngle.x+PI)*Input.get_action_strength("p1_move_backward")
moveDir.x -= cos(cameraAngle.x+(270*PI/180))*Input.get_action_strength("p1_move_left")
moveDir.z -= sin(cameraAngle.x+(270*PI/180))*Input.get_action_strength("p1_move_left")
moveDir.x -= cos(cameraAngle.x+(90*PI/180))*Input.get_action_strength("p1_move_right")
moveDir.z -= sin(cameraAngle.x+(90*PI/180))*Input.get_action_strength("p1_move_right")
which handles movement in all directions(+ analog strength, works with joysticks). You probably don't need to understand this part, I've forgotten how exactly it works. But this code should do the trick.
I also clamp moveDir:
moveDir = Vector3(clamp(moveDir.x, -1, 1),clamp(moveDir.y, -1, 1),clamp(moveDir.z, -1, 1))
I can explain more, tell me if you have any questions(and this is one method, I think I used another one in a different game).