import { mount } from '@vue/test-utils';
import VTabs from './VTabs.vue';
import VTab from './VTab.vue';
import VTabList from './VTabList.vue';
import VTabPanel from './VTabPanel.vue';
import VTabPanels from './VTabPanels.vue';
import { TabsProviderKey } from './types';
import { nextTick, h } from 'vue';

// Helper to create a minimal tabs structure for testing VTabs logic
const createBasicTabsStructure = (activeTabId: string | null = 'tab1') => {
  return {
    components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel },
    template: `
      <VTabs :modelValue="currentModelValue" @update:modelValue="val => currentModelValue = val" :initialTab="initialTabValue">
        <VTabList>
          <VTab id="tab1" title="Tab 1" />
          <VTab id="tab2" title="Tab 2" />
        </VTabList>
        <VTabPanels>
          <VTabPanel id="tab1"><p>Content 1</p></VTabPanel>
          <VTabPanel id="tab2"><p>Content 2</p></VTabPanel>
        </VTabPanels>
      </VTabs>
    `,
    data() {
      return {
        currentModelValue: activeTabId,
        initialTabValue: activeTabId, // Can be overridden in test
      };
    },
  };
};


describe('VTabs.vue', () => {
  it('initializes activeTabId with modelValue', () => {
    const wrapper = mount(VTabs, {
      props: { modelValue: 'second' },
      slots: { default: '<VTabList><VTab id="first"/><VTab id="second"/></VTabList><VTabPanels><VTabPanel id="first"/><VTabPanel id="second"/></VTabPanels>' },
      global: { components: { VTabList, VTab, VTabPanels, VTabPanel } } // Stubbing children
    });
    const context = wrapper.vm.$.provides[TabsProviderKey as any];
    expect(context.activeTabId.value).toBe('second');
  });

  it('initializes activeTabId with initialTab if modelValue is not provided', () => {
    const wrapper = mount(VTabs, {
      props: { initialTab: 'third' },
       slots: { default: '<VTabList><VTab id="first"/><VTab id="third"/></VTabList><VTabPanels><VTabPanel id="first"/><VTabPanel id="third"/></VTabPanels>' },
      global: { components: { VTabList, VTab, VTabPanels, VTabPanel } }
    });
    const context = wrapper.vm.$.provides[TabsProviderKey as any];
    expect(context.activeTabId.value).toBe('third');
  });

  it('updates activeTabId when modelValue prop changes', async () => {
    const wrapper = mount(VTabs, {
      props: { modelValue: 'one' },
      slots: { default: '<VTabList><VTab id="one"/><VTab id="two"/></VTabList><VTabPanels><VTabPanel id="one"/><VTabPanel id="two"/></VTabPanels>' },
      global: { components: { VTabList, VTab, VTabPanels, VTabPanel } }
    });
    const context = wrapper.vm.$.provides[TabsProviderKey as any];
    expect(context.activeTabId.value).toBe('one');
    await wrapper.setProps({ modelValue: 'two' });
    expect(context.activeTabId.value).toBe('two');
  });

  it('emits update:modelValue when selectTab is called', async () => {
    const wrapper = mount(VTabs, {
      props: { modelValue: 'alpha' },
      slots: { default: '<VTabList><VTab id="alpha"/><VTab id="beta"/></VTabList><VTabPanels><VTabPanel id="alpha"/><VTabPanel id="beta"/></VTabPanels>' },
      global: { components: { VTabList, VTab, VTabPanels, VTabPanel } }
    });
    const context = wrapper.vm.$.provides[TabsProviderKey as any];
    context.selectTab('beta');
    await nextTick();
    expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
    expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['beta']);
    expect(context.activeTabId.value).toBe('beta');
  });

  it('selects the first tab if no modelValue or initialTab is provided on mount', async () => {
    // This test is more involved as it requires inspecting slot children
    // We need to ensure VTab components are actually rendered within the slots
    const TestComponent = {
      components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel },
      template: `
        <VTabs>
          <VTabList>
            <VTab id="firstMounted" title="First" />
            <VTab id="secondMounted" title="Second" />
          </VTabList>
          <VTabPanels>
            <VTabPanel id="firstMounted">Content First</VTabPanel>
            <VTabPanel id="secondMounted">Content Second</VTabPanel>
          </VTabPanels>
        </VTabs>
      `,
    };
    const wrapper = mount(TestComponent);
    await nextTick(); // Wait for onMounted hook in VTabs

    // Access VTabs instance to check its internal activeTabId via provided context
    const vTabsInstance = wrapper.findComponent(VTabs);
    const context = vTabsInstance.vm.$.provides[TabsProviderKey as any];
    expect(context.activeTabId.value).toBe('firstMounted');
  });

  it('does not change activeTabId if modelValue is explicitly null and no initialTab', async () => {
     const TestComponent = {
      components: { VTabs, VTabList, VTab, VTabPanels, VTabPanel },
      template: `
        <VTabs :modelValue="null">
          <VTabList> <VTab id="t1" /> </VTabList>
          <VTabPanels> <VTabPanel id="t1" /> </VTabPanels>
        </VTabs>
      `,
    };
    const wrapper = mount(TestComponent);
    await nextTick();
    const vTabsInstance = wrapper.findComponent(VTabs);
    const context = vTabsInstance.vm.$.provides[TabsProviderKey as any];
    expect(context.activeTabId.value).toBeNull(); // Should remain null, not default to first tab
  });


  it('renders its default slot content', () => {
    const wrapper = mount(VTabs, {
      slots: { default: '<div class="test-slot-content">Hello</div>' },
    });
    expect(wrapper.find('.test-slot-content').exists()).toBe(true);
    expect(wrapper.text()).toContain('Hello');
  });
});
