import { mount, shallowMount } from '@vue/test-utils';
import { describe, test, expect, vi, beforeEach } from 'vitest';
import BmsPagination from './BmsPagination.vue';

// Mock field plugin
const mockField = {
  install: vi.fn(),
};

// Mock IntersectionObserver
const intersectionObserverMock = () => ({
  observe: () => null,
});

// Mock child components
vi.mock('@/components/button/BmsIconButton.vue', () => ({
  default: {
    name: 'BmsIconButton',
    template: '<button><slot /></button>',
    props: ['color', 'disabled'],
  },
}));

vi.mock('@/index', () => ({
  BmsSelect: {
    name: 'BmsSelect',
    template:
      '<select><option v-for="option in options" :key="option.value" :value="option.value">{{ option.label }}</option></select>',
    props: ['modelValue', 'options'],
    emits: ['update:modelValue'],
  },
}));

vi.mock('lucide-vue-next', () => ({
  ChevronFirst: { name: 'ChevronFirst', template: '<span>First</span>' },
  ChevronLast: { name: 'ChevronLast', template: '<span>Last</span>' },
  ChevronLeft: { name: 'ChevronLeft', template: '<span>Left</span>' },
  ChevronRight: { name: 'ChevronRight', template: '<span>Right</span>' },
}));

const shallowFactory = (props: any) => {
  return shallowMount(BmsPagination, {
    global: {
      plugins: [mockField],
    },
    props: { ...props },
  });
};

const factory = (props: any) => {
  return mount(BmsPagination, {
    global: {
      plugins: [mockField],
      stubs: {
        BmsSelect: {
          name: 'BmsSelect',
          template:
            '<select v-model="modelValue"><option v-for="option in options" :key="option.value" :value="option.value">{{ option.label }}</option></select>',
          props: ['modelValue', 'options'],
          emits: ['update:modelValue'],
        },
        BmsIconButton: {
          name: 'BmsIconButton',
          template:
            '<button @click="$emit(\'click\')" :disabled="disabled"><slot /></button>',
          props: ['color', 'disabled'],
          emits: ['click'],
        },
      },
    },
    props: { ...props },
  });
};

describe('BmsPagination', () => {
  beforeEach(() => {
    vi.resetAllMocks();
    window.IntersectionObserver = vi
      .fn()
      .mockImplementation(intersectionObserverMock);
  });

  test('should display correctly', () => {
    const wrapper = shallowFactory({
      sizes: [25, 50],
      total: 120,
      currentPage: 0,
      currentSize: 25,
      pages: Math.ceil(120 / 25),
    });

    expect(wrapper.text()).toContain('1 à 25');
  });

  test('should emit correct navigation events', async () => {
    const wrapper = factory({
      sizes: [25, 50],
      total: 120,
      currentPage: 2,
      currentSize: 25,
      pages: Math.ceil(120 / 25),
    });

    const buttons = wrapper.findAllComponents({ name: 'BmsIconButton' });
    const goToBeginning = buttons[0];
    const goBack = buttons[1];
    const goForward = buttons[2];
    const goToEnding = buttons[3];

    await goToBeginning.trigger('click');
    expect(wrapper.emitted('go')?.[0]).toEqual([0]);

    await goBack.trigger('click');
    expect(wrapper.emitted('prev')?.[0]).toEqual([]);

    await goForward.trigger('click');
    expect(wrapper.emitted('next')?.[0]).toEqual([]);

    await goToEnding.trigger('click');
    expect(wrapper.emitted('go')?.[1]).toEqual([4]);
  });

  test('should handle size change', async () => {
    const wrapper = factory({
      sizes: [25, 50],
      total: 120,
      currentPage: 0,
      currentSize: 25,
      pages: Math.ceil(120 / 25),
    });

    const select = wrapper.findComponent({ name: 'BmsSelect' });
    await select.vm.$emit('update:modelValue', 50);

    expect(wrapper.emitted('update:currentSize')?.[0]).toEqual([50]);
  });

  test('should disable navigation buttons correctly', () => {
    const wrapper = factory({
      sizes: [25, 50],
      total: 120,
      currentPage: 0,
      currentSize: 25,
      pages: Math.ceil(120 / 25),
    });

    const buttons = wrapper.findAllComponents({ name: 'BmsIconButton' });

    // First and previous buttons should be disabled on first page
    expect(buttons[0].props('disabled')).toBe(true);
    expect(buttons[1].props('disabled')).toBe(true);

    // Next and last buttons should be enabled
    expect(buttons[2].props('disabled')).toBe(false);
    expect(buttons[3].props('disabled')).toBe(false);
  });

  test('should calculate last item number correctly', () => {
    const wrapper = shallowFactory({
      sizes: [25, 50],
      total: 120,
      currentPage: 1,
      currentSize: 25,
      pages: Math.ceil(120 / 25),
    });

    expect(wrapper.text()).toContain('26 à 50');
  });
});
