import { Component, ElementRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subject, debounceTime, distinctUntilChanged } from 'rxjs';
import { ContextMenu } from 'src/app/shared/interfaces/components/context-menu/context-menu.interface';
import { FloatMenu } from 'src/app/shared/interfaces/components/float-menu/float-menu.interface';

import { RecipeFilters } from 'src/app/shared/interfaces/services/api-fit/request/recipe.interface';

import { Recipe } from 'src/app/shared/interfaces/services/api-fit/response/recipe.interface';

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

@Component({
  selector: 'app-foods',
  templateUrl: './foods.component.html',
  styleUrls: ['./foods.component.scss'],
})
export class FoodsComponent {
  containerRef: ElementRef<HTMLDivElement> | null = null;

  floatMenu: FloatMenu = {
    options: [
      {
        icon: 'pencil',
        label: 'Criar receita',
        onClick: () => this.goToCreateRecipe()
      },
    ]
  };

  recipes: Recipe[] = [];
  totalPages = 0;
  favoritesCount = 0;

  debouncedSearch = new Subject<string>();
  debounceTime = 500;

  recipeContextMenu: ContextMenu<Recipe> = {
    isVisible: false,
    position: {
      x: 0,
      y: 0,
    },
  };

  filter: RecipeFilters = {
    page: 1,
    items_per_page: 20,
    self: false,
    from_user_id: 0,
    from_username: '',
    liked_only: false,
    tags_ids: [],
    min_calorie_content_per_portion: 0,
    max_calorie_content_per_portion: 0,
    servings: 0,
    ingredients_ids: [],
    order_by: 'id.desc',
    search_by_name: '',
  };
  filtersCounter = '';
  isModalFiltersOpen = false;

  constructor(
    private apiFitService: ApiFitService,
    private activatedRoute: ActivatedRoute,
    private router: Router,
  ) {}

  ngOnInit() {
    this.setFilterFromQuery();
    this.fetchCountLikedRecipes();

    this.fetchRecipes();

    this.debouncedSearch
      .pipe(debounceTime(this.debounceTime), distinctUntilChanged())
      .subscribe({
        next: () => {
          this.filter.page = 1;
          this.fetchRecipes();
        },
      });
  }

  goToCreateRecipe() {
    this.router.navigate(['/app/foods/create']);
  }

  setFilterFromQuery() {
    this.activatedRoute.queryParams.subscribe({
      next: (p) => {
        const paramsEntries = Object.entries(p).map(([key, value]) => {
          const isNumber = !isNaN(parseFloat(value));

          if (isNumber) return [key, parseFloat(value)];
          return [key, value];
        });

        this.filter = {
          ...this.filter,
          ...Object.fromEntries(paramsEntries),
        };
      },
    });
  }

  scrollContainerTo(scrollTo: ScrollToOptions) {
    if (!this.containerRef?.nativeElement) return;
    this.containerRef.nativeElement.scroll(scrollTo);
  }

  openRecipeContextMenu(recipe: Recipe, ev: MouseEvent) {
    this.recipeContextMenu = {
      isVisible: true,
      data: recipe,
      position: {
        x: ev.pageX,
        y: ev.pageY,
      },
    };
  }

  openModalFilters() {
    this.isModalFiltersOpen = true;
  }

  updateQueryParamsFromFilter() {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const validParams = Object.entries(this.filter).filter(([_, value]) => {
      if (Array.isArray(value)) {
        return !!value.length;
      }

      return !!value;
    });

    const filterParams = Object.fromEntries(validParams);

    this.router.navigate([], {
      relativeTo: this.activatedRoute,
      queryParams: null,
    });

    setTimeout(() => {
      this.router.navigate([], {
        relativeTo: this.activatedRoute,
        queryParams: filterParams,
      });
    }, 100);
  }

  countFilters() {
    const ignoreKeys = ['page', 'search_by_name', 'liked_only', 'items_per_page'];
    const ignoreValues = [0, false, '', 'id.desc'];

    this.activatedRoute.queryParams.subscribe({
      next: (p) => {
        const keysParams = Object.keys(p);

        const validValues = keysParams.filter((k) => {
          return !ignoreKeys.includes(k) && !ignoreValues.includes(p[k]);
        });

        if (validValues.length) {
          this.filtersCounter = `(${validValues.length})`;
        } else {
          this.filtersCounter = '';
        }
      },
    });
  }

  fetchRecipes() {
    this.updateQueryParamsFromFilter();
    this.countFilters();

    this.apiFitService
      .getAllRecipes(this.filter)
      .pipe(distinctUntilChanged())
      .subscribe({
        next: (res) => {
          this.totalPages = res.totalPages ?? 0;
          this.filter.page = res.actualPage ?? 1;
          this.recipes = res.data;

          this.scrollContainerTo({
            behavior: 'smooth',
            top: 0,
          });
        },
        error: () => {
          this.recipes = [];
          this.totalPages = 0;
          this.filter.page = 1;
        },
      });
  }

  fetchCountLikedRecipes() {
    this.apiFitService.countLikedRecipes().subscribe({
      next: (res) => {
        this.favoritesCount = res.data;
      },
    });
  }

  toggleFavoritesOnly() {
    this.filter.page = 1;
    this.filter.liked_only = !this.filter.liked_only;
    this.fetchRecipes();
  }

  handleFavoriteClick(recipe: Recipe, hasLiked: boolean) {
    const recipeIndex = this.recipes.findIndex((r) => r === recipe);

    if (recipeIndex === -1) return;

    this.recipes[recipeIndex] = {
      ...this.recipes[recipeIndex],
      isLiked: hasLiked,
    };
    this.changeFavoritesCounter(hasLiked);

    if (this.filter.liked_only && !hasLiked) {
      this.recipes.splice(recipeIndex, 1);
    }
  }

  changeFavoritesCounter(hasLiked: boolean) {
    this.favoritesCount += hasLiked ? 1 : -1;
  }
}
