import {
  afterNextRender,
  ChangeDetectionStrategy,
  Component,
  computed,
  DestroyRef,
  inject,
  input,
  output,
  signal,
} from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';

import {
  CatalogFeaturedItem,
  CatalogFeaturedItems,
  CatalogFeaturedItemVariant,
  CatalogGroupLayout,
  CatalogProductLayout,
} from '../../../core/services/catalog/catalog.interface';
import { CarouselComponent } from '../carousel/carousel.component';
import { PaginatorComponent } from '../paginator/paginator.component';
import { ProductColumnWithImageComponent } from '../product-column-with-image/product-column-with-image.component';
import { ProductRowCardComponent } from '../product-row-card/product-row-card.component';
import { ProductVerticalWithCartCardComponent } from '../product-vertical-with-cart-card/product-vertical-with-cart-card.component';
import { ProductTicketSelectorComponent } from '../product-ticket-selector/product-ticket-selector.component';

export type ProductListLayout = CatalogProductLayout;
export type ProductListVariant = CatalogFeaturedItemVariant;
export type ProductListItem = CatalogFeaturedItem;

export interface ProductListCartEvent {
  product: ProductListItem;
  quantity: number;
  variant?: number | null;
}

export interface ProductListBuyEvent {
  product: ProductListItem;
  quantity: number;
  variant?: number | null;
  variantIds?: number[];
  directPurchase: boolean;
  reservedInCart?: boolean;
}

@Component({
  selector: 'app-product-list',
  imports: [
    CarouselComponent,
    NgTemplateOutlet,
    ProductColumnWithImageComponent,
    PaginatorComponent,
    ProductRowCardComponent,
    ProductVerticalWithCartCardComponent,
    ProductTicketSelectorComponent,
  ],
  templateUrl: './product-list.component.html',
  styleUrl: './product-list.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductListComponent {
  private readonly destroyRef = inject(DestroyRef);
  private readonly mobile = signal(false);

  readonly layout = input.required<ProductListLayout>();
  readonly groupLayout = input.required<CatalogGroupLayout>();
  readonly items = input.required<CatalogFeaturedItems>();
  readonly loading = input(false);
  readonly loadImages = input(true);
  readonly unavailableVariantIds = input<ReadonlySet<number>>(new Set<number>());
  readonly savingProductIds = input<ReadonlySet<number>>(new Set<number>());

  readonly buy = output<ProductListBuyEvent>();
  readonly addToCart = output<ProductListCartEvent>();
  readonly pageChange = output<number>();

  protected readonly effectiveLayout = computed<ProductListLayout>(() =>
    this.mobile() && this.layout() === 'row' ? 'column_with_cart' : this.layout(),
  );
  protected readonly itemData = computed(() => {
    const items = this.items();

    return Array.isArray(items) ? items : items.data;
  });
  protected readonly pagination = computed(() => {
    const items = this.items();

    return Array.isArray(items) ? null : items;
  });
  protected readonly trackProduct = (_index: number, item: ProductListItem): number => item.id;

  constructor() {
    afterNextRender(() => {
      const mobileQuery = window.matchMedia('(max-width: 767.98px)');
      const updateMobile = (event: MediaQueryList | MediaQueryListEvent): void =>
        this.mobile.set(event.matches);

      updateMobile(mobileQuery);
      mobileQuery.addEventListener('change', updateMobile);
      this.destroyRef.onDestroy(() => mobileQuery.removeEventListener('change', updateMobile));
    });
  }

  protected price(item: ProductListItem): number {
    const price = Number(item.precio);

    return Number.isFinite(price) ? price : 0;
  }

  protected emitRowCart(
    product: ProductListItem,
    event: { quantity: number; variant: unknown },
  ): void {
    this.addToCart.emit({
      product,
      quantity: event.quantity,
      variant: typeof event.variant === 'number' ? event.variant : null,
    });
  }

  protected emitColumnCart(
    product: ProductListItem,
    event: { quantity: number; variant: number | null },
  ): void {
    this.addToCart.emit({ product, quantity: event.quantity, variant: event.variant });
  }

  protected emitRowBuy(
    product: ProductListItem,
    event: { quantity: number; variant: unknown },
  ): void {
    this.buy.emit({
      product,
      quantity: event.quantity,
      variant: typeof event.variant === 'number' ? event.variant : null,
      directPurchase: true,
    });
  }

  protected emitColumnBuy(
    product: ProductListItem,
    event: { quantity: number; variant: number | null },
  ): void {
    this.buy.emit({
      product,
      quantity: event.quantity,
      variant: event.variant,
      directPurchase: true,
    });
  }

  protected emitProductDetailBuy(product: ProductListItem): void {
    this.buy.emit({ product, quantity: 1, variant: null, directPurchase: false });
  }

  protected emitTicketBuy(product: ProductListItem, variantIds: number[]): void {
    this.buy.emit({
      product,
      quantity: variantIds.length,
      variant: variantIds[0] ?? null,
      variantIds,
      directPurchase: true,
      reservedInCart: true,
    });
  }
}
