import { TestBed } from '@angular/core/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { PaginatorComponent } from './paginator.component';

describe('PaginatorComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [PaginatorComponent]
    }).compileComponents();
  });

  function setup(page: number, totalPages: number, disabled = false) {
    const fixture = TestBed.createComponent(PaginatorComponent);
    fixture.componentRef.setInput('page', page);
    fixture.componentRef.setInput('totalPages', totalPages);
    fixture.componentRef.setInput('disabled', disabled);
    fixture.detectChanges();

    return {
      fixture,
      element: fixture.nativeElement as HTMLElement
    };
  }

  it('renders the current page status', () => {
    const { element } = setup(1, 8);

    expect(element.querySelector('[data-testid="paginator-status"]')?.textContent?.trim()).toBe('1/8');
  });

  it('emits the next page when clicking next', () => {
    const { fixture, element } = setup(1, 8);
    const pageChangeSpy = vi.fn();

    fixture.componentInstance.pageChange.subscribe(pageChangeSpy);
    (element.querySelector('[data-testid="paginator-next"]') as HTMLButtonElement).click();

    expect(pageChangeSpy).toHaveBeenCalledWith(2);
  });

  it('emits the last page when clicking last', () => {
    const { fixture, element } = setup(1, 8);
    const pageChangeSpy = vi.fn();

    fixture.componentInstance.pageChange.subscribe(pageChangeSpy);
    (element.querySelector('[data-testid="paginator-last"]') as HTMLButtonElement).click();

    expect(pageChangeSpy).toHaveBeenCalledWith(8);
  });

  it('emits the first page when clicking first from a middle page', () => {
    const { fixture, element } = setup(4, 8);
    const pageChangeSpy = vi.fn();

    fixture.componentInstance.pageChange.subscribe(pageChangeSpy);
    (element.querySelector('[data-testid="paginator-first"]') as HTMLButtonElement).click();

    expect(pageChangeSpy).toHaveBeenCalledWith(1);
  });

  it('does not emit when trying to go before the first page', () => {
    const { fixture, element } = setup(1, 8);
    const pageChangeSpy = vi.fn();

    fixture.componentInstance.pageChange.subscribe(pageChangeSpy);
    (element.querySelector('[data-testid="paginator-previous"]') as HTMLButtonElement).click();

    expect(pageChangeSpy).not.toHaveBeenCalled();
  });

  it('does not emit when trying to go after the last page', () => {
    const { fixture, element } = setup(8, 8);
    const pageChangeSpy = vi.fn();

    fixture.componentInstance.pageChange.subscribe(pageChangeSpy);
    (element.querySelector('[data-testid="paginator-next"]') as HTMLButtonElement).click();

    expect(pageChangeSpy).not.toHaveBeenCalled();
  });

  it('disables all buttons when disabled is true', () => {
    const { element } = setup(2, 8, true);

    expect(Array.from(element.querySelectorAll('button')).every((button) => button.disabled)).toBe(true);
  });

  it('disables all buttons when there is only one page', () => {
    const { element } = setup(1, 1);

    expect(Array.from(element.querySelectorAll('button')).every((button) => button.disabled)).toBe(true);
  });
});
