each class should have a unit test
This is not strictly true. There is little value in assertions such as “each method should be covered” or “we should have 95% branch coverage.”
If you have parts of your code which contain complex logic, that caused you headaches in the past, and that is often modified, make sure you have through testing.
If you have a class that is little more than a DTO, and which is part of the code base that wasn't modified for the past ten years, why would you add a test for that? What's the value?
that would mean integrating the services with each other
Exactly. This is why there are different types of tests. Unit tests are rather limited to, well, the unit they are testing. And as they do it in isolation, through stubs and mocks, they won't catch issues that would arise when those units are interacting with each other. Here's the value of integration tests and system tests.
Make sure, however, to understand the limitation of integration and system tests. As they cover a larger part of the code base than a unit test, they:
Are usually slower than unit tests. This means that you won't be able to have tens of thousands of them for a medium-size application.
Can fail for numerous reasons, and won't point you to the location of the issue. By comparison, a unit test (if correctly designed) will necessarily point you to at least the class, and at best the method or the line of code which causes an issue—or the issue would be in the test itself or its stubs/mocks.
Integration and system tests are also usually prone to the issues with the infrastructure itself. For instance, a misconfigured proxy server could easily make all your system tests go red. This is not necessarily a good thing: you should be able to identify such infrastructure issues through other means, such as smoke tests.
Also, should the controller have unit tests, or would all be covered with the C1-S1 integration test?
If the controller has its own complex logic that is being actively modified, add unit tests. Or think about moving this logic to a dedicated class—a common practice is to keep controllers very basic.