import { AddAppCommand } from './add-app';
import { CreateAppCommand } from './create-app';
import { TemplateEngine } from '../template-engine/engine';
import inquirer from 'inquirer';

jest.mock('./create-app');
jest.mock('../template-engine/engine');
jest.mock('inquirer');

describe('AddAppCommand', () => {
  let command: AddAppCommand;
  let mockCreateAppCommand: jest.Mocked<CreateAppCommand>;
  let mockEngine: jest.Mocked<TemplateEngine>;

  beforeEach(() => {
    mockEngine = new TemplateEngine() as jest.Mocked<TemplateEngine>;
    mockCreateAppCommand = {
      execute: jest.fn().mockResolvedValue(undefined)
    } as any;
    
    (CreateAppCommand as jest.Mock).mockImplementation(() => mockCreateAppCommand);
    command = new AddAppCommand(mockEngine);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should prompt for app type when no type is provided', async () => {
    (inquirer.prompt as jest.Mock).mockResolvedValue({ type: 'web' });

    await command.execute();

    expect(inquirer.prompt).toHaveBeenCalledWith([
      expect.objectContaining({
        type: 'list',
        name: 'type',
        message: 'What type of app?',
        choices: expect.arrayContaining([
          expect.objectContaining({ value: 'web' }),
          expect.objectContaining({ value: 'mobile' }),
          expect.objectContaining({ value: 'api' }),
          expect.objectContaining({ value: 'desktop' })
        ])
      })
    ]);

    expect(mockCreateAppCommand.execute).toHaveBeenCalledWith({
      type: 'web'
    });
  });

  it('should use provided app type when given', async () => {
    await command.execute('mobile');

    expect(inquirer.prompt).not.toHaveBeenCalled();
    expect(mockCreateAppCommand.execute).toHaveBeenCalledWith({
      type: 'mobile'
    });
  });

  it('should throw error for invalid app type', async () => {
    await expect(command.execute('invalid')).rejects.toThrow(
      'Invalid app type: invalid. Must be one of: web, mobile, api, desktop'
    );

    expect(mockCreateAppCommand.execute).not.toHaveBeenCalled();
  });

  it('should handle all valid app types', async () => {
    const validTypes = ['web', 'mobile', 'api', 'desktop'];
    
    for (const type of validTypes) {
      await command.execute(type);
      expect(mockCreateAppCommand.execute).toHaveBeenCalledWith({ type });
      jest.clearAllMocks();
    }
  });
});