import { InjectRepository } from '@nestjs/typeorm';
import {
  WebSocketGateway,
  SubscribeMessage,
  OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Socket } from 'socket.io';
import { Repository } from 'typeorm';
import { LiveMsgDataDto } from '../dto/live-msg-data.dto';
import { LiveMsgData } from '../entities/live-msg-data.entity';
import { JwtService } from '@nestjs/jwt';
@WebSocketGateway()
export class OnlineTeachingGateway implements OnGatewayDisconnect {
  constructor(
    private jwtService: JwtService,
    @InjectRepository(LiveMsgData)
    private lmdRepository: Repository<LiveMsgData>,
  ) {}

  rooms = {};
  handleDisconnect(socket: Socket) {
    const authToken: string = socket.handshake?.auth?.token;
    const user = this.jwtService.decode(authToken.replace('Bearer ', ''));
    console.log(user, this.rooms);
    let roomId = null;
    Object.keys(this.rooms).forEach((item) => {
      if (Object.keys(this.rooms[item].users).includes(user.sub)) {
        roomId = item;
      }
    });

    if (user?.sub && roomId) {
      const data = {
        fromId: user.sub,
        roomId: roomId,
        type: 'leave',
        msg: 'leave',
        timestamp: new Date().getTime(),
        msgStr: null,
      };
      // socket.leave(roomId);
      // delete this.rooms[roomId]?.users[user.sub];
      // this.sendRoomInfo(socket, roomId);
      return this.lmdRepository.insert(data);
    } else {
      return null;
    }
  }
  @SubscribeMessage('join_live_room')
  joinLiveRoom(socket: Socket, data: LiveMsgDataDto) {
    socket.join(data.roomId);
    this.rooms[data.roomId] ??= {};
    this.rooms[data.roomId].users ??= {};
    this.rooms[data.roomId].users[data.from.id] = data.from;
    this.sendRoomInfo(socket, data.roomId);
    return this.sendLiveMsg(socket, data);
  }

  @SubscribeMessage('send_live_msg')
  sendLiveMsg(socket: Socket, data: LiveMsgDataDto) {
    data.timestamp = new Date().getTime();
    socket.to(data.roomId).emit('received_live_msg', data);
    this.saveMsg(data);
    return data;
  }

  @SubscribeMessage('leave_live_room')
  leaveRoom(socket: Socket, data: LiveMsgDataDto) {
    if (Array.isArray(data)) {
      data = data[0];
    }
    socket.leave(data.roomId);
    delete this.rooms[data.roomId]?.users[data.from.id];
    this.sendRoomInfo(socket, data.roomId);
    if (!Object.keys(this.rooms[data.roomId]?.users ?? {})) {
      delete this.rooms[data.roomId];
    }
    this.saveMsg(data);
    return this.sendLiveMsg(socket, data);
  }

  @SubscribeMessage('find_room_info')
  findRoomInfo(socket: Socket, roomId: string) {
    return {
      users: Object.values(this.rooms[roomId]?.users ?? {}),
    };
  }

  async saveMsg(data: LiveMsgDataDto) {
    const { from, roomId, type, msg, timestamp, ...other } = data;
    console.log(this.rooms);
    if (!from?.id) return null;
    return this.lmdRepository.insert({
      fromId: from.id,
      roomId,
      type,
      msg,
      timestamp: timestamp ? timestamp : new Date().getTime(),
      totalUser: this.rooms?.[roomId]
        ? Object.keys(this.rooms[roomId].users).length
        : 0,
      msgStr: Object.keys(other).length ? JSON.stringify(other) : null,
    });
  }

  sendRoomInfo(socket: Socket, roomId: string) {
    socket.to(roomId).emit('room_info', this.findRoomInfo(socket, roomId));
  }
}
