import { AbstractRepository } from "./AbstractRepository.js";
import { RecipeEntity } from "../entities/RecipeEntity.js";
import { AppDataSource } from "../data-source.js";
import { ILike, Like } from "typeorm";

export class RecipeRepository extends AbstractRepository<RecipeEntity> {
  constructor() {
    super(RecipeEntity);
  }

  /**
   * Find recipe including all relations by id
   * @param id Recipe id
   * @returns RecipeEntity including all relations such as ingredients groups, ingredients and instruction steps
   */
  async findById(id: string): Promise<RecipeEntity | null> {
    return this.repo.findOne(
    { where: { id } as any,
      relations: [
        'ingredientGroups', 
        'ingredientGroups.ingredients',
        'instructionSteps'
      ] 
    });
  }

  /**
   * Find all recipes matching the search. Currently it only searches on the title. Fetches only recipe header data but no relations.
   * @param searchString String to search for
   * @returns List of recipe entities matching the search criteria
   */
  async findCompactRecipeBySearch(searchString : string): Promise<RecipeEntity[] | null>{
    // @todo doesn't work like expected...
    return this.repo.find(
      { where: {title: ILike(`%${searchString}%`)}}
    );
  }

  /**
   * Update recipe and relations
   * @param entity Updated entity
   * @returns Updated Entity
   */
  async updateRecipe(entity: RecipeEntity): Promise<RecipeEntity> {
  return AppDataSource.transaction(async (em) => {
    // load existing data
    const existing = await this.repo.findOneOrFail({
      where: { id: entity.id },
      relations: ["instructionSteps", "ingredientGroups", "ingredientGroups.ingredients"],
    });

    // merge new entity and existing entity
    this.repo.merge(existing, entity);
    return this.repo.save(existing);
  });
}

}