Should software test automation projects echo the structure of the
application in test?
If "Echo" means to follow the same structure as the project from a code perspective (e.g. have package structure matching the application code) then no, not necessarily. If "Echo" means to model the application effectively - then yes, that can be very helpful.
For example, you might have workflow, usecase, or connector classes. For instance, if you have an application that writes reports and has a DB, you may have a ApplicationConnector class, a ReportConnector class, and a DatabaseConnector class. ApplicationConnector might have methods like generateReport(), which in turn invokes the application. The complexity of it is hidden away so in your test methods/steps you simply have applicationConnector.generateReport() making things very simple, readable, maintainable.
That is, would they use the services and APIs the application uses,
and if they do, to what extent?
Generally no, it's best to mock these if required. i.e. have a mock application with returns some standard response. This way you're not dependent on 3rd party behaviour and can also force some fail conditions like a timeout - which you couldn't force a 3rd party to do. (e.g. "Hey accuweather, if I send a request with test_001 will you guys wait 30 seconds to give a response?" - not feasable).
Is there a recognized best practice in test automation of large,
complex application?
Break it down, try testing component by component for starters. Start with the smallest easiest flow and build things up from there. Mock whatever parts you can. Model the application ecosystem. Use objects in your tests effectively, use patterns when it helps e.g. builder type pattern to build up a REST Request body. Keep the code as simple as possible. Keep in mind that less experience folks may work on it (manual testers transitioning to automation) so you want it easy for them to pick up and hard for them to introduce garbage code.