import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateCategoryDto } from '../dto/create-category.dto';
import { UpdateCategoryDto } from '../dto/update-category.dto';
import { CategoryRepository } from '../repositories/category.repository';
import { EntityManager } from '@mikro-orm/postgresql';
import { RequiredEntityData } from '@mikro-orm/core';
import { Category } from '../entities/category.entity';
import { CategoryMessage, RestMessage } from 'src/common/enums/message.enum';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';

@Injectable()
export class CategoryService {
  constructor(
    private readonly categoryRepository: CategoryRepository,
    private readonly restaurantsService: RestaurantsService,
    private readonly em: EntityManager,
  ) { }

  async create(restId: string, dto: CreateCategoryDto): Promise<Category> {
    const restaurant = await this.em.findOne(Restaurant, { id: restId });
    if (!restaurant) {
      throw new NotFoundException(RestMessage.NOT_FOUND);
    }
    const data: RequiredEntityData<Category> = {
      title: dto.title,
      isActive: dto.isActive ?? true,
      restaurant: restaurant,
      avatarUrl: dto.avatarUrl,
    };

    const category = this.categoryRepository.create(data);
    await this.em.persistAndFlush(category);
    return category;
  }

  async findAllByRestaurant(slug: string): Promise<Category[]> {
    const restaurant = await this.restaurantsService.findBySlug(slug)
    
    return this.categoryRepository.find(
      { restaurant: restaurant, isActive: true }, { orderBy: { order: 'ASC' } });
  }

  async findAllByRestaurantId(restId: string): Promise<Category[]> {
    return this.categoryRepository.find(
      { restaurant: { id: restId } },
      { orderBy: { order: 'asc' } });
  }

  async findOneOrFail(restId: string, id: string): Promise<Category> {
    const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
    if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
    return cat
  }


  async update(restId: string, id: string, dto: UpdateCategoryDto): Promise<Category> {
    const cat = await this.findOneOrFail(restId, id)
    this.em.assign(cat, dto);
    await this.em.persistAndFlush(cat);
    return cat;
  }

  async remove(restId: string, id: string): Promise<void> {
    const cat = await this.findOneOrFail(restId, id)
    cat.deletedAt = new Date();
    await this.em.persistAndFlush(cat);
  }
}
