3D rotation animation for CAGradientLayer

How to rotate in 3D CAGradientLayer from left to right when a user taps on it and after the second tap rotate it back (from right to left)? And also I need to change a gradient to different colors in the middle of animation (basically when the view rotates on 90 degrees and it gets "hidden" from the user's eyes)

For some reason, my implementation rotates the view only in one direction (left to right). I've tried to play with negative PI but the result was kind of weird. What I've got so far

func open() {

    var flipTransform: CATransform3D
    flipTransform = CATransform3DIdentity
    flipTransform.m34 = 1.0 / -1000
    flipTransform = CATransform3DRotate(flipTransform, .pi, 0.0, 1.0, 0.0)

    UIView.animate(withDuration: 2.0, animations: {
        self.tile.layer.transform = flipTransform
        DispatchQueue.main.asyncAfter(deadline: .now() + self.duration / 2, execute: {
            self.addGradientLayer(from: .red, to: .yellow)
        })
    })
}

func close() {

    UIView.animate(withDuration: 2.0, animations: {
        self.tile.layer.transform = CATransform3DIdentity
        DispatchQueue.main.asyncAfter(deadline: .now() + self.duration / 2, execute: {
            self.addGradientLayer(from: .black, to: .lightGray)
        })
    })

}

func addGradientLayer(from: UIColor, to: UIColor) {
    tile.layer.sublayers?.filter { $0 is CAGradientLayer }.forEach { $0.removeFromSuperlayer() }
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = tile.bounds
    gradientLayer.colors = [from.cgColor, to.cgColor]
    gradientLayer.locations = [0.0, 1.0]
    gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
    gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
    tile.layer.insertSublayer(gradientLayer, at: 0)
}