import { describe, expect, it } from 'vitest';
import { createSpeechTranscriber, MockSpeechTranscriber } from '../index.js';
import type { SpeechTranscriber } from '../index.js';

describe('@bytelyst/speech', () => {
  describe('MockSpeechTranscriber', () => {
    it('implements SpeechTranscriber interface', () => {
      const transcriber: SpeechTranscriber = new MockSpeechTranscriber();
      expect(transcriber.isActive).toBe(false);
    });

    it('start/stop lifecycle works', () => {
      const transcriber = new MockSpeechTranscriber();
      expect(transcriber.isActive).toBe(false);

      transcriber.start();
      expect(transcriber.isActive).toBe(true);

      const result = transcriber.stop();
      expect(transcriber.isActive).toBe(false);
      expect(result).toBe('Hello, this is a mock transcript.');
    });

    it('returns configurable mock transcript', () => {
      const transcriber = new MockSpeechTranscriber();
      transcriber.mockTranscript = 'Custom transcript';
      transcriber.mockConfidence = 0.8;

      transcriber.start();
      const result = transcriber.stop();
      expect(result).toBe('Custom transcript');
    });

    it('calls onFinal callback on stop', () => {
      const transcriber = new MockSpeechTranscriber();
      let receivedText = '';
      let receivedConfidence = 0;

      transcriber.onFinal((text, confidence) => {
        receivedText = text;
        receivedConfidence = confidence;
      });

      transcriber.start();
      transcriber.stop();

      expect(receivedText).toBe('Hello, this is a mock transcript.');
      expect(receivedConfidence).toBe(0.95);
    });

    it('calls onPartial callback on pushAudio', () => {
      const transcriber = new MockSpeechTranscriber();
      let partialText = '';

      transcriber.onPartial(text => {
        partialText = text;
      });

      transcriber.start();
      transcriber.pushAudio(new Uint8Array(100));
      expect(partialText).toBe('[Recording...]');
    });

    it('ignores pushAudio when not active', () => {
      const transcriber = new MockSpeechTranscriber();
      let called = false;
      transcriber.onPartial(() => {
        called = true;
      });

      transcriber.pushAudio(new Uint8Array(100));
      expect(called).toBe(false);
    });

    it('setVocabulary stores phrases', () => {
      const transcriber = new MockSpeechTranscriber();
      transcriber.setVocabulary(['hello', 'world']);
      expect(transcriber.getVocabulary()).toEqual(['hello', 'world']);
    });

    it('simulateError calls onError callback', () => {
      const transcriber = new MockSpeechTranscriber();
      let errorMsg = '';
      transcriber.onError(err => {
        errorMsg = err.message;
      });

      transcriber.simulateError('connection lost');
      expect(errorMsg).toBe('connection lost');
    });
  });

  describe('createSpeechTranscriber', () => {
    it('creates mock transcriber by default', () => {
      const transcriber = createSpeechTranscriber({ provider: 'mock' });
      expect(transcriber).toBeInstanceOf(MockSpeechTranscriber);
    });

    it('throws for azure provider (requires native implementation)', () => {
      expect(() => createSpeechTranscriber({ provider: 'azure' })).toThrow(
        'platform-specific implementation'
      );
    });

    it('throws for whisper provider (requires native implementation)', () => {
      expect(() => createSpeechTranscriber({ provider: 'whisper' })).toThrow(
        'platform-specific implementation'
      );
    });

    it('throws for unknown provider', () => {
      expect(() => createSpeechTranscriber({ provider: 'nonexistent' as 'azure' })).toThrow(
        'Unknown speech provider'
      );
    });
  });
});
