import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Output,
  SimpleChanges,
} from '@angular/core';
import { forkJoin, map } from 'rxjs';

import {
  FoodCardProps,
  FoodType,
} from 'src/app/shared/interfaces/components/cards/food-card/food-card.interface';
import { RecipeFilters } from 'src/app/shared/interfaces/services/api-fit/request/recipe.interface';
import { Ingredient } from 'src/app/shared/interfaces/services/api-fit/response/ingredient.interface';

import { ApiFitService } from 'src/app/shared/services/api-fit/api-fit.service';

@Component({
  selector: 'app-add-food',
  templateUrl: './add-food.component.html',
  styleUrls: ['./add-food.component.scss'],
})
export class AddFoodComponent implements OnChanges {
  @Input() isVisible = false;
  @Input() searchType: FoodType = 'food';
  @Input() addedFood: FoodCardProps | null = null;
  @Input() foodName = '';
  @Input() canEdit = true;

  @Output() isVisibleChange = new EventEmitter<boolean>();
  @Output() addedFoodChange = new EventEmitter<FoodCardProps | null>();
  @Output() onAddFood = new EventEmitter<FoodCardProps>();

  results: FoodCardProps[] = [];
  page = 1;
  maxPages = 1;

  selectedFood: FoodCardProps | null = null;
  selectedFoodIngredients: Ingredient[] = [];
  selectedFoodServings = 1;
  selectedFoodQuantityMultiplier = 1;

  typesLabels: Record<FoodType, string> = {
    food: 'Alimento',
    recipe: 'Receita',
  };

  constructor(private apiFitService: ApiFitService) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['addedFood']?.currentValue) {
      this.selectedFood = changes['addedFood'].currentValue;
      this.foodName = this.addedFood?.name.replace(/,/g, '') ?? '';
    }

    if (changes['foodName']) {
      this.handleSearch(changes['foodName'].currentValue);
    }

    if (changes['isVisible']) {
      const isVisible = changes['isVisible'].currentValue;

      if (!isVisible) return;
      this.handleSearch(this.foodName);
    }
  }

  onSearch(term: string) {
    this.page = 1;
    this.handleSearch(term);
  }

  handleSearch(term: string) {
    this.foodName = term;

    this.results = [];
    this.selectedFoodIngredients = [];

    if (!this.foodName) {
      this.getRecommendations();
      return;
    }

    if (this.selectedFood) {
      this.handleSelectFood(this.selectedFood);
    }

    if (this.searchType === 'food') {
      this.apiFitService
        .getFoods({
          page: this.page,
          search_by_name: this.foodName,
          items_per_page: 4,
        })
        .pipe(
          map((res) => {
            this.page = res.actualPage;
            this.maxPages = res.totalPages;

            return res.data;
          }),
        )
        .subscribe({
          next: (foods) =>
            (this.results = [
              ...this.results,
              ...foods.map((food) => {
                return {
                  ...food,
                  kcal: food.kcalPer100,
                  quantity: 100,
                  type: 'food',
                } as FoodCardProps;
              }),
            ]),
        });

      return;
    }

    if (this.searchType === 'recipe') {
      this.apiFitService
        .getAllRecipes({
          page: this.page,
          search_by_name: this.foodName,
        } as RecipeFilters)
        .pipe(
          map((res) => {
            this.page = res.actualPage;
            this.maxPages = res.totalPages;

            return res.data;
          }),
        )
        .subscribe({
          next: (recipes) =>
            (this.results = [
              ...this.results,
              ...recipes.map((recipe) => {
                return {
                  ...recipe,
                  quantity: 1,
                  type: 'recipe',
                } as FoodCardProps;
              }),
            ]),
        });

      return;
    }
  }

  getRecommendations() {
    if (this.searchType === 'food') {
      this.apiFitService.getFrequentAddedFoods().subscribe({
        next: (d) =>
          (this.results = d.data.map((food) => {
            return {
              ...food,
              kcal: food.kcalPer100,
              quantity: 100,
              type: 'food',
            };
          })),
      });

      return;
    }

    if (this.searchType === 'recipe') {
      this.apiFitService
        .getRecommendedRecipes()
        .pipe(
          map((d) => {
            return {
              ...d,
              data: d.data.slice(0, 5),
            };
          }),
        )
        .subscribe({
          next: (r) =>
            (this.results = r.data.map((recipe) => {
              return {
                ...recipe,
                quantity: 1,
                type: 'recipe',
              };
            })),
        });

      return;
    }
  }

  handleSelectFood(food: FoodCardProps) {
    this.selectedFood = food;
    this.selectedFoodServings = 1;

    if (food.type === 'food') {
      this.selectedFoodQuantityMultiplier = 1;

      this.apiFitService.getFoodById(food.id).subscribe({
        next: (res) => {
          this.selectedFood = {
            ...food,
            kcal: res.data.kcalPer100,
          };

          this.selectedFoodIngredients = [
            {
              ...res.data,
              quantity: food.quantity,
            },
          ];
        },
        error: () => {
          this.selectedFood = null;
          this.selectedFoodIngredients = [];
        },
      });

      return;
    }

    if (food.type === 'recipe') {
      forkJoin([
        this.apiFitService.getRecipeById(food.id),
        this.apiFitService.getRecipeIngredients({
          recipeId: food.id,
        }),
      ]).subscribe({
        next: ([resRecipe, resIngredients]) => {
          this.selectedFoodQuantityMultiplier = food.quantity;

          this.selectedFoodServings = resRecipe.data.servings;
          this.selectedFoodIngredients = resIngredients.data;
        },
        error: () => {
          this.selectedFood = null;
          this.selectedFoodIngredients = [];
          this.selectedFoodQuantityMultiplier = 1;
          this.selectedFoodServings = 1;
        },
      });

      return;
    }
  }

  updateSelectedFood(updatedFood: FoodCardProps) {
    this.selectedFood = updatedFood;

    if (updatedFood.type === 'food') {
      this.selectedFoodQuantityMultiplier = 1;
      this.selectedFoodServings = 1;

      this.selectedFoodIngredients = [
        {
          ...this.selectedFoodIngredients[0],
          quantity: updatedFood.quantity,
        },
      ];
    } else {
      this.selectedFoodQuantityMultiplier = updatedFood.quantity;
    }
  }

  getIngredientsMultiplied() {
    return this.selectedFoodIngredients.map((ingredient) => {
      return {
        ...ingredient,
        quantity: ingredient.quantity * this.selectedFoodQuantityMultiplier,
      };
    });
  }

  handleClose() {
    this.isVisible = false;
    this.isVisibleChange.emit(false);
    this.selectedFood = null;
  }

  handleAddFood(food: FoodCardProps | null) {
    if (!food) return;

    this.addedFoodChange.emit(food);
    this.onAddFood.emit(food);

    this.handleClose();
  }
}
