import { render } from '@testing-library/vue';
import { describe, expect, test, vi } from 'vitest';
import {
  UiSheet,
  UiSheetClose,
  UiSheetContent,
  UiSheetDescription,
  UiSheetFooter,
  UiSheetHeader,
  UiSheetTitle,
  UiSheetTrigger,
} from '../index';
import { UiButton } from '../../UiButton';
import { ref } from 'vue';

describe('UiSheet', () => {
  test('emits update:open when trigger is clicked', async () => {
    const onUpdateOpen = vi.fn();
    const { getByText } = render({
      components: {
        UiSheet,
        UiSheetContent,
        UiSheetDescription,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
      },
      setup() {
        return { onUpdateOpen };
      },
      template: `
        <UiSheet @update:open="onUpdateOpen">
          <UiSheetTrigger>Open</UiSheetTrigger>
          <UiSheetContent>
            <UiSheetHeader>
              <UiSheetTitle>Title</UiSheetTitle>
              <UiSheetDescription>Description</UiSheetDescription>
            </UiSheetHeader>
            Content
          </UiSheetContent>
        </UiSheet>
      `,
    });

    await getByText('Open').click();
    expect(onUpdateOpen).toHaveBeenCalledWith(true);
  });

  test('works with as-child pattern and UiButton', async () => {
    const onUpdateOpen = vi.fn();
    const { getByRole } = render({
      components: {
        UiSheet,
        UiSheetContent,
        UiSheetDescription,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
        UiButton,
      },
      setup() {
        return { onUpdateOpen };
      },
      template: `
        <UiSheet @update:open="onUpdateOpen">
          <UiSheetTrigger as-child>
            <UiButton variant="outline">Open Sheet</UiButton>
          </UiSheetTrigger>
          <UiSheetContent>
            <UiSheetHeader>
              <UiSheetTitle>Title</UiSheetTitle>
              <UiSheetDescription>Description</UiSheetDescription>
            </UiSheetHeader>
            Content
          </UiSheetContent>
        </UiSheet>
      `,
    });

    await getByRole('button', { name: 'Open Sheet' }).click();
    expect(onUpdateOpen).toHaveBeenCalledWith(true);
  });

  test('closes via UiSheetClose', async () => {
    const onUpdateOpen = vi.fn();
    const { getByRole, getByText } = render({
      components: {
        UiSheet,
        UiSheetClose,
        UiSheetContent,
        UiSheetDescription,
        UiSheetFooter,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
      },
      setup() {
        return { onUpdateOpen };
      },
      template: `
        <UiSheet @update:open="onUpdateOpen">
          <UiSheetTrigger>Open</UiSheetTrigger>
          <UiSheetContent>
            <UiSheetHeader>
              <UiSheetTitle>Title</UiSheetTitle>
              <UiSheetDescription>Description</UiSheetDescription>
            </UiSheetHeader>
            <UiSheetFooter>
              <UiSheetClose>Close sheet</UiSheetClose>
            </UiSheetFooter>
          </UiSheetContent>
        </UiSheet>
      `,
    });

    await getByText('Open').click();
    expect(getByRole('dialog')).toBeInTheDocument();

    await getByText('Close sheet').click();
    expect(onUpdateOpen).toHaveBeenCalledWith(false);
  });

  test('emits escapeKeyDown and closes when Escape is pressed', async () => {
    const onEscapeKeyDown = vi.fn();
    const onUpdateOpen = vi.fn();
    const { getByText, getByRole } = render({
      components: {
        UiSheet,
        UiSheetContent,
        UiSheetDescription,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
      },
      setup() {
        return { onEscapeKeyDown, onUpdateOpen };
      },
      template: `
        <UiSheet @update:open="onUpdateOpen">
          <UiSheetTrigger>Open</UiSheetTrigger>
          <UiSheetContent @escape-key-down="onEscapeKeyDown">
            <UiSheetHeader>
              <UiSheetTitle>Title</UiSheetTitle>
              <UiSheetDescription>Description</UiSheetDescription>
            </UiSheetHeader>
            Content
          </UiSheetContent>
        </UiSheet>
      `,
    });

    await getByText('Open').click();
    expect(getByRole('dialog')).toBeInTheDocument();

    await getByRole('dialog').dispatchEvent(
      new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }),
    );

    expect(onEscapeKeyDown).toHaveBeenCalled();
    expect(onUpdateOpen).toHaveBeenCalledWith(false);
  });

  test('forwards class to the underlying sheet content element', async () => {
    const { getByText, getByRole } = render({
      components: {
        UiSheet,
        UiSheetContent,
        UiSheetDescription,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
      },
      template: `
        <UiSheet>
          <UiSheetTrigger>Open</UiSheetTrigger>
          <UiSheetContent class="my-sheet-class">
            <UiSheetHeader>
              <UiSheetTitle>Title</UiSheetTitle>
              <UiSheetDescription>Description</UiSheetDescription>
            </UiSheetHeader>
            Content
          </UiSheetContent>
        </UiSheet>
      `,
    });

    await getByText('Open').click();
    expect(getByRole('dialog')).toHaveClass('my-sheet-class');
  });

  test('supports controlled mode via v-model:open', async () => {
    const { getByRole, getByText } = render({
      components: {
        UiSheet,
        UiSheetContent,
        UiSheetDescription,
        UiSheetHeader,
        UiSheetTitle,
        UiSheetTrigger,
      },
      setup() {
        const open = ref(false);
        return { open };
      },
      template: `
        <div>
          <button type="button" @click="open = true">Open via model</button>
          <button type="button" @click="open = false">Close via model</button>
          <UiSheet v-model:open="open">
            <UiSheetTrigger>Open</UiSheetTrigger>
            <UiSheetContent>
              <UiSheetHeader>
                <UiSheetTitle>Title</UiSheetTitle>
                <UiSheetDescription>Description</UiSheetDescription>
              </UiSheetHeader>
              Content
            </UiSheetContent>
          </UiSheet>
        </div>
      `,
    });

    await getByText('Open via model').click();
    expect(getByRole('dialog')).toHaveAttribute('data-state', 'open');

    await getByText('Close via model').click();
    expect(getByRole('dialog')).toHaveAttribute('data-state', 'closed');
  });
});
