import { Component, signal, HostListener, OnDestroy, ChangeDetectionStrategy, inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CartService } from '../../services';
import { PrefetchService } from '../../services/prefetch.service';
import { Item } from '../../models';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { getDiscountedPrice, getMainImage, trackByItemId, getBadgeClass, getTranslatedField } from '../../utils/item.utils';
import { LanguageService } from '../../services/language.service';
import { TranslatePipe } from '../../i18n/translate.pipe';
import { TranslateService } from '../../i18n/translate.service';
import { SEARCH_DEBOUNCE_MS, ITEMS_PER_PAGE, SCROLL_THRESHOLD_PX, SCROLL_DEBOUNCE_MS } from '../../config/constants';
import { ProductFacade } from '../../facades/platform/product.facade';
import { ProductCardComponent } from '../../components/product-card/product-card.component';
import { IconComponent } from '../../shared/ui/icon/icon.component';
import { SkeletonComponent } from '../../shared/ui/skeleton/skeleton.component';

@Component({
  selector: 'app-search',
  imports: [FormsModule, TranslatePipe, ProductCardComponent, IconComponent, SkeletonComponent],
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class SearchComponent implements OnDestroy {
  readonly minSearchLength = 3;
  searchQuery = '';
  items = signal<Item[]>([]);
  loading = signal(false);
  error = signal<string | null>(null);
  hasMore = signal(true);
  totalResults = signal<number>(0);
  
  private skip = 0;
  private readonly count = ITEMS_PER_PAGE;
  private isLoadingMore = false;
  private searchSubject = new Subject<string>();
  private searchSubscription: Subscription;
  private i18n = inject(TranslateService);
  private readonly productFacade = inject(ProductFacade);

  constructor(
    private cartService: CartService,
    private prefetchService: PrefetchService
  ) {
    this.searchSubscription = this.searchSubject
      .pipe(
        debounceTime(SEARCH_DEBOUNCE_MS),
        distinctUntilChanged()
      )
      .subscribe(query => {
        if (query.trim().length >= 3 || query.trim().length === 0) {
          this.performSearch(query);
        }
      });
  }

  ngOnDestroy(): void {
    this.searchSubscription.unsubscribe();
    this.searchSubject.complete();
    if (this.scrollTimeout) clearTimeout(this.scrollTimeout);
  }

  onSearchInput(query: string): void {
    this.searchQuery = query;
    this.error.set(null);

    if (this.isQueryTooShort()) {
      this.resetSearchState();
      return;
    }

    this.searchSubject.next(query);
  }

  performSearch(query: string): void {
    if (!query.trim()) {
      this.resetSearchState();
      return;
    }

    this.error.set(null);
    this.items.set([]);
    this.skip = 0;
    this.hasMore.set(true);
    this.totalResults.set(0);
    this.loadResults();
  }

  loadResults(): void {
    if (this.isLoadingMore || !this.hasMore() || !this.searchQuery.trim()) return;

    this.loading.set(true);
    this.isLoadingMore = true;

    this.productFacade.searchProducts({ search: this.searchQuery.trim(), count: this.count, skip: this.skip }).subscribe({
      next: (response) => {
        // Update total results (only on first load)
        if (this.skip === 0) {
          this.totalResults.set(response.total);
        }

        // Handle empty results
        if (!response.items || response.items.length === 0) {
          this.hasMore.set(false);
        } else {
          // Check if there are more items to load
          if (response.items.length < this.count || this.skip + response.items.length >= response.total) {
            this.hasMore.set(false);
          }
          this.items.update(current => [...current, ...response.items]);
          this.skip += response.items.length;
        }
        this.loading.set(false);
        this.isLoadingMore = false;
      },
      error: (err) => {
        this.error.set(this.i18n.t('home.errorTitle'));
        this.loading.set(false);
        this.isLoadingMore = false;
        console.error('Error searching items:', err);
      }
    });
  }

  private resetSearchState(): void {
    this.items.set([]);
    this.loading.set(false);
    this.hasMore.set(false);
    this.totalResults.set(0);
    this.skip = 0;
    this.isLoadingMore = false;
  }

  isQueryTooShort(): boolean {
    const length = this.searchQuery.trim().length;
    return length > 0 && length < this.minSearchLength;
  }

  private scrollTimeout?: ReturnType<typeof setTimeout>;

  @HostListener('window:scroll')
  onScroll(): void {
    if (this.scrollTimeout) clearTimeout(this.scrollTimeout);
    
    this.scrollTimeout = setTimeout(() => {
      const scrollPosition = window.innerHeight + window.scrollY;
      const bottomPosition = document.documentElement.scrollHeight - SCROLL_THRESHOLD_PX;

      if (scrollPosition >= bottomPosition && !this.loading() && this.hasMore()) {
        this.loadResults();
      }
    }, SCROLL_DEBOUNCE_MS);
  }

  addToCart(itemID: number, event: Event): void {
    event.preventDefault();
    event.stopPropagation();
    this.cartService.addItem(itemID);
  }

  onItemHover(itemID: number): void {
    this.prefetchService.prefetchItem(itemID);
  }

  readonly skeletonSlots = Array.from({ length: 8 });
  readonly getDiscountedPrice = getDiscountedPrice;
  readonly getMainImage = getMainImage;
  readonly trackByItemId = trackByItemId;
  readonly getBadgeClass = getBadgeClass;

  private langService = inject(LanguageService);
  itemName(item: Item): string { return getTranslatedField(item, 'name', this.langService.currentLanguage()); }
  itemDesc(item: Item): string { return getTranslatedField(item, 'simpleDescription', this.langService.currentLanguage()); }
}
