import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  ConnectedSocket,
  MessageBody,
  OnGatewayConnection,
} from "@nestjs/websockets"
import { Server, Socket } from "socket.io"
import { AuthService } from "../auth/v1/auth.service"
import moment from "moment"
import { CreateTripSocketDto } from "./dto/create-trip-socket.dto"
import { TripsService } from "../trips/v1/trips.service"
import { ChatMessageRepository } from "../chat/repositories/chat-message.repository"
import { ChatRoomRepository } from "../chat/repositories/chat-room.repository"
import { ChatParticipantRepository } from "../chat/repositories/chat-participant.repository"

import { ChatType } from "../chat/entities/chat-room.entity"
import { SenderType, ReceiverType } from "../chat/entities/chat-message.entity"
import { ParticipantType } from "../chat/entities/chat-participant.entity"

// Socket Event Constants
const SOCKET_EVENTS = {
  // Error Events
  CHAT_ERROR: "chatError",

  // Success Events
  SEND_MESSAGE_SUCCESS: "sendMessageSuccess",
  JOINED_CHAT_ROOM: "joinChatRoomSuccess",
  MARK_MESSAGES_AS_READ_SUCCESS: "markMessagesAsReadSuccess",
  GET_CHAT_HISTORY_SUCCESS: "getChatHistorySuccess",
  GET_MY_CHAT_ROOMS_SUCCESS: "getMyChatRoomsSuccess",
  UPDATE_STATUS_SUCCESS: "updateStatusSuccess",

  // Event Names for Error Context
  SEND_MESSAGE: "sendMessage",
  JOIN_CHAT_ROOM: "joinChatRoom",
  MARK_MESSAGES_AS_READ: "markMessagesAsRead",
  GET_CHAT_HISTORY: "getChatHistory",
  GET_MY_CHAT_ROOMS: "getMyChatRooms",
  UPDATE_STATUS: "updateStatus",
} as const
import { CustomersService } from "../customers/v1/customers.service"

@WebSocketGateway({ cors: { origin: "*" } })
export class TripSocketGateway implements OnGatewayConnection {
  @WebSocketServer()
  server: Server

  constructor(
    private readonly tripService: TripsService,
    private readonly authService: AuthService,
    private readonly chatMessageRepository: ChatMessageRepository,
    private readonly chatRoomRepository: ChatRoomRepository,
    private readonly chatParticipantRepository: ChatParticipantRepository,
    private readonly customerService: CustomersService,
  ) {}

  async handleConnection(client: Socket) {
    try {
      const token =
        client.handshake.auth?.token ||
        client.handshake.headers?.authorization?.replace("Bearer ", "")

      const isCustomer = client.handshake.auth?.isCustomer

      if (!token) {
        console.log("Socket disconnected: No token provided")
        client.disconnect()
        return
      }

      // Get user by token
      if (isCustomer) {
        const loggedInCustomer =
          await this.customerService.getCustomerByToken(token)
        if (!loggedInCustomer) {
          console.log("Socket disconnected: Customer not found")
          client.disconnect()
          return
        }

        if (loggedInCustomer.deleted_at) {
          console.log("Socket disconnected: Customer is deleted")
          client.disconnect()
          return
        }

        // Skip token expiration check for Android and iOS devices
        const deviceTypeCustomer = loggedInCustomer.device_type?.toLowerCase()
        const isMobileDeviceCustomer =
          deviceTypeCustomer === "android" || deviceTypeCustomer === "ios"

        if (!isMobileDeviceCustomer) {
          const expirationTimeCustomer = moment(
            loggedInCustomer.access_token_expire_at,
          ).utc(true)
          const currentTime = moment().utc(true)

          if (currentTime >= expirationTimeCustomer) {
            console.log("Socket disconnected: Customer token expired")
            client.disconnect()
            return
          }
        }

        ;(client as any).customer = loggedInCustomer

        console.log("Socket connected:", loggedInCustomer.customer_id)
      } else {
        const loggedInUser = await this.authService.getUserByToken(token)
        if (!loggedInUser) {
          console.log("Socket disconnected: User not found")
          client.disconnect()
          return
        }

        if (loggedInUser.is_deleted) {
          console.log("Socket disconnected: User is deleted or inactive")
          client.disconnect()
          return
        }

        // Skip token expiration check for Android and iOS devices
        const deviceType = loggedInUser.device_type?.toLowerCase()
        const isMobileDevice = deviceType === "android" || deviceType === "ios"

        if (!isMobileDevice) {
          const expirationTime = moment(
            loggedInUser.access_token_expire_at,
          ).utc(true)
          const currentTime = moment().utc(true)

          if (currentTime >= expirationTime) {
            await this.authService.logout(token)
            console.log("Socket disconnected: User token expired")
            client.disconnect()
            return
          }
        }

        ;(client as any).user = loggedInUser
        console.log("Socket connected:", loggedInUser.user_id)
      }
    } catch (error) {
      console.error("Socket authentication error:", error)
      client.disconnect()
    }
  }

  @SubscribeMessage("updateLocation")
  async handleUpdateLocation(@MessageBody() data: CreateTripSocketDto) {
    const parsedData = typeof data === "string" ? JSON.parse(data) : data

    const location = await this.tripService.saveTripLocation(parsedData)
    this.server.to(`trip-${data.trip_id}`).emit("locationUpdate", location)
    return { status: "ok", location }
  }

  @SubscribeMessage("joinTrip")
  handleJoinTrip(
    @MessageBody() tripId: number,
    @ConnectedSocket() client: Socket,
  ) {
    client.join(`trip-${tripId}`)
    return { status: "ok", message: `Joined room trip-${tripId}` }
  }

  @SubscribeMessage("getLatestLocation")
  async handleGetLatestLocation(
    @MessageBody() tripId: number,
    // @ConnectedSocket() client: Socket,
  ) {
    const latest = await this.tripService.getLatestTripLocation(tripId)
    // Send back directly to requester
    return { status: "ok", latest }
  }

  @SubscribeMessage("sendMessage")
  async handleSendMessage(
    @MessageBody()
    data: {
      sender_id: number
      receiver_id: number
      message: string
      chat_room_id: number
    },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const { receiver_id, message, chat_room_id, sender_id } = data

      if (!sender_id || !receiver_id || !message || !chat_room_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message:
            "Missing required fields: sender_id, receiver_id, message, chat_room_id",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (typeof message !== "string" || message.trim().length === 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Message cannot be empty",
          error_code: "INVALID_MESSAGE",
        })
        return
      }

      if (message.length > 1000) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Message too long. Maximum 1000 characters allowed",
          error_code: "MESSAGE_TOO_LONG",
        })
        return
      }

      // Get chat room details with participants to determine sender and receiver types
      let chatRoom
      try {
        chatRoom = await this.chatRoomRepository.findByParams({
          where: { id: chat_room_id },
          relations: ["participants"],
          findOne: true,
        })
      } catch (dbError) {
        console.error("Database error while fetching chat room:", dbError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Failed to retrieve chat room",
          error_code: "DATABASE_ERROR",
        })
        return
      }

      if (!chatRoom) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Chat room not found",
          error_code: "CHAT_ROOM_NOT_FOUND",
        })
        return
      }

      // Find sender participant details
      const senderParticipant = chatRoom.participants?.find(
        (p) => p.participant_id === sender_id,
      )

      // Find receiver participant details
      const receiverParticipant = chatRoom.participants?.find(
        (p) => p.participant_id === receiver_id,
      )

      if (!senderParticipant) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Sender not found in chat room participants",
          error_code: "SENDER_NOT_IN_CHAT",
        })
        return
      }

      if (!receiverParticipant) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Receiver not found in chat room participants",
          error_code: "RECEIVER_NOT_IN_CHAT",
        })
        return
      }

      // Validate participant types
      if (
        !senderParticipant.participant_type ||
        !receiverParticipant.participant_type
      ) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Invalid participant configuration in chat room",
          error_code: "INVALID_PARTICIPANT_TYPE",
        })
        return
      }

      // Save message with error handling
      let chatMessage
      try {
        chatMessage = await this.chatMessageRepository.saveMessage(
          chat_room_id,
          senderParticipant.participant_type as SenderType,
          sender_id,
          receiverParticipant.participant_type as ReceiverType,
          receiver_id,
          message.trim(),
        )
      } catch (saveError) {
        console.error("Error saving message:", saveError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Failed to save message",
          error_code: "SAVE_MESSAGE_FAILED",
        })
        return
      }

      if (!chatMessage || !chatMessage.id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.SEND_MESSAGE,
          status: "error",
          message: "Failed to create message",
          error_code: "MESSAGE_CREATION_FAILED",
        })
        return
      }

      // Send message to all other participants in the chat room
      this.server.to(`chat-room-${chat_room_id}`).emit("newMessage", {
        id: chatMessage.id,
        chat_room_id: chat_room_id,
        sender_type: senderParticipant.participant_type,
        sender_id: sender_id,
        receiver_type: receiverParticipant.participant_type,
        receiver_id: receiver_id,
        message_text: message.trim(),
        created_at: chatMessage.created_at,
        is_read: false,
      })

      // Send confirmation to sender
      client.emit(SOCKET_EVENTS.SEND_MESSAGE_SUCCESS, {
        status: "ok",
        message: "Message sent successfully",
        data: {
          id: chatMessage.id,
          chat_room_id: chat_room_id,
          sender_id: sender_id,
          receiver_id: receiver_id,
          message_text: message.trim(),
          created_at: chatMessage.created_at,
        },
      })
    } catch (error) {
      console.error("Unexpected error in handleSendMessage:", error)
      client.emit(SOCKET_EVENTS.CHAT_ERROR, {
        event: SOCKET_EVENTS.SEND_MESSAGE,
        status: "error",
        message: "An unexpected error occurred while sending message",
        error_code: "INTERNAL_ERROR",
      })
    }
  }

  @SubscribeMessage("joinChatRoom")
  async handleJoinChatRoom(
    @MessageBody()
    data: {
      current_user_id: number
      current_user_type?: string
      target_user_id: number
      target_user_type?: string
      trip_id?: number
      chat_type?: string
    },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const {
        current_user_id,
        current_user_type = "team_member",
        target_user_id,
        target_user_type = "team_member",
        trip_id,
        chat_type,
      } = data

      if (!current_user_id || !target_user_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message: "Missing required fields: current_user_id, target_user_id",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (current_user_id === target_user_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message: "Cannot create chat room with yourself",
          error_code: "INVALID_CHAT_PARTICIPANTS",
        })
        return
      }

      // Validate user types
      const validUserTypes = ["team_member", "customer"]
      if (!validUserTypes.includes(current_user_type)) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message:
            "Invalid current_user_type. Must be 'team_member' or 'customer'",
          error_code: "INVALID_USER_TYPE",
        })
        return
      }

      if (!validUserTypes.includes(target_user_type)) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message:
            "Invalid target_user_type. Must be 'team_member' or 'customer'",
          error_code: "INVALID_TARGET_USER_TYPE",
        })
        return
      }

      // Find existing chat room between current user and target user
      let chatRoom
      try {
        chatRoom =
          await this.chatRoomRepository.findChatRoomBetweenParticipants(
            current_user_type,
            current_user_id,
            target_user_type,
            target_user_id,
            trip_id,
          )
      } catch (dbError) {
        console.error("Database error while finding chat room:", dbError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message: "Failed to search for existing chat room",
          error_code: "DATABASE_ERROR",
        })
        return
      }

      // If chat room not found, create one
      if (!chatRoom) {
        try {
          // Create chat room
          chatRoom = await this.chatRoomRepository.findOrCreateChatRoom(
            chat_type as ChatType,
            trip_id,
            { teamMemberId: current_user_id, customerId: target_user_id },
          )
        } catch (createError) {
          console.error("Error creating chat room:", createError)
          client.emit(SOCKET_EVENTS.CHAT_ERROR, {
            event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
            status: "error",
            message: "Failed to create chat room",
            error_code: "CHAT_ROOM_CREATION_FAILED",
          })
          return
        }

        if (!chatRoom || !chatRoom.id) {
          client.emit(SOCKET_EVENTS.CHAT_ERROR, {
            event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
            status: "error",
            message: "Failed to create chat room - no ID returned",
            error_code: "CHAT_ROOM_CREATION_FAILED",
          })
          return
        }

        // Add all participants to chat room with error handling
        if (current_user_id && current_user_type) {
          try {
            await this.chatParticipantRepository.addParticipant(
              chatRoom.id,
              current_user_type as ParticipantType,
              current_user_id,
            )
          } catch (addParticipantError) {
            console.error(
              "Error adding current user to chat room:",
              addParticipantError,
            )
            client.emit(SOCKET_EVENTS.CHAT_ERROR, {
              event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
              status: "error",
              message: "Failed to add current user to chat room",
              error_code: "ADD_PARTICIPANT_FAILED",
            })
            return
          }
        }

        if (target_user_id && target_user_type) {
          try {
            await this.chatParticipantRepository.addParticipant(
              chatRoom.id,
              target_user_type as ParticipantType,
              target_user_id,
            )
          } catch (addParticipantError) {
            console.error(
              "Error adding target user to chat room:",
              addParticipantError,
            )
            client.emit(SOCKET_EVENTS.CHAT_ERROR, {
              event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
              status: "error",
              message: "Failed to add target user to chat room",
              error_code: "ADD_PARTICIPANT_FAILED",
            })
            return
          }
        }
      }

      if (!chatRoom || !chatRoom.id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message: "Invalid chat room - no ID available",
          error_code: "INVALID_CHAT_ROOM",
        })
        return
      }

      // Join the socket room for this chat
      client.join(`chat-room-${chatRoom.id}`)

      // Get chat history for this room with error handling
      let history
      try {
        history = await this.chatMessageRepository.getChatHistory(
          chatRoom.id,
          50,
          0,
        )
      } catch (historyError) {
        console.error("Error getting chat history:", historyError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
          status: "error",
          message: "Failed to retrieve chat history",
          error_code: "GET_HISTORY_FAILED",
        })
        return
      }

      client.emit(SOCKET_EVENTS.JOINED_CHAT_ROOM, {
        status: "ok",
        message: `Joined chat room ${chatRoom.id}`,
        data: {
          chat_room_id: chatRoom.id,
          chat_type: chatRoom.chat_type,
          history: history,
        },
      })
      return
    } catch (error) {
      console.error("Unexpected error in handleJoinChatRoom:", error)
      client.emit(SOCKET_EVENTS.CHAT_ERROR, {
        event: SOCKET_EVENTS.JOIN_CHAT_ROOM,
        status: "error",
        message: "An unexpected error occurred while joining chat room",
        error_code: "INTERNAL_ERROR",
      })
    }
  }

  @SubscribeMessage("markMessagesAsRead")
  async handleMarkMessagesAsRead(
    @MessageBody() data: { receiver_id: number; chat_room_id: number },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const { receiver_id, chat_room_id } = data

      if (!receiver_id || !chat_room_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "Missing required fields: receiver_id, chat_room_id",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (receiver_id <= 0 || chat_room_id <= 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "Invalid receiver_id or chat_room_id",
          error_code: "INVALID_ID",
        })
        return
      }

      // Get user participant type in this chat room with error handling
      let userParticipant
      try {
        userParticipant = await this.chatParticipantRepository.findByParams({
          where: {
            chat_room_id: chat_room_id,
            participant_id: receiver_id,
          },
          findOne: true,
        })
      } catch (dbError) {
        console.error("Database error while finding participant:", dbError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "Failed to verify participant in chat room",
          error_code: "DATABASE_ERROR",
        })
        return
      }

      if (!userParticipant) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "User not a participant in this chat room",
          error_code: "USER_NOT_PARTICIPANT",
        })
        return
      }

      // Validate participant type
      if (!userParticipant.participant_type) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "Invalid participant configuration",
          error_code: "INVALID_PARTICIPANT_TYPE",
        })
        return
      }

      // Mark messages as read with error handling
      try {
        await this.chatMessageRepository.markMessagesAsRead(
          chat_room_id,
          receiver_id,
          userParticipant.participant_type as SenderType | ReceiverType,
        )
      } catch (markError) {
        console.error("Error marking messages as read:", markError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
          status: "error",
          message: "Failed to mark messages as read",
          error_code: "MARK_READ_FAILED",
        })
        return
      }

      client.emit(SOCKET_EVENTS.MARK_MESSAGES_AS_READ_SUCCESS, {
        status: "ok",
        message: "Messages marked as read successfully",
      })
    } catch (error) {
      console.error("Unexpected error in handleMarkMessagesAsRead:", error)
      client.emit(SOCKET_EVENTS.CHAT_ERROR, {
        event: SOCKET_EVENTS.MARK_MESSAGES_AS_READ,
        status: "error",
        message: "An unexpected error occurred while marking messages as read",
        error_code: "INTERNAL_ERROR",
      })
    }
  }

  @SubscribeMessage("getChatHistory")
  async handleGetChatHistory(
    @MessageBody()
    data: {
      user_id: number
      chat_room_id: number
      limit?: number
      skip?: number
    },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const { user_id, chat_room_id, limit = 50, skip = 0 } = data

      if (!user_id || !chat_room_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Missing required fields: user_id, chat_room_id",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (user_id <= 0 || chat_room_id <= 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Invalid user_id or chat_room_id",
          error_code: "INVALID_ID",
        })
        return
      }

      if (limit <= 0 || limit > 100) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Invalid limit. Must be between 1 and 100",
          error_code: "INVALID_LIMIT",
        })
        return
      }

      if (skip < 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Invalid skip value. Must be >= 0",
          error_code: "INVALID_SKIP",
        })
        return
      }

      // Verify user is a participant in this chat room with error handling
      let userParticipant
      try {
        userParticipant = await this.chatParticipantRepository.findByParams({
          where: {
            chat_room_id: chat_room_id,
            participant_id: user_id,
          },
          findOne: true,
        })
      } catch (dbError) {
        console.error("Database error while verifying participant:", dbError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Failed to verify participant in chat room",
          error_code: "DATABASE_ERROR",
        })
        return
      }

      if (!userParticipant) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "User not a participant in this chat room",
          error_code: "USER_NOT_PARTICIPANT",
        })
        return
      }

      // Validate participant type
      if (!userParticipant.participant_type) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Invalid participant configuration",
          error_code: "INVALID_PARTICIPANT_TYPE",
        })
        return
      }

      // Get chat history with error handling
      let messages
      try {
        messages = await this.chatMessageRepository.getChatHistory(
          chat_room_id,
          limit,
          skip,
        )
      } catch (historyError) {
        console.error("Error getting chat history:", historyError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_CHAT_HISTORY,
          status: "error",
          message: "Failed to retrieve chat history",
          error_code: "GET_HISTORY_FAILED",
        })
        return
      }

      // Mark messages as read when retrieving history with error handling
      try {
        await this.chatMessageRepository.markMessagesAsRead(
          chat_room_id,
          user_id,
          userParticipant.participant_type,
        )
      } catch (markError) {
        console.error("Error marking messages as read:", markError)
        // Don't return error here as the main operation (getting history) succeeded
        console.warn(
          "Failed to mark messages as read, but continuing with response",
        )
      }

      client.emit(SOCKET_EVENTS.GET_CHAT_HISTORY_SUCCESS, {
        status: "ok",
        message: "Chat history retrieved successfully",
        data: messages,
      })
    } catch (error) {
      console.error("Unexpected error in handleGetChatHistory:", error)
      client.emit("getChatHistoryError", {
        status: "error",
        message: "An unexpected error occurred while retrieving chat history",
        error_code: "INTERNAL_ERROR",
      })
    }
  }

  @SubscribeMessage("getMyChatRooms")
  async handleGetMyChatRooms(
    @MessageBody() data: { user_id: number; user_type?: string },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const { user_id, user_type = "team_member" } = data

      if (!user_id) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Missing required field: user_id",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (user_id <= 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Invalid user_id",
          error_code: "INVALID_ID",
        })
        return
      }

      // Validate user type
      const validUserTypes = ["team_member", "customer"]
      if (!validUserTypes.includes(user_type)) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Invalid user_type. Must be 'team_member' or 'customer'",
          error_code: "INVALID_USER_TYPE",
        })
        return
      }

      // Get chat rooms where user is a participant with error handling
      let chatRooms
      try {
        chatRooms = await this.chatRoomRepository.getChatRoomsByParticipant(
          user_type,
          user_id,
        )
      } catch (dbError) {
        console.error("Database error while getting chat rooms:", dbError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Failed to retrieve chat rooms",
          error_code: "DATABASE_ERROR",
        })
        return
      }

      if (!Array.isArray(chatRooms)) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Invalid chat rooms data",
          error_code: "INVALID_DATA",
        })
        return
      }

      // Get unread counts for each chat room with error handling
      let chatRoomsWithUnread
      try {
        chatRoomsWithUnread = await Promise.all(
          chatRooms.map(async (room) => {
            if (!room || !room.id) {
              console.warn("Invalid room data:", room)
              return null
            }

            const participantType =
              room.participants.find((p) => p.participant_id === user_id)
                ?.participant_type || user_type

            let unreadCount = 0
            try {
              unreadCount = await this.chatMessageRepository.getUnreadCount(
                participantType,
                user_id,
              )
            } catch (unreadError) {
              console.error(
                "Error getting unread count for room:",
                room.id,
                unreadError,
              )
              // Continue with 0 as fallback
            }

            return {
              id: room.id,
              chat_type: room.chat_type,
              trip_id: room.trip_id,
              created_at: room.created_at,
              participants: room.participants,
              last_message: room.messages?.[room.messages.length - 1] || null,
              unread_count: unreadCount,
            }
          }),
        )
      } catch (mapError) {
        console.error("Error processing chat rooms:", mapError)
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
          status: "error",
          message: "Failed to process chat rooms data",
          error_code: "PROCESSING_ERROR",
        })
        return
      }

      // Filter out null values
      chatRoomsWithUnread = chatRoomsWithUnread.filter((room) => room !== null)

      client.emit(SOCKET_EVENTS.GET_MY_CHAT_ROOMS_SUCCESS, {
        status: "ok",
        message: "Chat rooms retrieved successfully",
        data: chatRoomsWithUnread,
      })
    } catch (error) {
      console.error("Unexpected error in handleGetMyChatRooms:", error)
      client.emit(SOCKET_EVENTS.CHAT_ERROR, {
        event: SOCKET_EVENTS.GET_MY_CHAT_ROOMS,
        status: "error",
        message: "An unexpected error occurred while retrieving chat rooms",
        error_code: "INTERNAL_ERROR",
      })
    }
  }

  @SubscribeMessage("updateStatus")
  async handleUpdateStatus(
    @MessageBody() data: { trip_id: number; status: string },
    @ConnectedSocket() client: Socket,
  ) {
    try {
      // Validate input data
      const { trip_id, status } = data

      if (!trip_id || !status) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.UPDATE_STATUS,
          status: "error",
          message: "Missing required fields: trip_id, status",
          error_code: "MISSING_REQUIRED_FIELDS",
        })
        return
      }

      if (trip_id <= 0) {
        client.emit(SOCKET_EVENTS.CHAT_ERROR, {
          event: SOCKET_EVENTS.UPDATE_STATUS,
          status: "error",
          message: "Invalid trip_id",
          error_code: "INVALID_ID",
        })
        return
      }

      this.server
        .to(`trip-${trip_id}`)
        .emit(SOCKET_EVENTS.UPDATE_STATUS_SUCCESS, {
          status: "ok",
          message: "Status update sent successfully",
          data: {
            trip_id,
            status,
            timestamp: new Date().toISOString(),
          },
        })
      return {
        status: "ok",
        message: "Status update sent successfully",
        data: {
          trip_id,
          status,
          timestamp: new Date().toISOString(),
        },
      }
    } catch (error) {
      console.error("Unexpected error in handleUpdateStatus:", error)
      client.emit(SOCKET_EVENTS.CHAT_ERROR, {
        event: SOCKET_EVENTS.UPDATE_STATUS,
        status: "error",
        message: "An unexpected error occurred while updating status",
        error_code: "INTERNAL_ERROR",
      })
    }
  }
}
