Blockstate files are a way for the game to change what model a block is using, depending on how it appears in the environment/world around it. In essence, they point to a model within the '.../models/block/...' folder. Here's a vanilla dispenser blockstate:
Note: Not all blocks have the same tags that you can use like 'facing='. It depends on the functionality of the block.
If you want to find these tags, they're actually displayed on the right-hand side of the F3 debug screen when you look at a block (if it has any).
These change the shape of a block in-game. Their functionality (interactions/GUIs) and hitboxes remain the same.
Here, you can create parent models. For the most part, these contain code that is common to a large group of models, and instead of writing the same code again and again, the child models link to the parent and essentially copy their properties.
Stone says "here is a texture, I'm going to call it '#all'". Then it parents to 'cube_all'.
'cube_all' says "I'm going to take '#all' and assign it to all 6 faces". Those faces are created in 'cube' which is the parent.
'cube' says "I will take those 6 faces and assign them on a cube shape". Lastly, it parents to 'block'.
'block' says "Anything that points to me needs to have this rotation, translation & scale in all these different places in the UI".
Essentially block models change how any block looks and points to all the textures it uses on the model.
These are fairly simple. They just change the colors you see on a block. They can be any size (>0) as long as they are square (except for animated ones).
Block models and textures can actually have any name and can be placed anywhere under 'models/block/...' & 'textures/...' respectively.
If you want to make a full, proper resource pack, the hierarchy goes: Blockstate (points to) --> Model (points to) --> Texture.
You've probably been using it but the Model page on the MC Wiki is a very good place to check your code structure is right. Especially the code trees that tell you what text can and can't be in blockstate or model files.
If you want to change the shape of a block, use models.
If you want to change the different variations of a block, use blockstates.
If you want to change how a block looks visually, use textures.
Phew, I put waaayyy too much effort into this reply. Hope this helps.