Context-switches only occur when… the context (think of not only cpu registers' value but also page tables, open files handlers, permissions… ) needs to be… switched (changed for others).
Apart from interrupt handling that you already understood, this concept is only known in the context of multiprocessing since in the case of single processing… there is always a unique context.
System calls do not trigger context-switch per se since the kernel, when executing the procedure needs to run in the calling process context and moreover, after completion, the execution is likely to resume on the next instruction of the calling process as if whatever ordinary subroutine had been called.
However, in some cases (blocking read on some opened descriptor for example), the kernel is aware that execution should not resume in the calling process. (since it should instead be waiting for some event to occur)
At the right opposite, chances should be offered for the scheduler to schedule the process out and schedule another one in. Context will necessarily be changed (to the benefit of the scheduled-in process context) => a Context-switch must happen.
To sum up with, a context-switch will systematically occur immediately after some IRQ fires (since the IRQ handler is never executed on behalf of whatever process) whereas a context-switch might occur at some point of the execution of some system call depending on possible scheduling opportunities.