import { BadRequestException, Injectable, NotFoundException, Inject, forwardRef } from '@nestjs/common';
import { CreatePagerDto } from '../dto/create-pager.dto';
import { User } from '../../users/entities/user.entity';
import { EntityManager } from '@mikro-orm/postgresql';
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
import { Pager } from '../entities/pager.entity';
import { PagerStatus } from '../interface/pager';
import { ulid } from 'ulid';
import { Admin } from '../../admin/entities/admin.entity';
import { PagerCreatedEvent } from '../events/pager.events';
import { EventEmitter2 } from '@nestjs/event-emitter';

@Injectable()
export class PagerService {
  constructor(
    private readonly em: EntityManager,
    // @Inject(forwardRef(() => PagerGateway))
    // private readonly pagerGateway: PagerGateway,
    private readonly eventEmitter: EventEmitter2,
  ) {}

  async create(
    createPagerDto: CreatePagerDto,
    params: { restId?: string; userId?: string; slug: string; userCookieId?: string },
  ) {
    const { restId, userId, slug, userCookieId } = params;
    let restaurant: Restaurant | null = null;
    let user: User | null = null;
    if (!restId && !userId && !slug) {
      throw new BadRequestException('Invalid parameters');
    }
    if (restId) {
      restaurant = await this.em.findOne(Restaurant, { id: restId });
      if (!restaurant) {
        throw new NotFoundException('Restaurant not found');
      }
    }
    if (userId) {
      user = await this.em.findOne(User, { id: userId });
      if (!user) {
        throw new NotFoundException('User not found');
      }
    }
    if (!restaurant && slug) {
      restaurant = await this.em.findOne(Restaurant, { slug });
      if (!restaurant) {
        throw new NotFoundException('Restaurant not found');
      }
    }
    const cookieId = userCookieId || ulid().toString();
    // const existingPager = await this.em.findOne(Pager, {
    //   restaurant: { id: restaurant!.id },
    //   status: PagerStatus.Pending,
    //   cookieId,
    // });
    // if (existingPager) {
    //   throw new BadRequestException('Pager already exists');
    // }

    const pager = this.em.create(Pager, {
      ...createPagerDto,
      restaurant: restaurant!,
      user,
      cookieId: ulid().toString(),
      status: PagerStatus.Pending,
    });

    await this.em.persistAndFlush(pager);

    // Populate relations before emitting
    await this.em.populate(pager, ['restaurant']);
    // Emit socket event for new pager
    this.eventEmitter.emit(PagerCreatedEvent.name, new PagerCreatedEvent(pager.restaurant.id, pager.tableNumber));

    return pager;
  }

  async findAll(cookieId: string) {
    const pagers = await this.em.find(Pager, { cookieId }, { populate: ['user'] });
    return pagers;
  }

  async findAllByRestaurantId(restId: string) {
    const pagers = await this.em.find(Pager, { restaurant: { id: restId } }, { populate: ['user'] });
    return pagers;
  }

  async updateStatus(pagerId: string, restId: string, staffId: string, status: PagerStatus) {
    const pager = await this.em.findOne(
      Pager,
      { id: pagerId, restaurant: { id: restId } },
      { populate: ['restaurant'] },
    );
    if (!pager) {
      throw new NotFoundException('Pager not found *');
    }
    const staff = await this.em.findOne(Admin, { id: staffId });
    if (!staff) {
      throw new NotFoundException('Staff not found');
    }
    pager.status = status;
    if (status === PagerStatus.Acknowledged) {
      pager.staff = staff;
    }
    await this.em.persistAndFlush(pager);

    // Populate relations before emitting
    await this.em.populate(pager, ['restaurant', 'staff', 'user']);

    // Emit socket event for status update
    // this.pagerGateway.emitPagerStatusUpdated(pager);

    return pager;
  }
}
