import { Component, Input, OnInit, computed, inject, signal } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { RecipeService } from '../../core/services/recipe.service';
import {
  MealCategory,
  MEAL_CATEGORY_I18N_KEYS,
  RecipeListItem,
} from '../../core/models/recipe.models';
import { ErrorStateComponent } from '../../shared/components/error-state.component';
import { EmptyStateComponent } from '../../shared/components/empty-state.component';
import { GridSkeletonComponent } from '../../shared/components/skeleton.component';
import { RecipeCardComponent } from '../recipes/recipe-card.component';
import { translatePlural } from '../../core/utils/plural-translate.util';
import { extractApiError } from '../../core/utils/api-error.util';
import { nextSort, sortBy, sortIndicator, type SortDirection } from '../../core/utils/sort.util';

type RecipeSortColumn = 'name' | 'calories' | 'prepTime';

@Component({
  selector: 'app-category-page',
  standalone: true,
  imports: [
    TranslatePipe,
    ErrorStateComponent,
    EmptyStateComponent,
    GridSkeletonComponent,
    RecipeCardComponent,
  ],
  template: `
    <div class="space-y-6">
      <header>
        <h1 class="text-2xl font-extrabold tracking-tight sm:text-3xl">{{ categoryLabel | translate }}</h1>
        <p class="mt-1 text-slate-500 dark:text-slate-400">
          @if (recipes()) {
            {{ recipeCountLabel(recipes()!.length) }}
          } @else {
            {{ 'common.loading' | translate }}
          }
        </p>
      </header>

      @if (loading()) {
        <app-grid-skeleton />
      }

      @if (error()) {
        <app-error-state [message]="error()!" [showRetry]="true" (retry)="load()" />
      }

      @if (!loading() && !error() && recipes()?.length === 0) {
        <app-empty-state
          [title]="emptyTitle"
          [description]="'recipes.emptyCategoryDescription' | translate"
        />
      }

      @if (!loading() && !error() && recipes() && recipes()!.length > 0) {
        <div class="flex flex-wrap gap-2 text-sm">
          @for (col of recipeSortColumns; track col.id) {
            <button type="button" class="rounded-lg border border-slate-200 px-3 py-1.5 font-medium hover:bg-slate-50 dark:border-slate-700 dark:hover:bg-slate-800" (click)="toggleRecipeSort(col.id)">
              {{ col.labelKey | translate }}{{ recipeSortIndicator(col.id) }}
            </button>
          }
        </div>
        <div class="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
          @for (recipe of sortedRecipes(); track recipe.id) {
            <app-recipe-card [recipe]="recipe" />
          }
        </div>
      }
    </div>
  `,
})
export class CategoryPageComponent implements OnInit {
  private readonly recipeService = inject(RecipeService);
  private readonly route = inject(ActivatedRoute);
  private readonly translate = inject(TranslateService);

  @Input() category?: MealCategory;

  readonly loading = signal(true);
  readonly error = signal<string | null>(null);
  readonly recipes = signal<RecipeListItem[] | null>(null);
  readonly recipeSort = signal<{ column: RecipeSortColumn; direction: SortDirection }>({
    column: 'name',
    direction: 'asc',
  });
  readonly recipeSortColumns: { id: RecipeSortColumn; labelKey: string }[] = [
    { id: 'name', labelKey: 'manage.recipeName' },
    { id: 'calories', labelKey: 'recipes.calories' },
    { id: 'prepTime', labelKey: 'manage.prepTimeMin' },
  ];

  readonly sortedRecipes = computed(() => {
    const list = this.recipes();
    if (!list) return [];
    const { column, direction } = this.recipeSort();
    return sortBy(list, direction, (recipe) => {
      switch (column) {
        case 'name':
          return recipe.name;
        case 'calories':
          return recipe.calories;
        case 'prepTime':
          return recipe.prepTimeMinutes;
      }
    });
  });

  get categoryLabel(): string {
    const cat = this.resolvedCategory;
    return cat != null ? MEAL_CATEGORY_I18N_KEYS[cat] : 'categories.unknown';
  }

  get emptyTitle(): string {
    return this.translate.instant('recipes.emptyCategoryTitle', {
      category: this.translate.instant(this.categoryLabel),
    });
  }

  private get resolvedCategory(): MealCategory | undefined {
    return this.category ?? this.route.snapshot.data['category'];
  }

  ngOnInit(): void {
    this.load();
  }

  load(): void {
    const category = this.resolvedCategory;
    if (category == null) return;

    this.loading.set(true);
    this.error.set(null);
    this.recipeService.getRecipes({ category }).subscribe({
      next: (data) => {
        this.recipes.set(data);
        this.loading.set(false);
      },
      error: (err) => {
        this.error.set(extractApiError(err, this.translate.instant('errors.loadRecipesFailed')));
        this.loading.set(false);
      },
    });
  }

  recipeCountLabel(count: number): string {
    return translatePlural(this.translate, 'common.recipeCount', count);
  }

  toggleRecipeSort(column: RecipeSortColumn): void {
    this.recipeSort.update((current) => nextSort(current, column));
  }

  recipeSortIndicator(column: RecipeSortColumn): string {
    return sortIndicator(this.recipeSort(), column);
  }
}
