/**
 * Lego 03 / Lego 06 — RAG Chat via NestJS Socket Proxy
 *
 * Sends chat messages to NestJS over the existing /vision Socket.io connection.
 * NestJS forwards the message server-to-server to n8n (no CORS constraint),
 * then emits chat:result back here.
 *
 * This service does NOT open a second socket — it shares the /vision namespace
 * socket with VisionSocketService by injecting VisionSocketService and calling
 * its exposed socket methods. Instead, we open our own /vision socket here
 * specifically for chat so lifecycle is independently managed.
 *
 * Events:
 *   emit  → chat:send   { message: string }
 *   on    ← chat:result  <n8n response object>
 *   on    ← chat:error   { message: string }
 */

import { Injectable, signal, OnDestroy } from '@angular/core';
import { io, Socket } from 'socket.io-client';
import { environment } from '../../environments/environment';

export interface ChatResult {
  output?: string;
  answer?: string;
  response?: string;
  text?: string;
  [key: string]: any;
}

@Injectable({ providedIn: 'root' })
export class ChatSocketService implements OnDestroy {

  readonly sending = signal<boolean>(false);
  readonly lastError = signal<string | null>(null);

  private socket: Socket;

  constructor() {
    this.socket = io(`${environment.nestWsUrl}/vision`, {
      transports: ['websocket'],
      reconnection: true,
      reconnectionDelay: 1000,
    });
  }

  /**
   * Send a chat message to NestJS. NestJS proxies it to n8n server-to-server.
   * Returns a Promise that resolves with the n8n response or rejects on error.
   */
  send(message: string): Promise<ChatResult> {
    return new Promise((resolve, reject) => {
      this.sending.set(true);
      this.lastError.set(null);

      // One-shot listeners — removed immediately after first fire
      const onResult = (data: ChatResult) => {
        cleanup();
        this.sending.set(false);
        resolve(data);
      };

      const onError = (err: { message: string }) => {
        cleanup();
        this.sending.set(false);
        const msg = err?.message ?? 'n8n proxy error';
        this.lastError.set(msg);
        reject(new Error(msg));
      };

      const cleanup = () => {
        this.socket.off('chat:result', onResult);
        this.socket.off('chat:error', onError);
      };

      this.socket.once('chat:result', onResult);
      this.socket.once('chat:error', onError);

      this.socket.emit('chat:send', { message });
    });
  }

  clearBackendSession(): void {
    this.socket.emit('chat:clear');
  }

  ngOnDestroy(): void {
    this.socket.disconnect();
  }
}
