import type { Meta, StoryObj } from '@storybook/vue3-vite';
import { ref } from 'vue';
import {
  UiResizableHandle,
  UiResizablePanel,
  UiResizablePanelGroup,
} from './index';

/**
 * UiResizable creates split-panel layouts whose panels can be resized by dragging
 * the handle between them.
 */
const meta: Meta<typeof UiResizablePanelGroup> = {
  title: 'Components/UiResizable',
  component: UiResizablePanelGroup,
  tags: ['autodocs'],
  argTypes: {
    direction: {
      control: 'select',
      options: ['horizontal', 'vertical'],
      description: 'The orientation of the resizable panel group.',
    },
    autoSaveId: {
      control: 'text',
      description:
        'Optional id used to persist the panel layout in localStorage.',
    },
    keyboardResizeBy: {
      control: 'number',
      description: 'Step size used when resizing with the keyboard.',
    },
  },
  args: {
    direction: 'horizontal',
    keyboardResizeBy: 10,
  },
};

export default meta;

type Story = StoryObj<typeof UiResizablePanelGroup>;

const panelClasses =
  'flex items-center justify-center rounded-md bg-background-surface-muted p-6 text-sm';
const sizeValueClasses = 'font-mono text-xs text-muted-foreground';

const defaultTemplateSource = `<script setup lang="ts">
import { ref } from 'vue'
import {
  UiResizableHandle,
  UiResizablePanel,
  UiResizablePanelGroup,
} from '@aleph-alpha/ui-library'

const sidebarWidth = ref(30)
const contentWidth = ref(70)

function updateSidebarWidth(size: number) {
  sidebarWidth.value = Math.round(size)
}

function updateContentWidth(size: number) {
  contentWidth.value = Math.round(size)
}
</script>

<template>
  <UiResizablePanelGroup direction="horizontal" class="min-h-64 rounded-lg">
    <UiResizablePanel
      :default-size="30"
      :min-size="20"
      @resize="updateSidebarWidth"
    >
      <div
        class="flex h-full flex-col items-center justify-center gap-1 rounded-md bg-background-surface-muted p-6 text-sm"
      >
        <span>Sidebar</span>
        <span class="font-mono text-xs text-muted-foreground">{{ sidebarWidth }}% wide</span>
      </div>
    </UiResizablePanel>
    <UiResizableHandle with-handle />
    <UiResizablePanel
      :default-size="70"
      :min-size="30"
      @resize="updateContentWidth"
    >
      <div
        class="flex h-full flex-col items-center justify-center gap-1 rounded-md bg-background-surface-muted p-6 text-sm"
      >
        <span>Content</span>
        <span class="font-mono text-xs text-muted-foreground">{{ contentWidth }}% wide</span>
      </div>
    </UiResizablePanel>
  </UiResizablePanelGroup>
</template>`;

/**
 * Two horizontal panels with a visible drag handle.
 */
export const Default: Story = {
  render: (args) => ({
    components: {
      UiResizableHandle,
      UiResizablePanel,
      UiResizablePanelGroup,
    },
    setup() {
      const sidebarWidth = ref(30);
      const contentWidth = ref(70);

      function updateSidebarWidth(size: number) {
        sidebarWidth.value = Math.round(size);
      }

      function updateContentWidth(size: number) {
        contentWidth.value = Math.round(size);
      }

      return {
        args,
        contentWidth,
        panelClasses,
        sidebarWidth,
        sizeValueClasses,
        updateContentWidth,
        updateSidebarWidth,
      };
    },
    template: `
      <UiResizablePanelGroup
        v-bind="args"
        class="min-h-64 border border-border-surface-focus-ring"
      >
        <UiResizablePanel
          :default-size="30"
          :min-size="20"
          @resize="updateSidebarWidth"
        >
          <div
            :class="[panelClasses, 'h-full flex-col gap-1']"
          >
            <span>Sidebar</span>
            <span :class="sizeValueClasses">{{ sidebarWidth }}% wide</span>
          </div>
        </UiResizablePanel>
        <UiResizableHandle with-handle />
        <UiResizablePanel
          :default-size="70"
          :min-size="30"
          @resize="updateContentWidth"
        >
          <div
            :class="[panelClasses, 'h-full flex-col gap-1']"
          >
            <span>Content</span>
            <span :class="sizeValueClasses">{{ contentWidth }}% wide</span>
          </div>
        </UiResizablePanel>
      </UiResizablePanelGroup>
    `,
  }),
  parameters: {
    docs: {
      source: {
        code: defaultTemplateSource,
      },
    },
  },
};

const verticalTemplateSource = `<script setup lang="ts">
import { ref } from 'vue'
import {
  UiResizableHandle,
  UiResizablePanel,
  UiResizablePanelGroup,
} from '@aleph-alpha/ui-library'

const previewHeight = ref(60)
const consoleHeight = ref(40)

function updatePreviewHeight(size: number) {
  previewHeight.value = Math.round(size)
}

function updateConsoleHeight(size: number) {
  consoleHeight.value = Math.round(size)
}
</script>

<template>
  <UiResizablePanelGroup direction="vertical" class="min-h-96 rounded-lg bg-background-surface-secondary p-2 shadow-lg">
    <UiResizablePanel
      :default-size="60"
      :min-size="30"
      @resize="updatePreviewHeight"
    >
      <div
        class="flex h-full flex-col items-center justify-center gap-1 rounded-md bg-background-surface-muted p-6 text-sm"
      >
        <span>Preview</span>
        <span class="font-mono text-xs text-muted-foreground">{{ previewHeight }}% tall</span>
      </div>
    </UiResizablePanel>
    <UiResizableHandle with-handle />
    <UiResizablePanel
      :default-size="40"
      :min-size="20"
      @resize="updateConsoleHeight"
    >
      <div
        class="flex h-full flex-col items-center justify-center gap-1 rounded-md bg-background-surface-muted p-6 text-sm"
      >
        <span>Console</span>
        <span class="font-mono text-xs text-muted-foreground">{{ consoleHeight }}% tall</span>
      </div>
    </UiResizablePanel>
  </UiResizablePanelGroup>
</template>`;

/**
 * Vertical resizing stacks panels from top to bottom.
 */
export const Vertical: Story = {
  render: () => ({
    components: {
      UiResizableHandle,
      UiResizablePanel,
      UiResizablePanelGroup,
    },
    setup() {
      const previewHeight = ref(60);
      const consoleHeight = ref(40);

      function updatePreviewHeight(size: number) {
        previewHeight.value = Math.round(size);
      }

      function updateConsoleHeight(size: number) {
        consoleHeight.value = Math.round(size);
      }

      return {
        consoleHeight,
        panelClasses,
        previewHeight,
        sizeValueClasses,
        updateConsoleHeight,
        updatePreviewHeight,
      };
    },
    template: `
      <UiResizablePanelGroup
        direction="vertical"
        class="min-h-96 rounded-lg bg-background-surface-secondary p-2 shadow-lg"
      >
        <UiResizablePanel
          :default-size="60"
          :min-size="30"
          @resize="updatePreviewHeight"
        >
          <div
            :class="[panelClasses, 'h-full flex-col gap-1']"
          >
            <span>Preview</span>
            <span :class="sizeValueClasses">{{ previewHeight }}% tall</span>
          </div>
        </UiResizablePanel>
        <UiResizableHandle with-handle />
        <UiResizablePanel
          :default-size="40"
          :min-size="20"
          @resize="updateConsoleHeight"
        >
          <div
            :class="[panelClasses, 'h-full flex-col gap-1']"
          >
            <span>Console</span>
            <span :class="sizeValueClasses">{{ consoleHeight }}% tall</span>
          </div>
        </UiResizablePanel>
      </UiResizablePanelGroup>
    `,
  }),
  parameters: {
    docs: {
      source: {
        code: verticalTemplateSource,
      },
    },
  },
};

const collapsibleTemplateSource = `<script setup lang="ts">
import {
  UiResizableHandle,
  UiResizablePanel,
  UiResizablePanelGroup,
} from '@aleph-alpha/ui-library'
</script>

<template>
  <UiResizablePanelGroup direction="horizontal" class="min-h-64 rounded-lg bg-background-surface-secondary p-2 shadow-lg">
    <UiResizablePanel collapsible :collapsed-size="8" :default-size="25" :min-size="20">
      <div class="flex h-full items-center justify-center rounded-md bg-background-surface-muted p-6 text-sm">
        Collapsible
      </div>
    </UiResizablePanel>
    <UiResizableHandle with-handle />
    <UiResizablePanel :default-size="75" :min-size="30">
      <div class="flex h-full items-center justify-center rounded-md bg-background-surface-muted p-6 text-sm">
        Main panel
      </div>
    </UiResizablePanel>
  </UiResizablePanelGroup>
</template>`;

/**
 * A panel can collapse when resized below its minimum size.
 */
export const Collapsible: Story = {
  render: () => ({
    components: {
      UiResizableHandle,
      UiResizablePanel,
      UiResizablePanelGroup,
    },
    setup() {
      return { panelClasses };
    },
    template: `
      <UiResizablePanelGroup
        direction="horizontal"
        class="min-h-64 rounded-lg bg-background-surface-secondary p-2 shadow-lg"
      >
        <UiResizablePanel
          collapsible
          :collapsed-size="8"
          :default-size="25"
          :min-size="20"
        >
          <div :class="[panelClasses, 'h-full']">Collapsible</div>
        </UiResizablePanel>
        <UiResizableHandle with-handle />
        <UiResizablePanel :default-size="75" :min-size="30">
          <div :class="[panelClasses, 'h-full']">Main panel</div>
        </UiResizablePanel>
      </UiResizablePanelGroup>
    `,
  }),
  parameters: {
    docs: {
      source: {
        code: collapsibleTemplateSource,
      },
    },
  },
};

const pixelSizingTemplateSource = `<script setup lang="ts">
import {
  UiResizableHandle,
  UiResizablePanel,
  UiResizablePanelGroup,
} from '@aleph-alpha/ui-library'
</script>

<template>
  <UiResizablePanelGroup direction="horizontal" class="min-h-64 rounded-lg bg-background-surface-secondary p-2 shadow-lg">
    <UiResizablePanel size-unit="px" :default-size="240" :min-size="160" :max-size="320">
      <div class="flex h-full items-center justify-center rounded-md bg-background-surface-muted p-6 text-sm">
        Fixed sidebar
      </div>
    </UiResizablePanel>
    <UiResizableHandle with-handle />
    <UiResizablePanel>
      <div class="flex h-full items-center justify-center rounded-md bg-background-surface-muted p-6 text-sm">
        Flexible content
      </div>
    </UiResizablePanel>
  </UiResizablePanelGroup>
</template>`;

/**
 * Pixel sizing keeps a panel at a fixed pixel width while the rest of the group stays flexible.
 */
export const PixelSizing: Story = {
  render: () => ({
    components: {
      UiResizableHandle,
      UiResizablePanel,
      UiResizablePanelGroup,
    },
    setup() {
      return { panelClasses };
    },
    template: `
      <UiResizablePanelGroup
        direction="horizontal"
        class="min-h-64 rounded-lg bg-background-surface-secondary p-2 shadow-lg"
      >
        <UiResizablePanel
          size-unit="px"
          :default-size="240"
          :min-size="160"
          :max-size="320"
        >
          <div :class="[panelClasses, 'h-full']">Fixed sidebar</div>
        </UiResizablePanel>
        <UiResizableHandle with-handle />
        <UiResizablePanel>
          <div :class="[panelClasses, 'h-full']">Flexible content</div>
        </UiResizablePanel>
      </UiResizablePanelGroup>
    `,
  }),
  parameters: {
    docs: {
      source: {
        code: pixelSizingTemplateSource,
      },
    },
  },
};
