import { describe, expect, it } from 'vitest';
import { PaginationItemType, getRange, transform } from '../utils';

describe(getRange, () => {
  it('returns empty array for zero total pages', () => {
    expect(getRange(1, 0, 1, false)).toEqual([]);
  });

  it('returns single page when totalPages is 1', () => {
    expect(getRange(1, 1, 1, false)).toEqual([
      { type: 'page', value: 1 },
    ]);
  });

  it('returns all pages when totalPages fits within visible window', () => {
    expect(getRange(1, 5, 1, false)).toEqual([
      { type: 'page', value: 1 },
      { type: 'page', value: 2 },
      { type: 'page', value: 3 },
      { type: 'page', value: 4 },
      { type: 'page', value: 5 },
    ]);
  });

  it('returns all pages when totalPages equals the threshold', () => {
    // siblingCount=1: totalWithEllipsis = 1*2+3+2 = 7
    expect(getRange(1, 7, 1, false)).toEqual([
      { type: 'page', value: 1 },
      { type: 'page', value: 2 },
      { type: 'page', value: 3 },
      { type: 'page', value: 4 },
      { type: 'page', value: 5 },
      { type: 'page', value: 6 },
      { type: 'page', value: 7 },
    ]);
  });

  it('shows right ellipsis when current page is near the start', () => {
    const items = getRange(1, 10, 1, false);

    expect(items[0]).toEqual({ type: 'page', value: 1 });
    expect(items).toContainEqual({ type: 'ellipsis' });
    expect(items[items.length - 1]).toEqual({ type: 'page', value: 10 });
  });

  it('shows left ellipsis when current page is near the end', () => {
    const items = getRange(10, 10, 1, false);

    expect(items[0]).toEqual({ type: 'page', value: 1 });
    expect(items).toContainEqual({ type: 'ellipsis' });
    expect(items[items.length - 1]).toEqual({ type: 'page', value: 10 });
  });

  it('shows both ellipses when current page is in the middle', () => {
    const items = getRange(5, 10, 1, false);
    const ellipses = items.filter(i => i.type === 'ellipsis');

    expect(ellipses).toHaveLength(2);
    expect(items[0]).toEqual({ type: 'page', value: 1 });
    expect(items[items.length - 1]).toEqual({ type: 'page', value: 10 });
    // Should include current page and siblings
    expect(items).toContainEqual({ type: 'page', value: 4 });
    expect(items).toContainEqual({ type: 'page', value: 5 });
    expect(items).toContainEqual({ type: 'page', value: 6 });
  });

  it('respects siblingCount when generating range', () => {
    const items = getRange(10, 20, 2, false);
    const ellipses = items.filter(i => i.type === 'ellipsis');

    expect(ellipses).toHaveLength(2);
    // Current page ± 2 siblings
    expect(items).toContainEqual({ type: 'page', value: 8 });
    expect(items).toContainEqual({ type: 'page', value: 9 });
    expect(items).toContainEqual({ type: 'page', value: 10 });
    expect(items).toContainEqual({ type: 'page', value: 11 });
    expect(items).toContainEqual({ type: 'page', value: 12 });
  });

  it('shows edge pages when showEdges is true', () => {
    const items = getRange(5, 10, 1, true);

    // First and last pages should always be present
    expect(items[0]).toEqual({ type: 'page', value: 1 });
    expect(items[items.length - 1]).toEqual({ type: 'page', value: 10 });

    // Should have ellipses
    const ellipses = items.filter(i => i.type === 'ellipsis');
    expect(ellipses.length).toBeGreaterThanOrEqual(1);
  });

  it('does not duplicate first/last page with showEdges at boundaries', () => {
    const items = getRange(1, 10, 1, true);
    const firstPages = items.filter(i => i.type === 'page' && i.value === 1);

    expect(firstPages).toHaveLength(1);
  });

  it('handles large siblingCount gracefully', () => {
    const items = getRange(1, 3, 10, false);

    expect(items).toEqual([
      { type: 'page', value: 1 },
      { type: 'page', value: 2 },
      { type: 'page', value: 3 },
    ]);
  });

  it('always includes current page in the result', () => {
    for (let page = 1; page <= 20; page++) {
      const items = getRange(page, 20, 1, false);
      const pages = items.filter(i => i.type === 'page').map(i => (i as { type: 'page'; value: number }).value);

      expect(pages).toContain(page);
    }
  });
});

describe(transform, () => {
  it('converts numbers to page items', () => {
    expect(transform([1, 2, 3])).toEqual([
      { type: PaginationItemType.Page, value: 1 },
      { type: PaginationItemType.Page, value: 2 },
      { type: PaginationItemType.Page, value: 3 },
    ]);
  });

  it('converts strings to ellipsis items', () => {
    expect(transform(['...'])).toEqual([
      { type: PaginationItemType.Ellipsis },
    ]);
  });

  it('converts mixed array', () => {
    expect(transform([1, '...', 5])).toEqual([
      { type: PaginationItemType.Page, value: 1 },
      { type: PaginationItemType.Ellipsis },
      { type: PaginationItemType.Page, value: 5 },
    ]);
  });

  it('returns empty array for empty input', () => {
    expect(transform([])).toEqual([]);
  });
});
