import { SpeechRecognition } from '../speech-recognition/SpeechRecognition';
import { Context } from '../context/Context';
import { PluginManager } from '../plugin-manager/PluginManager';

// Mock dependencies
jest.mock('../context/Context');
jest.mock('../plugin-manager/PluginManager');

describe('SpeechRecognition', () => {
  let mockContext: jest.Mocked<Context>;
  let mockPluginManager: jest.Mocked<PluginManager>;

  beforeEach(() => {
    mockContext = {
      updateConfig: jest.fn(),
      connection: {
        removeAllListeners: jest.fn(),
        on: jest.fn(),
      },
      recorder: {
        on: jest.fn(),
      },
    } as any;

    mockPluginManager = {
      callPlugin: jest.fn(),
      unregisterAllPlugin: jest.fn(),
    } as any;

    (Context as jest.Mock).mockImplementation(() => mockContext);
    (PluginManager as jest.Mock).mockImplementation(() => mockPluginManager);
  });

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

  describe('constructor', () => {
    it('should create SpeechRecognition instance', () => {
      const recognition = new SpeechRecognition();
      expect(recognition).toBeInstanceOf(SpeechRecognition);
      expect(mockPluginManager.callPlugin).toHaveBeenCalledWith('onInit');
    });

    it('should create instance with config', () => {
      const config = { plugins: [] };
      const recognition = new SpeechRecognition(config);
      expect(recognition).toBeInstanceOf(SpeechRecognition);
    });
  });

  describe('start', () => {
    it('should start recognition with valid URL', () => {
      const recognition = new SpeechRecognition();
      const url = 'wss://example.com/asr';

      recognition.start({ url });

      expect(mockContext.updateConfig).toHaveBeenCalledWith({ url });
      expect(mockPluginManager.callPlugin).toHaveBeenCalledWith('onWsConnect');
    });

    it('should throw error if URL is not provided', () => {
      const recognition = new SpeechRecognition();

      expect(() => {
        recognition.start({ url: '' });
      }).toThrow('url is required');
    });
  });

  describe('reStart', () => {
    it('should restart recognition with valid URL', () => {
      const recognition = new SpeechRecognition();
      const url = 'wss://example.com/asr';

      recognition.reStart({ url });

      expect(mockContext.connection.removeAllListeners).toHaveBeenCalled();
      expect(mockContext.updateConfig).toHaveBeenCalledWith({ url });
      expect(mockPluginManager.callPlugin).toHaveBeenCalledWith('onWsConnect');
    });

    it('should throw error if URL is not provided', () => {
      const recognition = new SpeechRecognition();

      expect(() => {
        recognition.reStart({ url: '' });
      }).toThrow('url is required');
    });
  });

  describe('stop', () => {
    it('should stop recognition', () => {
      const recognition = new SpeechRecognition();

      recognition.stop();

      expect(mockPluginManager.callPlugin).toHaveBeenCalledWith('onBeforeStop');
    });
  });

  describe('destroy', () => {
    it('should destroy recognition instance', () => {
      const recognition = new SpeechRecognition();

      recognition.destroy();

      expect(mockPluginManager.callPlugin).toHaveBeenCalledWith('onDestroy');
      expect(mockPluginManager.unregisterAllPlugin).toHaveBeenCalled();
    });
  });
});

