import { Injectable } from "@nestjs/common"
import { Repository } from "typeorm"
import { InjectRepository } from "@nestjs/typeorm"
import { ChatConversation } from "../entities/chat-conversation.entity"

@Injectable()
export class ChatConversationRepository {
  constructor(
    @InjectRepository(ChatConversation)
    private readonly chatConversationEntity: Repository<ChatConversation>,
  ) {}

  async save(
    conversationData: Partial<ChatConversation>,
  ): Promise<ChatConversation> {
    const conversation = this.chatConversationEntity.create(conversationData)
    return await this.chatConversationEntity.save(conversation)
  }

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

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

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

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

    if (options.orderBy) {
      Object.entries(options.orderBy).forEach(([field, direction]) => {
        query.orderBy(`conversation.${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 findOrCreateConversation(
    dispatcherId: number,
    driverId: number,
  ): Promise<ChatConversation> {
    let conversation = await this.chatConversationEntity.findOne({
      where: [
        { dispatcher_id: dispatcherId, driver_id: driverId },
        { dispatcher_id: driverId, driver_id: dispatcherId },
      ],
    })

    if (!conversation) {
      conversation = await this.chatConversationEntity.save({
        dispatcher_id: dispatcherId,
        driver_id: driverId,
      })
    }

    return conversation
  }

  async updateUnreadCount(
    userId: number,
    isDispatcher: boolean,
  ): Promise<void> {
    const field = isDispatcher
      ? "dispatcher_unread_count"
      : "driver_unread_count"

    await this.chatConversationEntity
      .createQueryBuilder()
      .update(ChatConversation)
      .set({ [field]: () => `${field} + 1` })
      .where(isDispatcher ? "dispatcher_id = :userId" : "driver_id = :userId", {
        userId,
      })
      .execute()
  }

  async resetUnreadCount(userId: number, isDispatcher: boolean): Promise<void> {
    const field = isDispatcher
      ? "dispatcher_unread_count"
      : "driver_unread_count"

    await this.chatConversationEntity
      .createQueryBuilder()
      .update(ChatConversation)
      .set({ [field]: 0 })
      .where(isDispatcher ? "dispatcher_id = :userId" : "driver_id = :userId", {
        userId,
      })
      .execute()
  }
}
