Is there an objective criteria for buttons in a GUI on how to reflect the current state of a button and indicate what happens if you click it? For example an On/Off button where green indicates on and red off. If the button currently shows green does that mean that it is on or that if you click it the you will turn it on? I can think of buttons that are set up either way.
The classic example for this behavior is the humble play/pause button: When the video is paused, do you show the Play symbol (to indicate that you can press the button to initiate playback), or the Pause symbol (to indicate you're currently paused)? This specific issue has been discussed in this question: Separation of play and pause buttons for playing media
In the play/pause case, you always want to show the action in the button; if I want to play a video, my eyes will be on a lookout for triangles, not parallel lines.
Another example is this mode switcher in blender:
Here, the dropdown text always shows the current state, but since it's a dropdown, the affordance to switch between modes is there. (NB: Having a dropdown for modes probably should be a last resort for your app, only utilized in the face of near-overwhelming complexity)
We could split this dropdown into two components by the way, a field showing the mode and a button with the action "change mode".
A third examples are checkboxes and toggles. Their primary purpose is to communicate state, so even though they are interactable just like buttons, they should only ever show state (maybe with a tiny bit of anticipation on hover).
The criterion for when to use which is context. In some cases the state of the app is obvious (playing vs not playing), so the button doesn't need to communicate the state, it's only saving space by combining opposite actions. In others, it needs to only communicate state, and in others still, it needs to do both.
If the context ever is ambiguous, you're generally better off separating state indicator from action.
As a final aside, you may want to avoid coloring buttons as red=bad green=good, as it is ineffective for some color blind users and tends to look fairly noisy. Using primary/secondary or color=enabled grey=disabled patterns generally works better across the board.