```ts
export function normalizePartCode(code: string): string {
  if (typeof code !== 'string') {
    throw new Error('Input must be a string');
  }

  const cleaned = code.replace(/[- ]/g, '').toUpperCase();
  if (cleaned.length !== 9 || !/^[0-9A-Z]+$/.test(cleaned)) {
    throw new Error('Invalid part code format');
  }

  const payload = cleaned.slice(0, 8);
  const checkChar = cleaned[8];

  const weightCycle = [3, 5, 7];
  let sum = 0;
  for (let i = 0; i < payload.length; i++) {
    const value = parseInt(payload[i], 36);
    sum += value * weightCycle[i % weightCycle.length];
  }

  const expectedCheckChar = String.fromCharCode((sum % 36) + 55).toUpperCase();
  if (checkChar !== expectedCheckChar) {
    throw new Error('Invalid check character');
  }

  return `${payload.slice(0, 4)}-${payload.slice(4)}-${checkChar}`;
}
```