/**
 * Unit tests for sanitizeName function in installer.ts
 *
 * These tests verify the sanitization logic for skill names to ensure:
 * - Path traversal attacks are prevented
 * - Names follow kebab-case convention
 * - Special characters are handled safely
 */

import { describe, it, expect } from 'vitest';
import { sanitizeName } from '../src/installer.ts';

describe('sanitizeName', () => {
  describe('basic transformations', () => {
    it('converts to lowercase', () => {
      expect(sanitizeName('MySkill')).toBe('myskill');
      expect(sanitizeName('UPPERCASE')).toBe('uppercase');
    });

    it('replaces spaces with hyphens', () => {
      expect(sanitizeName('my skill')).toBe('my-skill');
      expect(sanitizeName('Convex Best Practices')).toBe('convex-best-practices');
    });

    it('replaces multiple spaces with single hyphen', () => {
      expect(sanitizeName('my   skill')).toBe('my-skill');
    });

    it('preserves dots and underscores', () => {
      expect(sanitizeName('bun.sh')).toBe('bun.sh');
      expect(sanitizeName('my_skill')).toBe('my_skill');
      expect(sanitizeName('skill.v2_beta')).toBe('skill.v2_beta');
    });

    it('preserves numbers', () => {
      expect(sanitizeName('skill123')).toBe('skill123');
      expect(sanitizeName('v2.0')).toBe('v2.0');
    });
  });

  describe('special character handling', () => {
    it('replaces special characters with hyphens', () => {
      expect(sanitizeName('skill@name')).toBe('skill-name');
      expect(sanitizeName('skill#name')).toBe('skill-name');
      expect(sanitizeName('skill$name')).toBe('skill-name');
      expect(sanitizeName('skill!name')).toBe('skill-name');
    });

    it('collapses multiple special chars into single hyphen', () => {
      expect(sanitizeName('skill@#$name')).toBe('skill-name');
      expect(sanitizeName('a!!!b')).toBe('a-b');
    });
  });

  describe('path traversal prevention', () => {
    it('prevents path traversal with ../', () => {
      expect(sanitizeName('../etc/passwd')).toBe('etc-passwd');
      expect(sanitizeName('../../secret')).toBe('secret');
    });

    it('prevents path traversal with backslashes', () => {
      expect(sanitizeName('..\\..\\secret')).toBe('secret');
    });

    it('handles absolute paths', () => {
      expect(sanitizeName('/etc/passwd')).toBe('etc-passwd');
      expect(sanitizeName('C:\\Windows\\System32')).toBe('c-windows-system32');
    });
  });

  describe('leading/trailing cleanup', () => {
    it('removes leading dots', () => {
      expect(sanitizeName('.hidden')).toBe('hidden');
      expect(sanitizeName('..hidden')).toBe('hidden');
      expect(sanitizeName('...skill')).toBe('skill');
    });

    it('removes trailing dots', () => {
      expect(sanitizeName('skill.')).toBe('skill');
      expect(sanitizeName('skill..')).toBe('skill');
    });

    it('removes leading hyphens', () => {
      expect(sanitizeName('-skill')).toBe('skill');
      expect(sanitizeName('--skill')).toBe('skill');
    });

    it('removes trailing hyphens', () => {
      expect(sanitizeName('skill-')).toBe('skill');
      expect(sanitizeName('skill--')).toBe('skill');
    });

    it('removes mixed leading dots and hyphens', () => {
      expect(sanitizeName('.-.-skill')).toBe('skill');
      expect(sanitizeName('-.-.skill')).toBe('skill');
    });
  });

  describe('edge cases', () => {
    it('returns unnamed-skill for empty string', () => {
      expect(sanitizeName('')).toBe('unnamed-skill');
    });

    it('returns unnamed-skill when only special chars', () => {
      expect(sanitizeName('...')).toBe('unnamed-skill');
      expect(sanitizeName('---')).toBe('unnamed-skill');
      expect(sanitizeName('@#$%')).toBe('unnamed-skill');
    });

    it('handles very long names (truncates to 255 chars)', () => {
      const longName = 'a'.repeat(300);
      const result = sanitizeName(longName);
      expect(result.length).toBe(255);
      expect(result).toBe('a'.repeat(255));
    });

    it('handles unicode characters', () => {
      expect(sanitizeName('skill日本語')).toBe('skill');
      expect(sanitizeName('émoji🎉skill')).toBe('moji-skill');
    });
  });

  describe('real-world examples', () => {
    it('handles GitHub repo style names', () => {
      expect(sanitizeName('vercel/next.js')).toBe('vercel-next.js');
      expect(sanitizeName('owner/repo-name')).toBe('owner-repo-name');
    });

    it('handles URLs', () => {
      expect(sanitizeName('https://example.com')).toBe('https-example.com');
    });

    it('handles mintlify style names', () => {
      expect(sanitizeName('docs.example.com')).toBe('docs.example.com');
      expect(sanitizeName('bun.sh')).toBe('bun.sh');
    });
  });
});