import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ActivatedRoute, convertToParamMap, provideRouter } from '@angular/router';
import { of } from 'rxjs';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { CartService } from '../../../../core/services/cart/cart.service';
import { CatalogService } from '../../../../core/services/catalog/catalog.service';
import { CatalogAvailabilityService } from '../../../../core/services/catalog/catalog-availability.service';
import { Tenant } from '../../../../core/services/tenant.interface';
import { TenantService } from '../../../../core/services/tenant.service';
import { ToastService } from '../../../../core/services/toast.service';
import { ProductListComponent } from '../../../../shared/components/product-list/product-list.component';
import { CategoryItemsPageComponent } from './category-items-page.component';

describe('CategoryItemsPageComponent', () => {
  const getCategoryItems = vi.fn();
  const tenant = signal({ codigo: 'shop' } as Tenant);

  beforeEach(async () => {
    getCategoryItems.mockReset();
    getCategoryItems.mockReturnValue(
      of({
        category: {
          id: 7,
          nombre: 'Remeras',
          categoria_id: null,
        },
        layout: 'row',
        group_layout: 'simple_vertical',
        data: [
          {
            id: 1,
            nombre: 'Remera clásica',
            descripcion: 'Algodón',
            precio: '100.00',
            variants: [],
          },
        ],
        links: {
          first: '/categories/7?page=1',
          last: '/categories/7?page=2',
          prev: null,
          next: '/categories/7?page=2',
        },
        meta: {
          current_page: 1,
          from: 1,
          last_page: 2,
          links: [],
          path: '/categories/7',
          per_page: 12,
          to: 1,
          total: 13,
        },
      }),
    );

    await TestBed.configureTestingModule({
      imports: [CategoryItemsPageComponent],
      providers: [
        provideRouter([]),
        {
          provide: ActivatedRoute,
          useValue: {
            paramMap: of(convertToParamMap({ id: '7' })),
            queryParamMap: of(convertToParamMap({ page: '1' })),
          },
        },
        {
          provide: CatalogService,
          useValue: {
            getCategoryItems,
          },
        },
        {
          provide: TenantService,
          useValue: { tenant: tenant.asReadonly() },
        },
        {
          provide: CartService,
          useValue: { addItem: vi.fn() },
        },
        {
          provide: ToastService,
          useValue: {
            success: vi.fn(),
            danger: vi.fn(),
          },
        },
      ],
    }).compileComponents();
  });

  it('loads the category and renders its products with the configured product layout', () => {
    const fixture = TestBed.createComponent(CategoryItemsPageComponent);
    fixture.detectChanges();

    expect(getCategoryItems).toHaveBeenCalledWith(7, { page: 1 });
    expect((fixture.nativeElement as HTMLElement).textContent).toContain('Remeras');

    const productList = fixture.debugElement.query(By.directive(ProductListComponent))
      .componentInstance as ProductListComponent;

    expect(productList.layout()).toBe('row');
    expect(productList.groupLayout()).toBe('paginated');
    expect(Array.isArray(productList.items())).toBe(false);
  });

  it('reloads the current category page when catalog availability changes', () => {
    const fixture = TestBed.createComponent(CategoryItemsPageComponent);
    fixture.detectChanges();

    TestBed.inject(CatalogAvailabilityService).notifyAvailabilityChanged();

    expect(getCategoryItems).toHaveBeenCalledTimes(2);
    expect(getCategoryItems).toHaveBeenLastCalledWith(7, { page: 1 });
  });

  it('does not request the API when the category id is invalid', () => {
    TestBed.overrideProvider(ActivatedRoute, {
      useValue: {
        paramMap: of(convertToParamMap({ id: 'invalid' })),
        queryParamMap: of(convertToParamMap({ page: '1' })),
      },
    });

    const fixture = TestBed.createComponent(CategoryItemsPageComponent);
    fixture.detectChanges();

    expect(getCategoryItems).not.toHaveBeenCalled();
    expect((fixture.nativeElement as HTMLElement).textContent).toContain(
      'La categoría solicitada no es válida.',
    );
  });
});
