/**
 * Agent Spawning Core Test Suite - Unit Tests
 *
 * Comprehensive test coverage for agent-spawn.ts covering:
 * - Argument parsing and validation
 * - Agent type resolution
 * - Task ID propagation
 * - Context injection (broadcast messages)
 * - Provider parameter handling
 * - Error handling for invalid agent types
 *
 * Target Coverage: ≥80%
 *
 * @version 2.0.0
 * @description Unit tests for critical agent spawning logic
 * @note Tests exported functions directly (no process spawning)
 */

import { describe, test, expect, jest, beforeEach } from '@jest/globals';
import { parseAgentArgs, buildTaskDescription } from '../../src/cli/agent-spawn.js';

describe('Agent Spawning Core - agent-spawn.ts', () => {
  // ============================================================================
  // Argument Parsing Tests
  // ============================================================================

  describe('parseAgentArgs - Argument Parsing', () => {
    test('parses agent type from "agent <type>" pattern', () => {
      const result = parseAgentArgs(['agent', 'researcher', '--task-id', 'task-test']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('researcher');
      expect(result?.taskId).toBe('task-test');
    });

    test('parses agent type from "<type>" pattern (implied agent)', () => {
      const result = parseAgentArgs(['researcher', '--task-id', 'task-123']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('researcher');
      expect(result?.taskId).toBe('task-123');
    });

    test('parses all optional parameters correctly', () => {
      const result = parseAgentArgs([
        'backend-developer',
        '--agent-id', 'agent-001',
        '--task-id', 'task-123',
        '--iteration', '5',
        '--context', 'Implement JWT auth',
        '--mode', 'cli',
        '--priority', '8',
        '--parent-task-id', 'parent-456',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('backend-developer');
      expect(result?.agentId).toBe('agent-001');
      expect(result?.taskId).toBe('task-123');
      expect(result?.iteration).toBe(5);
      expect(result?.context).toBe('Implement JWT auth');
      expect(result?.mode).toBe('cli');
      expect(result?.priority).toBe(8);
      expect(result?.parentTaskId).toBe('parent-456');
    });

    test('handles --parent-task alias for --parent-task-id', () => {
      const result = parseAgentArgs(['tester', '--parent-task', 'parent-789']);

      expect(result).not.toBeNull();
      expect(result?.parentTaskId).toBe('parent-789');
    });

    test('parses integer values correctly', () => {
      const result = parseAgentArgs(['coder', '--iteration', '42', '--priority', '3']);

      expect(result).not.toBeNull();
      expect(result?.iteration).toBe(42);
      expect(result?.priority).toBe(3);
    });

    test('warns on unknown options', () => {
      const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();

      const result = parseAgentArgs(['researcher', '--unknown-flag', 'value']);

      expect(consoleSpy).toHaveBeenCalledWith('Unknown option: --unknown-flag');
      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('researcher');

      consoleSpy.mockRestore();
    });

    test('exits with error when agent type is missing', () => {
      const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();

      const result = parseAgentArgs(['--task-id', 'task-123']);

      expect(result).toBeNull();
      expect(consoleErrorSpy).toHaveBeenCalledWith('Error: Agent type is required');
      expect(consoleErrorSpy).toHaveBeenCalledWith('Usage: cfn-spawn agent <type> [options]');

      consoleErrorSpy.mockRestore();
    });

    test('handles empty arguments array', () => {
      const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();

      const result = parseAgentArgs([]);

      expect(result).toBeNull();
      expect(consoleErrorSpy).toHaveBeenCalledWith('Error: Agent type is required');

      consoleErrorSpy.mockRestore();
    });

    test('handles multiple parameters in sequence', () => {
      const result = parseAgentArgs([
        'frontend-designer',
        '--task-id', 'ui-task',
        '--iteration', '2',
        '--context', 'Design login page',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('frontend-designer');
      expect(result?.taskId).toBe('ui-task');
      expect(result?.iteration).toBe(2);
      expect(result?.context).toBe('Design login page');
    });

    test('handles special characters in agent type', () => {
      const result = parseAgentArgs(['rust-developer', '--task-id', 'special-123']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('rust-developer');
      expect(result?.taskId).toBe('special-123');
    });
  });

  // ============================================================================
  // Edge Cases and Error Scenarios
  // ============================================================================

  describe('parseAgentArgs - Edge Cases', () => {
    test('handles very long context strings', () => {
      const longContext = 'A'.repeat(500);
      const result = parseAgentArgs(['coder', '--context', longContext]);

      expect(result).not.toBeNull();
      expect(result?.context).toBe(longContext);
    });

    test('handles iteration value of 0', () => {
      const result = parseAgentArgs(['reviewer', '--iteration', '0']);

      expect(result).not.toBeNull();
      expect(result?.iteration).toBe(0);
    });

    test('handles negative priority value', () => {
      const result = parseAgentArgs(['tester', '--priority', '-5']);

      expect(result).not.toBeNull();
      expect(result?.priority).toBe(-5);
    });

    test('handles multiple unknown options', () => {
      const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();

      const result = parseAgentArgs([
        'researcher',
        '--unknown1', 'value1',
        '--unknown2', 'value2',
        '--task-id', 'task-123',
      ]);

      expect(consoleSpy).toHaveBeenCalledWith('Unknown option: --unknown1');
      expect(consoleSpy).toHaveBeenCalledWith('Unknown option: --unknown2');
      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('researcher');
      expect(result?.taskId).toBe('task-123');

      consoleSpy.mockRestore();
    });

    test('handles empty string values for parameters', () => {
      const result = parseAgentArgs(['coder', '--context', '', '--task-id', '']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('coder');
      expect(result?.context).toBe('');
      expect(result?.taskId).toBe('');
    });

    test('handles malformed iteration value', () => {
      const result = parseAgentArgs(['validator', '--iteration', 'not-a-number']);

      expect(result).not.toBeNull();
      expect(result?.iteration).toBeNaN();
    });

    test('handles context with special characters', () => {
      const result = parseAgentArgs(['backend-developer', '--context', 'Fix bug #123 @priority']);

      expect(result).not.toBeNull();
      expect(result?.context).toBe('Fix bug #123 @priority');
    });

    test('handles hyphenated agent types', () => {
      const result = parseAgentArgs(['quality-assurance', '--task-id', 'qa-001']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('quality-assurance');
      expect(result?.taskId).toBe('qa-001');
    });

    test('handles numeric task IDs', () => {
      const result = parseAgentArgs(['developer', '--task-id', '12345']);

      expect(result).not.toBeNull();
      expect(result?.taskId).toBe('12345');
    });

    test('handles mixed case agent types', () => {
      const result = parseAgentArgs(['BackendDeveloper']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('BackendDeveloper');
    });
  });

  // ============================================================================
  // Integration Tests
  // ============================================================================

  describe('parseAgentArgs - Integration Tests', () => {
    test('complete spawn cycle with all parameters', () => {
      const result = parseAgentArgs([
        'agent',
        'backend-developer',
        '--agent-id', 'dev-001',
        '--task-id', 'auth-epic',
        '--iteration', '3',
        '--context', 'JWT implementation',
        '--mode', 'api',
        '--priority', '9',
        '--parent-task-id', 'parent-epic',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('backend-developer');
      expect(result?.agentId).toBe('dev-001');
      expect(result?.taskId).toBe('auth-epic');
      expect(result?.iteration).toBe(3);
      expect(result?.context).toBe('JWT implementation');
      expect(result?.mode).toBe('api');
      expect(result?.priority).toBe(9);
      expect(result?.parentTaskId).toBe('parent-epic');
    });

    test('minimal spawn with agent type only', () => {
      const result = parseAgentArgs(['researcher']);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('researcher');
      expect(result?.agentId).toBeUndefined();
      expect(result?.taskId).toBeUndefined();
      expect(result?.iteration).toBeUndefined();
    });

    test('spawn with task context', () => {
      const result = parseAgentArgs([
        'tester',
        '--task-id', 'test-phase',
        '--iteration', '1',
        '--context', 'Run integration tests',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('tester');
      expect(result?.taskId).toBe('test-phase');
      expect(result?.iteration).toBe(1);
      expect(result?.context).toBe('Run integration tests');
    });

    test('spawn with mode and priority', () => {
      const result = parseAgentArgs([
        'validator',
        '--mode', 'hybrid',
        '--priority', '10',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('validator');
      expect(result?.mode).toBe('hybrid');
      expect(result?.priority).toBe(10);
    });

    test('spawn with parent task relationship', () => {
      const result = parseAgentArgs([
        'frontend-designer',
        '--task-id', 'child-task-001',
        '--parent-task-id', 'epic-ui-redesign',
      ]);

      expect(result).not.toBeNull();
      expect(result?.agentType).toBe('frontend-designer');
      expect(result?.taskId).toBe('child-task-001');
      expect(result?.parentTaskId).toBe('epic-ui-redesign');
    });
  });

  // ============================================================================
  // buildTaskDescription Tests
  // ============================================================================

  describe('buildTaskDescription - Task Description Building', () => {
    test('builds basic task description with only agent type', () => {
      const desc = buildTaskDescription('researcher');

      expect(desc).toBe('Execute task as researcher agent');
    });

    test('builds task description with task ID', () => {
      const desc = buildTaskDescription('coder', 'task-123');

      expect(desc).toBe('Execute task as coder agent for task task-123');
    });

    test('builds task description with iteration', () => {
      const desc = buildTaskDescription('tester', 'task-456', 2);

      expect(desc).toBe('Execute task as tester agent for task task-456 (iteration 2)');
    });

    test('builds task description with context', () => {
      const desc = buildTaskDescription('developer', 'task-789', 1, 'Implement auth');

      expect(desc).toBe('Execute task as developer agent for task task-789 (iteration 1): Implement auth');
    });

    test('builds task description with only context (no task ID)', () => {
      const desc = buildTaskDescription('reviewer', undefined, undefined, 'Review code');

      expect(desc).toBe('Execute task as reviewer agent: Review code');
    });

    test('handles empty context string', () => {
      const desc = buildTaskDescription('validator', 'task-001', 1, '');

      expect(desc).toBe('Execute task as validator agent for task task-001 (iteration 1)');
    });

    test('handles zero iteration value', () => {
      const desc = buildTaskDescription('implementer', 'task-002', 0);

      expect(desc).toBe('Execute task as implementer agent for task task-002 (iteration 0)');
    });

    test('builds complex task description', () => {
      const desc = buildTaskDescription(
        'backend-developer',
        'auth-epic-123',
        5,
        'Fix JWT token expiration bug'
      );

      expect(desc).toBe('Execute task as backend-developer agent for task auth-epic-123 (iteration 5): Fix JWT token expiration bug');
    });
  });
});
