#!/usr/bin/env bun
/**
 * Unit tests for validation logic
 * Tests name validation without external dependencies
 */

import { expect, test, describe } from 'bun:test';

// Extracted validation function for testing
function validateStackName(name: string, reservedNames: string[] = []): { valid: boolean; error?: string } {
  if (!name || typeof name !== 'string') {
    return { valid: false, error: 'Name is required' };
  }

  const trimmedName = name.trim().toLowerCase();

  if (trimmedName.length < 3 || trimmedName.length > 20) {
    return { valid: false, error: 'Name must be between 3 and 20 characters' };
  }

  if (!/^[a-z0-9-]+$/.test(trimmedName)) {
    return { valid: false, error: 'Name can only contain lowercase letters, numbers, and hyphens' };
  }

  if (trimmedName.startsWith('-') || trimmedName.endsWith('-')) {
    return { valid: false, error: 'Name cannot start or end with a hyphen' };
  }

  if (reservedNames.includes(trimmedName)) {
    return { valid: false, error: `Name "${trimmedName}" is reserved` };
  }

  return { valid: true };
}

describe('validateStackName', () => {
  const reservedNames = ['admin', 'api', 'www', 'root', 'system', 'test', 'demo', 'portal'];

  test('accepts valid names', () => {
    expect(validateStackName('john', reservedNames).valid).toBe(true);
    expect(validateStackName('alice-123', reservedNames).valid).toBe(true);
    expect(validateStackName('my-stack', reservedNames).valid).toBe(true);
    expect(validateStackName('abc', reservedNames).valid).toBe(true);
    expect(validateStackName('12345678901234567890', reservedNames).valid).toBe(true); // exactly 20 chars
  });

  test('rejects empty or null names', () => {
    expect(validateStackName('', reservedNames).valid).toBe(false);
    expect(validateStackName('   ', reservedNames).valid).toBe(false);
  });

  test('rejects names too short or too long', () => {
    expect(validateStackName('ab', reservedNames).error).toContain('between 3 and 20');
    expect(validateStackName('a'.repeat(21), reservedNames).error).toContain('between 3 and 20');
  });

  test('rejects invalid characters', () => {
    const result1 = validateStackName('john_doe', reservedNames);
    expect(result1.valid).toBe(false);
    expect(result1.error).toBe('Name can only contain lowercase letters, numbers, and hyphens');

    const result2 = validateStackName('john.doe', reservedNames);
    expect(result2.valid).toBe(false);
    expect(result2.error).toBe('Name can only contain lowercase letters, numbers, and hyphens');

    const result3 = validateStackName('john doe', reservedNames);
    expect(result3.valid).toBe(false);
    expect(result3.error).toBe('Name can only contain lowercase letters, numbers, and hyphens');

    const result4 = validateStackName('john@example', reservedNames);
    expect(result4.valid).toBe(false);
    expect(result4.error).toBe('Name can only contain lowercase letters, numbers, and hyphens');
  });

  test('rejects names with leading or trailing hyphens', () => {
    expect(validateStackName('-john', reservedNames).error).toContain('cannot start or end');
    expect(validateStackName('john-', reservedNames).error).toContain('cannot start or end');
    expect(validateStackName('-john-', reservedNames).error).toContain('cannot start or end');
  });

  test('rejects reserved names', () => {
    expect(validateStackName('admin', reservedNames).error).toContain('reserved');
    expect(validateStackName('api', reservedNames).error).toContain('reserved');
    expect(validateStackName('www', reservedNames).error).toContain('reserved');
    expect(validateStackName('root', reservedNames).error).toContain('reserved');
  });

  test('normalizes names (lowercase, trim)', () => {
    // Uppercase input gets normalized to lowercase
    const result1 = validateStackName('  John  ', reservedNames);
    expect(result1.valid).toBe(true); // passes after trim and lowercase

    // Already lowercase with spaces - should pass
    const result2 = validateStackName('  john  ', reservedNames);
    expect(result2.valid).toBe(true);

    // All uppercase - should pass after normalization
    const result3 = validateStackName('MYSTACK', reservedNames);
    expect(result3.valid).toBe(true);
  });
});

console.log('\n✅ Running unit tests...\n');
