import type { Meta, StoryObj } from "@storybook/vue3-vite"
import FileTree from "./FileTree.vue"
import type { TreeNode } from "./FileTree.vue"
import { componentDoc } from "@/lib/storybook"

const ROOT: TreeNode[] = [
  { path: "src", name: "src", kind: "directory" },
  { path: "tests", name: "tests", kind: "directory" },
  { path: "README.md", name: "README.md", kind: "file" },
  { path: "package.json", name: "package.json", kind: "file" },
]

const SRC: TreeNode[] = [
  { path: "src/components", name: "components", kind: "directory" },
  { path: "src/index.ts", name: "index.ts", kind: "file" },
  { path: "src/App.vue", name: "App.vue", kind: "file" },
]

const SRC_COMPONENTS: TreeNode[] = [
  { path: "src/components/Button.vue", name: "Button.vue", kind: "file" },
  { path: "src/components/Card.vue", name: "Card.vue", kind: "file" },
  { path: "src/components/Input.vue", name: "Input.vue", kind: "file" },
]

const TESTS: TreeNode[] = [
  { path: "tests/Button.test.ts", name: "Button.test.ts", kind: "file" },
]

function mockLoad(delay = 250): (path: string) => Promise<TreeNode[]> {
  return (path: string) =>
    new Promise((resolve) =>
      setTimeout(() => {
        if (path === "") {
          resolve(ROOT)
        } else if (path === "src") {
          resolve(SRC)
        } else if (path === "src/components") {
          resolve(SRC_COMPONENTS)
        } else if (path === "tests") {
          resolve(TESTS)
        } else {
          resolve([])
        }
      }, delay),
    )
}

function neverResolve(): (path: string) => Promise<TreeNode[]> {
  return () => new Promise(() => {})
}

function alwaysFail(): (path: string) => Promise<TreeNode[]> {
  return () => Promise.reject(new globalThis.Error("Repository not available"))
}

const meta = {
  title: "Elements/Code/FileTree",
  component: FileTree,
  tags: ["autodocs"],
  args: {
    label: "File Tree",
    onLoadTree: mockLoad(),
  },
  parameters: componentDoc("FileTree", { barrel: "code" }),
  decorators: [
    () => ({
      template: '<div class="w-96 p-4"><story /></div>',
    }),
  ],
} satisfies Meta<typeof FileTree>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
  args: {
    onLoadTree: mockLoad(),
  },
}

export const WithSelectedItem: Story = {
  args: {
    onLoadTree: mockLoad(),
    selectedPath: "README.md",
    expandedPaths: ["src", "src/components"],
  },
}

export const Loading: Story = {
  args: {
    onLoadTree: neverResolve(),
  },
}

export const ErrorState: Story = {
  args: {
    onLoadTree: alwaysFail(),
  },
}

export const Showcase: Story = {
  args: {} as never,
  render: () => ({
    components: { FileTree },
    setup() {
      return { load: mockLoad(150) }
    },
    template: `
      <div class="flex flex-col gap-4">
        <FileTree label="Project files" :on-load-tree="load" />
        <FileTree
          label="With selection"
          :on-load-tree="load"
          selected-path="README.md"
          :expanded-paths="['src']"
        />
      </div>
    `,
  }),
}
