import { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';
import { EventEmitter } from 'events';
import {
  createClient,
  LiveTranscriptionEvents,
  LiveClient,
  DeepgramClient,
} from '@deepgram/sdk';
import { Buffer } from 'buffer';
import { config } from 'dotenv';

config();

export class TranscriptionService extends EventEmitter {
  private readonly logger = new Logger(TranscriptionService.name);
  private deepgramClient: DeepgramClient;
  private dgConnection: any;
  private finalResult = '';
  private speechFinal = false;
  private streamSid: string;
  private is_pause: Boolean;
  private last_text_time: number;

  constructor() {
    super();
    this.initializeDeepgramConnection();
    this.streamSid = '';
    this.last_text_time = + new Date();
    this.is_pause = true
  }

  private async initializeDeepgramConnection() {
    this.deepgramClient = createClient(process.env.DEEPGRAM_API_KEY);
    // this.deepgramClient = createClient(process.env.DEEPGRAM_API_KEY, {
    //   global: { url: process.env.SERVER },
    // });

    this.dgConnection = this.deepgramClient.listen.live({
      encoding: 'mulaw',
      sample_rate: 8000,
      model: 'nova-2',
      punctuate: true,
      interim_results: true,
      // smart_format: true
      // endpointing: 900,// Time in milliseconds of silence to wait for before finalizing speech
      // utterance_end_ms: 1000,
    });

    this.dgConnection.on(LiveTranscriptionEvents.Open, () => {
      this.logger.log('Deepgram connection opened');
      this.dgConnection.on(
        LiveTranscriptionEvents.Transcript,
        (transcriptionEvent: any) => {
          // console.log('transcriptionEvent',transcriptionEvent);

          // console.time("transcriptionEvent")
          const alternatives = transcriptionEvent.channel?.alternatives;
          // console.time("transcriptionEvent")
          let text = '';
          if (alternatives) {
            text = alternatives[0]?.transcript;
          }

          if (transcriptionEvent.type === 'UtteranceEnd') {

            this.logger.log(
              `UtteranceEnd received before speechFinal. Emitting collected text: ${this.finalResult}`
            );
            if (!this.speechFinal) {
              console.time("Speech to text")
              this.emit('transcription', this.finalResult);
              console.timeEnd("Speech to text")

              return;
            } else {
              this.logger.log(
                'Speech was already final when UtteranceEnd received'
              );
              return;
            }
          }

          if (transcriptionEvent.is_final === true && text.trim().length > 0) {
            this.finalResult += ` ${text}`;
            this.last_text_time = + new Date()
            this.emit('set_audio_send', false);
            if (transcriptionEvent.speech_final === true) {
              this.speechFinal = true;
              console.log('this.finalResult', this.finalResult);
              this.emit('transcription', this.finalResult);
              this.finalResult = '';
            } else {
              this.speechFinal = false;
            }
          } else {
            // console.log('utterance-', text);
            let current_time = + new Date()
            let time_diffrence = current_time - this.last_text_time
            if (this.finalResult.length >= 3 && time_diffrence >= 1300 && !transcriptionEvent.speech_final) {
              console.log("sending from 1000");

              this.speechFinal = true;
              this.emit('transcription', this.finalResult);
              this.finalResult = '';
            } else {
              this.speechFinal = false;
            }
            this.emit('utterance', text);
          }

        }
      );

      // this.handleTranscriptionEvents();
    });

    this.dgConnection.on(LiveTranscriptionEvents.Error, (error: any) => {
      this.logger.error('Deepgram error', error);
      console.log('Deepgram error', error);
    });

    this.dgConnection.on(LiveTranscriptionEvents.Close, () => {
      this.logger.warn('Deepgram connection closed');
    });

    this.dgConnection.on(LiveTranscriptionEvents.Metadata, (metadata: any) => {
      this.logger.debug('Deepgram metadata', metadata);
      this.emit('call_end', { stream_id: this.streamSid, metadata });
    });

    // this.dgConnection.on(LiveTranscriptionEvents.Transcript, (transcriptionEvent: any) => {
    //   console.log('Received transcription event:', JSON.stringify(transcriptionEvent, null, 2));
    // });
  }

  /**
   * Send the payload to Deepgram
   * @param payload A base64 MULAW/8000 audio stream
   */
  async send(payload: string) {
    // await this.initializeDeepgramConnection();
    // console.log("this.dgConnection && this.dgConnection.getReadyState() === 1",this.dgConnection && this.dgConnection.getReadyState() === 1);
    // console.log("payload", payload);

    if (this.dgConnection && this.dgConnection.getReadyState() === 1) {
      // console.log("inside_send");

      this.dgConnection.send(Buffer.from(payload, 'base64'));
    } else {
      // this.logger.error('Connection to Deepgram is not open');
    }
  }

  async keep_alive() {

    if (this.dgConnection && this.dgConnection.getReadyState() === 1) {
      // console.log("inside_send");
      this.dgConnection.keepAlive()
    }

  }

  setStreamSid(streamSid: string) {
    this.streamSid = streamSid;
    // console.log('streamSid', streamSid);
  }

  getStreamSid() {
    return this.streamSid
  }

  // onModuleDestroy() {
  //   this.dgConnection.requestClose();
  //   this.logger.log('Deepgram connection closed on module destroy');
  // }
}
