import { describe, it, expect, beforeEach, vi } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
import { useUi } from '@/stores/useUi'
import { useEmpleadosStore } from '@/stores/useEmpleados'
import EmpleadosIndex from '../EmpleadosIndex.vue'
import TablaEmpleados from '@/components/empleados/tablaEmpleados.vue'
import CardEmpleado from '@/components/empleados/cardEmpleado.vue'

// Mock the child components to simplify testing and focus on EmpleadosIndex logic
vi.mock('@/components/empleados/tablaEmpleados.vue', () => ({
  default: {
    name: 'TablaEmpleados',
    props: ['employees'],
    template: '<div data-testid="tabla-empleados"></div>',
  },
}))

vi.mock('@/components/empleados/cardEmpleado.vue', () => ({
  default: {
    name: 'CardEmpleado',
    props: ['employee'],
    template: '<div data-testid="card-empleado"></div>',
  },
}))

// Mock the stores
// We need to define the mock functions before they are used by `vi.mock`
const mockSetDefaultViewEmpleados = vi.fn();
const mockFetchEmpleados = vi.fn();

vi.mock('@/stores/useUi', () => ({
  useUi: vi.fn(() => ({
    defaultViewEmpleados: 'table', // Default mock value
    // Add any other state or actions needed by the component from useUi
    setDefaultViewEmpleados: mockSetDefaultViewEmpleados,
  })),
}))

vi.mock('@/stores/useEmpleados', () => ({
  useEmpleadosStore: vi.fn(() => ({
    empleados: [],
    fetchEmpleados: mockFetchEmpleados,
    // Add other state or actions if EmpleadosIndex uses them
  })),
}))

describe('EmpleadosIndex.vue', () => {
  let uiStoreMock
  let empleadosStoreMock

  beforeEach(() => {
    setActivePinia(createPinia())

    // Reset mocks and provide fresh instances for each test
    mockFetchEmpleados.mockClear().mockResolvedValue([]); // Default to resolve successfully
    mockSetDefaultViewEmpleados.mockClear();

    // Get fresh instances of the mocked stores for manipulation in tests
    // The actual `useUi` and `useEmpleadosStore` will be the vi.fn defined above
    // Re-calling them ensures we can configure their return values per test suite if needed
    // or rely on the default mock implementation.
    uiStoreMock = useUi()
    empleadosStoreMock = useEmpleadosStore()
  })

  const mountComponent = () => {
    return mount(EmpleadosIndex, {
      global: {
        stubs: {
          // While components are mocked via vi.mock, explicit stubs can be used for further control if needed
          // For instance, if you didn't want to mock the entire module.
          // 'TablaEmpleados': true,
          // 'CardEmpleado': true,
        }
      },
    })
  }

  it('fetches employees on mount', () => {
    mountComponent()
    expect(mockFetchEmpleados).toHaveBeenCalledTimes(1)
  })

  describe('View Rendering based on useUi store', () => {
    it('renders TablaEmpleados when defaultViewEmpleados is "table"', async () => {
      uiStoreMock.defaultViewEmpleados = 'table' // Set store state for this test
      empleadosStoreMock.empleados = [{ id: 1, nombre: 'Test Employee' }] // Provide some data

      const wrapper = mountComponent()
      await wrapper.vm.$nextTick() // Wait for any reactivity updates

      expect(wrapper.findComponent({ name: 'TablaEmpleados' }).exists()).toBe(true)
      expect(wrapper.findComponent({ name: 'TablaEmpleados' }).props('employees')).toEqual(empleadosStoreMock.empleados)
      expect(wrapper.findComponent({ name: 'CardEmpleado' }).exists()).toBe(false)
    })

    it('renders CardEmpleado when defaultViewEmpleados is "card"', async () => {
      uiStoreMock.defaultViewEmpleados = 'card' // Set store state for this test
      empleadosStoreMock.empleados = [{ id: 1, nombre: 'Test Employee' }, { id: 2, nombre: 'Another Employee' }]

      const wrapper = mountComponent()
      await wrapper.vm.$nextTick()

      const cardWrappers = wrapper.findAllComponents({ name: 'CardEmpleado' })
      expect(cardWrappers.length).toBe(empleadosStoreMock.empleados.length)
      expect(cardWrappers[0].props('employee')).toEqual(empleadosStoreMock.empleados[0])
      expect(wrapper.findComponent({ name: 'TablaEmpleados' }).exists()).toBe(false)
    })

    it('renders no data message for table view when no employees exist', async () => {
        uiStoreMock.defaultViewEmpleados = 'table';
        empleadosStoreMock.empleados = []; // No data

        const wrapper = mountComponent();
        await wrapper.vm.$nextTick(); // allow loading state to pass
        await wrapper.vm.$nextTick(); // allow conditional rendering based on data

        expect(wrapper.findComponent({ name: 'TablaEmpleados' }).exists()).toBe(true); // Table component itself still renders
        expect(wrapper.text()).toContain('No hay empleados para mostrar en la vista de tabla.');
    });

    it('renders no data message for card view when no employees exist', async () => {
        uiStoreMock.defaultViewEmpleados = 'card';
        empleadosStoreMock.empleados = []; // No data

        const wrapper = mountComponent();
        await wrapper.vm.$nextTick();
        await wrapper.vm.$nextTick();

        expect(wrapper.findAllComponents({ name: 'CardEmpleado' }).length).toBe(0);
        expect(wrapper.text()).toContain('No hay empleados para mostrar en la vista de tarjetas.');
    });
  })

  describe('Local View Toggle Buttons', () => {
    it('renders toggle buttons and reflects initial view from store (table)', async () => {
      uiStoreMock.defaultViewEmpleados = 'table';
      const wrapper = mountComponent();
      // Wait for loading and reactivity
      await wrapper.vm.$nextTick();
      await wrapper.vm.$nextTick();


      const tableViewButton = wrapper.find('button[aria-label="Table View"]');
      const cardViewButton = wrapper.find('button[aria-label="Card View"]');

      expect(tableViewButton.exists()).toBe(true);
      expect(cardViewButton.exists()).toBe(true);
      expect(tableViewButton.classes()).toContain('bg-[var(--accent-color-empleados)]');
      expect(cardViewButton.classes()).toContain('bg-gray-200');
    });

    it('renders toggle buttons and reflects initial view from store (card)', async () => {
      uiStoreMock.defaultViewEmpleados = 'card';
      const wrapper = mountComponent();
      await wrapper.vm.$nextTick();
      await wrapper.vm.$nextTick();

      const tableViewButton = wrapper.find('button[aria-label="Table View"]');
      const cardViewButton = wrapper.find('button[aria-label="Card View"]');

      expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-empleados)]');
      expect(tableViewButton.classes()).toContain('bg-gray-200');
    });

    it('switches to card view on button click and updates button styles, does not call global store action', async () => {
      uiStoreMock.defaultViewEmpleados = 'table';
      empleadosStoreMock.empleados = [{ id: 1, nombre: 'Test' }];
      const wrapper = mountComponent();
      await wrapper.vm.$nextTick();
      await wrapper.vm.$nextTick();

      const cardViewButton = wrapper.find('button[aria-label="Card View"]');
      const tableViewButton = wrapper.find('button[aria-label="Table View"]');

      await cardViewButton.trigger('click');
      await wrapper.vm.$nextTick();

      expect(wrapper.findComponent({ name: 'CardEmpleado' }).exists()).toBe(true);
      expect(wrapper.findComponent({ name: 'TablaEmpleados' }).exists()).toBe(false);
      expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-empleados)]');
      expect(tableViewButton.classes()).toContain('bg-gray-200');
      expect(mockSetDefaultViewEmpleados).not.toHaveBeenCalled();
    });

    it('switches back to table view on button click and updates button styles, does not call global store action', async () => {
      uiStoreMock.defaultViewEmpleados = 'card'; // Start with card view
      empleadosStoreMock.empleados = [{ id: 1, nombre: 'Test' }];
      const wrapper = mountComponent();
      await wrapper.vm.$nextTick();
      await wrapper.vm.$nextTick();

      const cardViewButton = wrapper.find('button[aria-label="Card View"]');
      const tableViewButton = wrapper.find('button[aria-label="Table View"]');
      expect(cardViewButton.classes()).toContain('bg-[var(--accent-color-empleados)]');

      await tableViewButton.trigger('click');
      await wrapper.vm.$nextTick();

      expect(wrapper.findComponent({ name: 'TablaEmpleados' }).exists()).toBe(true);
      expect(wrapper.findComponent({ name: 'CardEmpleado' }).exists()).toBe(false);
      expect(tableViewButton.classes()).toContain('bg-[var(--accent-color-empleados)]');
      expect(cardViewButton.classes()).toContain('bg-gray-200');
      expect(mockSetDefaultViewEmpleados).not.toHaveBeenCalled();
    });
  });
})
