/**
 * Lego 09 — Surveillance Gateway
 * Lego 11 — Socket Event Schema: monitor:subscribe / monitor:data
 *
 * Registers the Socket.io namespace on port 3000 (shared server).
 * On client subscribe → sends the latest snapshot immediately.
 * Every 500ms tick → SurveillanceService calls back → we broadcast to all.
 */

import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  OnGatewayInit,
  OnGatewayConnection,
  OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Logger, OnModuleInit } from '@nestjs/common';
import { Server, Socket } from 'socket.io';
import { SurveillanceService, MonitorPayload } from './surveillance.service';

@WebSocketGateway({
  cors: { origin: '*' },   // Angular dev server on any port
  namespace: '/monitor',
})
export class SurveillanceGateway
  implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect, OnModuleInit
{
  @WebSocketServer()
  private server!: Server;

  private readonly logger = new Logger(SurveillanceGateway.name);

  constructor(private readonly surveillanceService: SurveillanceService) {}

  // ─── Lifecycle ─────────────────────────────────────────────────────────────

  onModuleInit() {
    // Wire the service callback → broadcasts to all connected clients
    this.surveillanceService.registerMetricsCallback((metrics: MonitorPayload[]) => {
      this.broadcast(metrics);
    });
  }

  afterInit(server: Server) {
    this.logger.log('🔌 SurveillanceGateway initialized on /monitor namespace');
  }

  handleConnection(client: Socket) {
    this.logger.log(`📡 Client connected: ${client.id}`);
    const snapshot = this.surveillanceService.getLatestMetrics();
    if (snapshot.length > 0) {
      client.emit('monitor:data', snapshot);
    }
  }

  handleDisconnect(client: Socket) {
    this.logger.log(`🔌 Client disconnected: ${client.id}`);
  }

  // ─── Event Handlers ────────────────────────────────────────────────────────

  /**
   * Lego 11 — monitor:subscribe
   * UI emits this to start (or re-confirm) the resource tracking stream.
   * We acknowledge and immediately push the latest snapshot.
   */
  @SubscribeMessage('monitor:subscribe')
  handleSubscribe(client: Socket) {
    this.logger.log(`🟢 monitor:subscribe from ${client.id}`);
    const snapshot = this.surveillanceService.getLatestMetrics();
    client.emit('monitor:data', snapshot);
    return { event: 'monitor:subscribed', data: { ok: true } };
  }

  // ─── Broadcast ─────────────────────────────────────────────────────────────

  private broadcast(metrics: MonitorPayload[]) {
    if (this.server) {
      this.server.emit('monitor:data', metrics);
    }
  }
}
