import {
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
  WsResponse,
  OnGatewayConnection,
  OnGatewayDisconnect,
  MessageBody,
  ConnectedSocket,
} from '@nestjs/websockets';
import { from, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Server, WebSocket } from 'ws';
import { StreamService } from '../services/stream.service';
import { TranscriptionService } from '../services/transcription.service';
import { TextToSpeechService } from '../services/tts.service';
import { RagService } from '../rag/rag.service';

@WebSocketGateway()
export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  constructor(private ragService: RagService) {}

  handleConnection(client: WebSocket) {
    console.log('Client connected');
    const streamService = new StreamService(client);
    const transcriptionService = new TranscriptionService();
    const ttsService = new TextToSpeechService();
    client.on('message', async (data: any) => {
      const msg = JSON.parse(data);
      //   client.send(JSON.stringify({ event: 'ack', ack: 'ok' }));
      if (msg.event === 'start') {
        console.log('msg', msg);
        const { streamSid, callSid } = msg.start;
        streamService.setStreamSid(streamSid);
        // this.gptService.setCallSid(callSid);

        ttsService.generate(
          {
            partialResponseIndex: null,
            partialResponse:
              "Hello! I understand you're looking for a pair of AirPods, is that correct?",
          },
          0
        );
      } else if (msg.event === 'media') {
        transcriptionService.send(msg.media.payload);
      } else if (msg.event === 'mark') {
        const label = msg.mark.name;
        console.log(`Twilio -> Audio completed mark: ${label}`);
      } else if (msg.event === 'stop') {
        console.log(`Twilio -> Media stream ended.`);
      }
    });

    ttsService.on('speech', (responseIndex, audio, label, icount) => {
      console.log(`Interaction ${icount}: TTS -> TWILIO: ${label}`);

      streamService.buffer(responseIndex, audio);
    });

    transcriptionService.on('transcription', async (text) => {
      if (!text) {
        return;
      }
      // console.log(`Interaction ${'interactionCount'} – STT -> GPT: ${text}`);
      // gptService.completion(text, interactionCount);
      // interactionCount += 1;
      let data = await this.ragService.getAnswerRag(text);
      console.log('gpt-rply', data);
      ttsService.generate(
        {
          partialResponseIndex: null,
          partialResponse: data.answer,
        },
        0
      );
    });

    transcriptionService.on('utterance', async (text) => {
      if (!text) {
        return;
      }
      console.log(`Interaction ${'interactionCount'} – STT -> GPT: ${text}`);
      // gptService.completion(text, interactionCount);
      // interactionCount += 1;
    });
    client.on('error', (error) => console.error('WebSocket error:', error));
    client.on('close', () => console.log('Client disconnected'));
  }

  handleDisconnect(client: WebSocket) {
    console.log('Client disconnected');
  }
}
