Kilian is right that there is more to consider than the production database, and that one has to think about how secure the deletion must be. But there is still your core question to answer, how to delete the right things, within the database, assuming you have already his other points in mind, too. You wrote
the system is complex ... If I simply do a cascade delete, it can easily affect how other functionality might operate in unpredictable ways.
This gives me the impression you did not make a thorough impact analysis about the deletion, which semantics the data record relations have, if all integrity requirements of the business are explicitly modeled correctly by using referential integrity mechanisms of the database, which of the existing applications deal with the parts of the data model where the deletion will take place, and so on.
But this is mandatory to get it right , there is no shortcut to this. You need to understand exactly the consequences of your action as good as you can, especially because the system is complex, not "in spite of". Typically, you cannot just look at the data model, you need to read the documentation, find out in which "portions" data is added currently to the database (so you can deduce what to delete by reversing that process), and understand the related business processes, at least to a certain point. If you are lucky, you can ask other colleagues who have that information or, if you are very lucky, others who have helped to develop the parts of the system you have to deal with.
Once you understand the relations in your data model, you will have solved more than 50% of your task and I am pretty sure then you can answer your question by yourself.
Of course, through such an analysis, you might overlook something, and that is why your deletion scripts have to be tested just like any other piece of software - not on the "live database", but on a test system, ideally filled with data from the live system.