import { Injectable } from "@nestjs/common"
import { Repository } from "typeorm"
import { InjectRepository } from "@nestjs/typeorm"
import {
  ChatParticipant,
  ParticipantType,
} from "../entities/chat-participant.entity"

@Injectable()
export class ChatParticipantRepository {
  constructor(
    @InjectRepository(ChatParticipant)
    private readonly chatParticipantEntity: Repository<ChatParticipant>,
  ) {}

  async save(
    participantData: Partial<ChatParticipant>,
  ): Promise<ChatParticipant> {
    const participant = this.chatParticipantEntity.create(participantData)
    return await this.chatParticipantEntity.save(participant)
  }

  async findByParams(options: {
    where?: any
    relations?: string[]
    select?: string[]
    orderBy?: any
    take?: number
    skip?: number
    findOne?: boolean
  }): Promise<ChatParticipant | ChatParticipant[]> {
    const query = this.chatParticipantEntity.createQueryBuilder("participant")

    if (options.where) {
      Object.entries(options.where).forEach(([key, value]) => {
        if (Array.isArray(value)) {
          query.andWhere(`participant.${key} IN (:...${key})`, { [key]: value })
        } else {
          query.andWhere(`participant.${key} = :${key}`, { [key]: value })
        }
      })
    }

    if (options.relations && options.relations.length > 0) {
      options.relations.forEach((relation) => {
        query.leftJoinAndSelect(`participant.${relation}`, relation)
      })
    }

    if (options.select && options.select.length > 0) {
      query.select(options.select.map((field) => `participant.${field}`))
    }

    if (options.orderBy) {
      Object.entries(options.orderBy).forEach(([field, direction]) => {
        query.orderBy(`participant.${field}`, direction as "ASC" | "DESC")
      })
    }

    if (options.take) {
      query.take(options.take)
    }

    if (options.skip) {
      query.skip(options.skip)
    }

    if (options.findOne) {
      return await query.getOne()
    }

    return await query.getMany()
  }

  async addParticipant(
    chatRoomId: number,
    participantType: ParticipantType,
    participantId: number,
  ): Promise<ChatParticipant> {
    // Check if participant already exists
    const existingParticipant = await this.chatParticipantEntity.findOne({
      where: {
        chat_room_id: chatRoomId,
        participant_type: participantType,
        participant_id: participantId,
      },
    })

    if (existingParticipant) {
      return existingParticipant
    }

    // Add new participant
    return await this.save({
      chat_room_id: chatRoomId,
      participant_type: participantType,
      participant_id: participantId,
    })
  }

  async getParticipantsByChatRoom(
    chatRoomId: number,
  ): Promise<ChatParticipant[]> {
    return await this.chatParticipantEntity.find({
      where: { chat_room_id: chatRoomId },
      relations: ["chat_room"],
    })
  }

  async removeParticipant(
    chatRoomId: number,
    participantType: ParticipantType,
    participantId: number,
  ): Promise<void> {
    await this.chatParticipantEntity.delete({
      chat_room_id: chatRoomId,
      participant_type: participantType,
      participant_id: participantId,
    })
  }
}
