import {
  ChangeDetectionStrategy,
  Component,
  OnDestroy,
  OnInit,
  computed,
  inject,
  signal,
} from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs';

import { ApiPaginatedResponse } from '../../../../core/services/api-paginated-response.interface';
import { CatalogService } from '../../../../core/services/catalog/catalog.service';
import { Product } from '../../../../core/services/catalog/catalog.interface';
import { ProductCardComponent } from '../../../../shared/components/product-card/product-card.component';
import { PaginatorComponent } from '../../../../shared/components/paginator/paginator.component';
import { StoreSectionComponent } from '../../../../shared/components/store-section/store-section.component';
import {
  STORE_HOME_PRODUCTS_ERROR_MESSAGE,
  StoreHomeProductsResolvedData,
} from './store-home-page.resolver';

interface StoreHomeProductCardViewModel {
  id: number;
  title: string;
  originalPrice: number;
  discount: null;
  transferPrice: null;
  imageUrl: string | null;
}

@Component({
  selector: 'app-store-home-page',
  imports: [StoreSectionComponent, ProductCardComponent, PaginatorComponent],
  templateUrl: './store-home-page.component.html',
  styleUrl: './store-home-page.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StoreHomePageComponent implements OnInit, OnDestroy {
  private readonly catalogService = inject(CatalogService);
  private readonly route = inject(ActivatedRoute);
  private readonly router = inject(Router);

  private activeRequestId = 0;
  private productsRequestSubscription: Subscription | null = null;
  protected readonly priorityImageCount = 4;

  protected readonly currentPage = signal(1);
  protected readonly products = signal<Product[]>([]);
  protected readonly totalPages = signal(0);
  protected readonly loading = signal(false);
  protected readonly error = signal<string | null>(null);

  protected readonly productCards = computed<StoreHomeProductCardViewModel[]>(() =>
    this.products().map((product) => ({
      id: product.id,
      title: product.nombre,
      originalPrice: this.parseProductPrice(product.precio),
      discount: null,
      transferPrice: null,
      imageUrl: product.images?.[0] ?? null,
    })),
  );

  ngOnInit(): void {
    const resolvedData = this.route.snapshot.data['productsData'] as
      | StoreHomeProductsResolvedData
      | undefined;

    if (resolvedData) {
      this.applyResolvedData(resolvedData);

      return;
    }

    this.loadProducts(1);
  }

  ngOnDestroy(): void {
    this.productsRequestSubscription?.unsubscribe();
  }

  protected onPageChange(page: number): void {
    if (page === this.currentPage() || page < 1) {
      return;
    }

    this.loadProducts(page);
  }

  protected onBuyProduct(productId: number): void {
    this.router.navigate(['/producto', productId]);
  }

  private loadProducts(page: number): void {
    this.activeRequestId += 1;
    const requestId = this.activeRequestId;

    this.productsRequestSubscription?.unsubscribe();
    this.loading.set(true);
    this.error.set(null);

    this.productsRequestSubscription = this.catalogService.getProductos({ page }).subscribe({
      next: (response) => {
        if (requestId !== this.activeRequestId) {
          return;
        }

        this.applyProductsResponse(response);
      },
      error: () => {
        if (requestId !== this.activeRequestId) {
          return;
        }

        this.products.set([]);
        this.totalPages.set(0);
        this.loading.set(false);
        this.error.set(STORE_HOME_PRODUCTS_ERROR_MESSAGE);
      },
      complete: () => {
        if (requestId !== this.activeRequestId) {
          return;
        }

        this.loading.set(false);
      },
    });
  }

  private applyResolvedData(resolvedData: StoreHomeProductsResolvedData): void {
    if (resolvedData.error) {
      this.products.set([]);
      this.totalPages.set(0);
      this.loading.set(false);
      this.error.set(resolvedData.error);

      return;
    }

    if (resolvedData.response) {
      this.applyProductsResponse(resolvedData.response);
      this.loading.set(false);
      this.error.set(null);
    }
  }

  private applyProductsResponse(response: ApiPaginatedResponse<Product[]>): void {
    this.products.set(response.data ?? []);
    this.currentPage.set(response.meta.current_page);
    this.totalPages.set(response.meta.last_page);
  }

  private parseProductPrice(price: string): number {
    const parsedPrice = Number(price);

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