Seems like you've got everything right - a state machine based on instance variables and timers, families, functions etc. That's how games with multiple enemies are made in Construct.
Don't use top-level events like "Enemies state=attack : do something", this is bad practice and bad for performance.
Use Timer behavior to change enemy states and to switch targets. Use LOS and Pathfinding behaviors to look for targets and chase them.
There are lots of ways to pick targets. You can, for example, do something like this if you don't want all enemies to attack one target:
Enemy On "pick_new_target" Timer
Enemy Pick Allies in LOS
.. For each Allies
.... Enemies pick All
.... Pick Enemies that are already targeting this Ally -> Save their count in an instance variable Allies.targetedBy
.. Pick Allies instance with the lowest targetedBy value
If you are new to C3, one of the most important concepts is picking. Once you understand how instances are picked in events (and in nested events), it all starts to make sense.