To me this perfectly fits spaghetti code.
https://www.joelonsoftware.com/2001/04/21/dont-let-architect...
For the record, this one is not that bad. It is comprehensible and pretty easy to refactor. Real spaghetti is something you have no idea what it does.
That's usually termed lasagna code. Lots of layers with a little bit of filling in between.
Just use global state! Then you can have something where Module A depends on Module B. Now, at one point Module A calls into Module B which fires off an event that's handled in Module C that then calls back into Module A. If that event is going through a pub/sub notifier, bam, hidden global state. Good luck tracing that subtle bug down when you swapped out implementations of Module C thinking the new one explicitly filled the contract of the old one, or worse yet not realizing Module B indirectly depended on C in the first place, and that A's response to the call from C may repeat the cycle several times. Soon you realize everything depends on everything else and your tooling does you no good. That's spaghetti code, just as bad or worse than the gotos sprinkled through some ugly C code that an undergrad wrote in the 80s.
Personally i associate it with lack of abstractions, or extremely leaky abstractions.