import {
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Output,
  SimpleChanges,
} from '@angular/core';
import { Store } from '@ngrx/store';
import { ToastDispatchers } from 'src/app/core/stores/index.dispatchers';

import { UserStore } from 'src/app/core/interfaces/user.interface';
import {
  ContextMenu,
  ContextMenuItem,
} from 'src/app/shared/interfaces/components/context-menu/context-menu.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';
import { Router } from '@angular/router';

@Component({
  selector: 'app-recipe-context-menu',
  templateUrl: './recipe-context-menu.component.html',
  styleUrls: ['./recipe-context-menu.component.scss'],
})
export class RecipeContextMenuComponent implements OnChanges {
  @Input() isVisible = false;
  @Input() recipe?: Recipe;
  @Input() position: ContextMenu<Recipe>['position'] = {
    x: 0,
    y: 0,
  };

  @Output() isVisibleChange = new EventEmitter<boolean>();

  @Output() onEdit = new EventEmitter<void>();
  @Output() onDelete = new EventEmitter<void>();
  @Output() onShare = new EventEmitter<string>();
  @Output() onToggleFavorite = new EventEmitter<boolean>();

  isModalConfirmExclusionOpen = false;

  contextMenuItems: ContextMenuItem[] = [];
  user!: UserStore;

  constructor(
    private store: Store<{ user: UserStore }>,
    private toastDispatchers: ToastDispatchers,
    private apiFitService: ApiFitService,
    private router: Router,
  ) {
    this.store.select('user').subscribe({
      next: (d) => (this.user = d),
      error: () => {
        throw new Error('User store cannot be accessed');
      },
    });
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (!changes['recipe']?.currentValue) return;

    this.setContextMenuItems();
  }

  setContextMenuItems() {
    this.contextMenuItems = [];

    if (!this.recipe) return;

    const isRecipeAuthor = this.user.username === this.recipe.creator;
    const { isLiked } = this.recipe;

    if (isRecipeAuthor) {
      this.contextMenuItems = [
        {
          icon: 'pencil',
          label: 'Editar receita',
          onClick: () => this.goToEdit(),
        },
        {
          icon: 'trash-can',
          label: 'Excluir receita',
          onClick: () => (this.isModalConfirmExclusionOpen = true),
        },
      ];
    }

    this.contextMenuItems = [
      ...this.contextMenuItems,
      {
        icon: 'share',
        label: 'Compartilhar',
        onClick: () => this.copyToClipboard(),
      },
      {
        icon: isLiked ? 'heart-filled' : 'heart-outline',
        label: isLiked ? 'Desfavoritar' : 'Favoritar',
        onClick: () => this.toggleFavorite(),
      },
    ];
  }

  goToEdit() {
    this.router.navigate(['/app/foods/edit', this.recipe?.id]);
  }

  excludeRecipe() {
    if (!this.recipe?.id) return;

    this.apiFitService.excludeRecipe(this.recipe.id).subscribe({
      next: () => {
        this.toastDispatchers.showSuccess({
          isVisible: true,
          delay: 3000,
          message: 'Receita excluída com sucesso',
          shouldHideAutomatically: true,
          showCloseButton: false,
        });
        this.onDelete.emit();
      },
      error: () => {
        this.toastDispatchers.showError({
          isVisible: true,
          delay: 3000,
          message: 'Houve um erro ao excluir a receita',
          shouldHideAutomatically: true,
          showCloseButton: false,
        });
      },
    });
  }

  toggleFavorite() {
    if (!this.recipe) return;

    const { isLiked, id: recipeId } = this.recipe;

    if (isLiked) {
      this.apiFitService
        .unlikeRecipe({
          recipeId,
        })
        .subscribe({
          next: () => {
            if (this.recipe) this.recipe.isLiked = false;
            this.onToggleFavorite.emit(false);
            this.setContextMenuItems();
          },
        });
    } else {
      this.apiFitService
        .likeRecipe({
          recipeId,
        })
        .subscribe({
          next: () => {
            if (this.recipe) this.recipe.isLiked = true;
            this.onToggleFavorite.emit(true);
            this.setContextMenuItems();
          },
        });
    }
  }

  async copyToClipboard() {
    if (!this.recipe?.id) return;

    try {
      const url = this.getRecipeUrl(this.recipe.id);
      await navigator.clipboard.writeText(url);

      this.toastDispatchers.showSuccess({
        isVisible: true,
        delay: 3000,
        message: 'Link da receita copiado com sucesso',
        shouldHideAutomatically: true,
        showCloseButton: false,
      });
    } catch (err) {
      this.toastDispatchers.showError({
        isVisible: true,
        delay: 3000,
        message: 'Houve um erro ao copiar o link',
        shouldHideAutomatically: true,
        showCloseButton: false,
      });
    }
  }

  getRecipeUrl(recipeId: number): string {
    const recipeRoute = `/app/foods/${recipeId}`;
    const baseUrl = location.origin;

    try {
      const url = new URL(recipeRoute, baseUrl);
      return url.toString();
    } catch (err) {
      throw new Error('Error generating recipe url');
    }
  }
}
