import { mount } from '@vue/test-utils';
import VTable from './VTable.vue';
import { describe, it, expect, vi } from 'vitest';

const testHeaders = [
  { key: 'id', label: 'ID' },
  { key: 'name', label: 'Name', headerClass: 'name-header', cellClass: 'name-cell' },
  { key: 'email', label: 'Email Address' },
];

const testItems = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob', email: 'bob@example.com' },
];

describe('VTable.vue', () => {
  it('renders headers correctly', () => {
    const wrapper = mount(VTable, { props: { headers: testHeaders, items: [] } });
    const thElements = wrapper.findAll('thead th');
    expect(thElements.length).toBe(testHeaders.length);
    testHeaders.forEach((header, index) => {
      expect(thElements[index].text()).toBe(header.label);
    });
  });

  it('renders item data correctly', () => {
    const wrapper = mount(VTable, { props: { headers: testHeaders, items: testItems } });
    const rows = wrapper.findAll('tbody tr');
    expect(rows.length).toBe(testItems.length);

    rows.forEach((row, rowIndex) => {
      const cells = row.findAll('td');
      expect(cells.length).toBe(testHeaders.length);
      testHeaders.forEach((header, colIndex) => {
        expect(cells[colIndex].text()).toBe(String(testItems[rowIndex][header.key]));
      });
    });
  });

  it('applies stickyHeader class to thead', () => {
    const wrapper = mount(VTable, { props: { headers: [], items: [], stickyHeader: true } });
    expect(wrapper.find('thead').classes()).toContain('sticky-header');
  });

  it('applies stickyFooter class to tfoot', () => {
    const wrapper = mount(VTable, {
      props: { headers: [], items: [], stickyFooter: true },
      slots: { footer: '<tr><td>Footer</td></tr>' },
    });
    expect(wrapper.find('tfoot').classes()).toContain('sticky-footer');
  });

  it('does not render tfoot if no footer slot', () => {
    const wrapper = mount(VTable, { props: { headers: [], items: [] } });
    expect(wrapper.find('tfoot').exists()).toBe(false);
  });

  it('renders custom header slot content', () => {
    const wrapper = mount(VTable, {
      props: { headers: [{ key: 'name', label: 'Name' }], items: [] },
      slots: { 'header.name': '<div class="custom-header-slot">Custom Name Header</div>' },
    });
    const headerCell = wrapper.find('thead th');
    expect(headerCell.find('.custom-header-slot').exists()).toBe(true);
    expect(headerCell.text()).toBe('Custom Name Header');
  });

  it('renders custom item cell slot content', () => {
    const wrapper = mount(VTable, {
      props: { headers: [{ key: 'name', label: 'Name' }], items: [{ name: 'Alice' }] },
      slots: { 'item.name': '<template #item.name="{ value }"><strong>{{ value.toUpperCase() }}</strong></template>' },
    });
    const cell = wrapper.find('tbody td');
    expect(cell.find('strong').exists()).toBe(true);
    expect(cell.text()).toBe('ALICE');
  });

  it('renders custom full item row slot content', () => {
    const wrapper = mount(VTable, {
      props: { headers: testHeaders, items: [testItems[0]] },
      slots: {
        'item': '<template #item="{ item, rowIndex }"><tr class="custom-row"><td :colspan="3">Custom Row {{ rowIndex }}: {{ item.name }}</td></tr></template>'
      },
    });
    expect(wrapper.find('tbody tr.custom-row').exists()).toBe(true);
    expect(wrapper.find('tbody td').text()).toBe('Custom Row 0: Alice');
  });


  it('renders empty-state slot when items array is empty', () => {
    const emptyStateContent = '<div>No items available.</div>';
    const wrapper = mount(VTable, {
      props: { headers: testHeaders, items: [] },
      slots: { 'empty-state': emptyStateContent },
    });
    const emptyRow = wrapper.find('tbody tr');
    expect(emptyRow.exists()).toBe(true);
    const cell = emptyRow.find('td');
    expect(cell.exists()).toBe(true);
    expect(cell.attributes('colspan')).toBe(String(testHeaders.length));
    expect(cell.html()).toContain(emptyStateContent);
  });

  it('renders empty-state slot with colspan 1 if headers are also empty', () => {
    const wrapper = mount(VTable, {
      props: { headers: [], items: [] }, // No headers
      slots: { 'empty-state': '<span>Empty</span>' },
    });
    const cell = wrapper.find('tbody td');
    expect(cell.attributes('colspan')).toBe('1');
  });


  it('renders caption from prop', () => {
    const captionText = 'My Table Caption';
    const wrapper = mount(VTable, { props: { headers: [], items: [], caption: captionText } });
    const captionElement = wrapper.find('caption');
    expect(captionElement.exists()).toBe(true);
    expect(captionElement.text()).toBe(captionText);
  });

  it('renders caption from slot (overrides prop)', () => {
    const slotCaption = '<em>Slot Caption</em>';
    const wrapper = mount(VTable, {
      props: { headers: [], items: [], caption: 'Prop Caption Ignored' },
      slots: { caption: slotCaption },
    });
    const captionElement = wrapper.find('caption');
    expect(captionElement.html()).toContain(slotCaption);
  });

  it('does not render caption if no prop and no slot', () => {
     const wrapper = mount(VTable, { props: { headers: [], items: [] } });
     expect(wrapper.find('caption').exists()).toBe(false);
  });

  it('applies tableClass to table element', () => {
    const customClass = 'my-custom-table-class';
    const wrapper = mount(VTable, { props: { headers: [], items: [], tableClass: customClass } });
    expect(wrapper.find('table.table').classes()).toContain(customClass);
  });

  it('applies headerClass to th element', () => {
    const headerWithClass = [{ key: 'id', label: 'ID', headerClass: 'custom-th-class' }];
    const wrapper = mount(VTable, { props: { headers: headerWithClass, items: [] } });
    expect(wrapper.find('thead th').classes()).toContain('custom-th-class');
  });

  it('applies cellClass to td element', () => {
    const headerWithCellClass = [{ key: 'name', label: 'Name', cellClass: 'custom-td-class' }];
    const itemsForCellClass = [{ name: 'Test' }];
    const wrapper = mount(VTable, { props: { headers: headerWithCellClass, items: itemsForCellClass } });
    expect(wrapper.find('tbody td').classes()).toContain('custom-td-class');
  });

  it('renders an empty tbody if items is empty and no empty-state slot', () => {
    const wrapper = mount(VTable, { props: { headers: testHeaders, items: [] } });
    const tbody = wrapper.find('tbody');
    expect(tbody.exists()).toBe(true);
    expect(tbody.findAll('tr').length).toBe(0); // No rows
  });
});
