import { Injectable } from '@angular/core';
import { Category } from '../../../core/categories/models/category-domain.model';
import { Product } from '../../../core/products/models/product-domain.model';
import { SearchSuggestion } from '../models/search.model';

@Injectable({ providedIn: 'root' })
export class SearchAutocompleteService {
  createSuggestions(query: string, products: Product[], categories: Category[] = [], limit = 10): SearchSuggestion[] {
    const normalized = query.trim().toLowerCase();
    if (normalized.length < 2) {
      return [];
    }

    const productSuggestions: SearchSuggestion[] = this.collectUniqueById(
      products
        .filter(item => item.name.toLowerCase().includes(normalized))
        .slice(0, limit)
        .map(item => ({
          id: `product-${item.itemID}`,
          type: 'product' as const,
          title: item.name,
          text: item.name,
          kind: 'live' as const,
          subtitle: item.simpleDescription ?? '',
          icon: 'package',
          target: { route: '/product', params: { id: item.itemID } },
          score: this.score(item.name, normalized),
        }))
    );

    const categorySuggestions: SearchSuggestion[] = this.collectUniqueById(
      categories
        .filter(item => item.title.toLowerCase().includes(normalized))
        .slice(0, Math.ceil(limit / 2))
        .map(item => ({
          id: `category-${item.id}`,
          type: 'category' as const,
          title: item.title,
          text: item.title,
          kind: 'live' as const,
          subtitle: '',
          icon: 'folder',
          target: { route: '/catalog', params: { id: item.id } },
          score: this.score(item.title, normalized),
        }))
    );

    const brandSuggestions: SearchSuggestion[] = this.collectUniqueById(
      products
        .flatMap(item => item.tags ?? [])
        .filter(tag => tag.toLowerCase().includes(normalized))
        .slice(0, Math.ceil(limit / 2))
        .map(tag => ({
          id: `brand-${tag}`,
          type: 'brand' as const,
          title: tag,
          text: tag,
          kind: 'live' as const,
          subtitle: '',
          icon: 'tag',
          target: { route: '/search', query: { q: tag } },
          score: this.score(tag, normalized),
        }))
    );

    const aiSuggestion: SearchSuggestion | null = normalized.length >= 4
      ? {
          id: `ai-${normalized}`,
          type: 'ai',
          title: query,
          text: query,
          kind: 'live',
          subtitle: 'search.aiSuggestionHint',
          icon: 'zap',
          target: { route: '/search', query: { q: query } },
          score: 0,
        }
      : null;

    return [...productSuggestions, ...categorySuggestions, ...brandSuggestions, ...(aiSuggestion ? [aiSuggestion] : [])]
      .sort((a, b) => (b.score ?? 0) - (a.score ?? 0))
      .slice(0, limit);
  }

  private score(value: string, query: string): number {
    const normalized = value.toLowerCase();
    if (normalized.startsWith(query)) {
      return 2;
    }

    if (normalized.includes(query)) {
      return 1;
    }

    return 0;
  }

  private collectUniqueById<T extends { id: string }>(items: T[]): T[] {
    const map = new Map<string, T>();
    for (const item of items) {
      if (!map.has(item.id)) {
        map.set(item.id, item);
      }
    }

    return [...map.values()];
  }
}
