I think I've found a workaround (I've not had a bad shutdown in a while now). I went back to my original DSDT and customised the _PTS method so when the arg is 5, I do a load of sleep(0x14) commands (I put ten of them in one after another in succession).
My hunch was that given the machine sometimes shuts down quickly but other times didn't (but did always shutdown in the end eventually), something somewhere low level was running too fast and there was a race condition happening which caused things to get into a weird state sometimes. As such I decided to try slowing down the method by adding the aforementioned ten sleep(0x14)commands in. Now it seems to shutdown reliably all the time straight away, no more hanging. Bizarre.
I'm not even sure exactly what this command does so it's very hacky but it does seem to work.
Would be interested to know if you think there's a more elegant way I could make the machine wait within the _PTS arg 5, but no worries if not, it seems like I've fixed the issue myself now. Thanks for your support