import '@testing-library/jest-dom/vitest';
import { render, waitFor } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import { describe, expect, test, vi } from 'vitest';
import { ref } from 'vue';
import { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent } from '../index';

describe('UiTabs', () => {
  test('activates tab specified by defaultValue prop', () => {
    const { getByRole } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs default-value="tab2">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
            <UiTabsTrigger value="tab2">Tab 2</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content 1</UiTabsContent>
          <UiTabsContent value="tab2">Content 2</UiTabsContent>
        </UiTabs>
      `,
    });

    expect(getByRole('tab', { name: 'Tab 2' })).toHaveAttribute(
      'data-state',
      'active',
    );
    expect(getByRole('tabpanel')).toHaveTextContent('Content 2');
  });

  test('emits update:modelValue when tab changes', async () => {
    const user = userEvent.setup();
    const onUpdateModelValue = vi.fn();

    const { getByRole } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs default-value="tab1" @update:modelValue="onUpdateModelValue">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
            <UiTabsTrigger value="tab2">Tab 2</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content 1</UiTabsContent>
          <UiTabsContent value="tab2">Content 2</UiTabsContent>
        </UiTabs>
      `,
      setup() {
        return { onUpdateModelValue };
      },
    });

    await user.click(getByRole('tab', { name: 'Tab 2' }));

    expect(onUpdateModelValue).toHaveBeenCalledWith('tab2');
  });

  test('reflects controlled modelValue', async () => {
    const { getByRole } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs :model-value="value">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
            <UiTabsTrigger value="tab2">Tab 2</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content 1</UiTabsContent>
          <UiTabsContent value="tab2">Content 2</UiTabsContent>
        </UiTabs>
      `,
      setup() {
        const value = ref('tab2');
        return { value };
      },
    });

    await waitFor(() => {
      expect(getByRole('tab', { name: 'Tab 2' })).toHaveAttribute(
        'data-state',
        'active',
      );
      expect(getByRole('tabpanel')).toHaveTextContent('Content 2');
    });
  });

  test('does not activate disabled tabs when clicked', async () => {
    const user = userEvent.setup();
    const { getByRole } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs default-value="tab1">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
            <UiTabsTrigger value="tab2" :disabled="true">Tab 2</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content 1</UiTabsContent>
          <UiTabsContent value="tab2">Content 2</UiTabsContent>
        </UiTabs>
      `,
    });

    const tab2 = getByRole('tab', { name: 'Tab 2' });
    expect(tab2).toBeDisabled();

    await user.click(tab2);

    await waitFor(() => {
      expect(tab2).toHaveAttribute('data-state', 'inactive');
      expect(getByRole('tabpanel')).toHaveTextContent('Content 1');
    });
  });

  test('applies custom class to root element', () => {
    const { container } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs default-value="tab1" class="custom-tabs-class">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content</UiTabsContent>
        </UiTabs>
      `,
    });

    const tabsRoot = container.querySelector('[data-slot="tabs"]');
    expect(tabsRoot).toHaveClass('custom-tabs-class');
  });

  test('uses muted-subtle list background and secondary tab states', () => {
    const { container, getByRole } = render({
      components: { UiTabs, UiTabsList, UiTabsTrigger, UiTabsContent },
      template: `
        <UiTabs default-value="tab1">
          <UiTabsList>
            <UiTabsTrigger value="tab1">Tab 1</UiTabsTrigger>
            <UiTabsTrigger value="tab2">Tab 2</UiTabsTrigger>
          </UiTabsList>
          <UiTabsContent value="tab1">Content 1</UiTabsContent>
          <UiTabsContent value="tab2">Content 2</UiTabsContent>
        </UiTabs>
      `,
    });

    const tabsList = container.querySelector('[data-slot="tabs-list"]');
    const tab = getByRole('tab', { name: 'Tab 1' });

    expect(tabsList).toHaveClass('bg-background-surface-muted-subtle');
    expect(tab).toHaveClass('hover:bg-background-surface-secondary');
    expect(tab).toHaveClass(
      'data-[state=active]:bg-background-surface-secondary',
    );
  });
});
