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

const BRANCHES = ["main", "develop", "feat/new-card", "hotfix/login"]

const SAMPLE: Record<string, string> = {
  "README.md": "# Project\n\nHello world.\n",
  "src/index.ts": "export const greet = (n: string) => `Hi ${n}`\n",
  "package.json": `{\n  "name": "demo",\n  "version": "1.0.0"\n}\n`,
}

function mockLoadBranches(delay = 150): () => Promise<string[]> {
  return () =>
    new Promise((r) => setTimeout(() => r(BRANCHES), delay))
}

function mockLoadFile(
  delay = 200,
): (p: string, b: string) => Promise<GitCodeEditorLoadedFile> {
  return (p) =>
    new Promise((resolve) =>
      setTimeout(() => {
        const content = SAMPLE[p] ?? `// ${p}\n// (no sample content)\n`
        const language = p.endsWith(".ts")
          ? "typescript"
          : p.endsWith(".md")
            ? "markdown"
            : p.endsWith(".json")
              ? "json"
              : "plaintext"
        resolve({ content, language })
      }, delay),
    )
}

function mockSaveFile(
  delay = 400,
): (p: string, b: string, c: string) => Promise<void> {
  return () => new Promise((r) => setTimeout(() => r(), delay))
}

const meta = {
  title: "Elements/Code/GitCodeEditor",
  component: GitCodeEditor,
  tags: ["autodocs"],
  args: {
    label: "Git Code Editor",
    repository: "gramercy/demo",
    branch: "main",
    path: "README.md",
    onLoadBranches: mockLoadBranches(),
    onLoadFile: mockLoadFile(),
  },
  parameters: componentDoc("GitCodeEditor", { barrel: "code" }),
  decorators: [
    () => ({
      template: '<div class="w-[640px] p-4"><story /></div>',
    }),
  ],
} satisfies Meta<typeof GitCodeEditor>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
  args: {
    label: "README",
    repository: "gramercy/demo",
    branch: "main",
    path: "README.md",
    onLoadBranches: mockLoadBranches(),
    onLoadFile: mockLoadFile(),
  },
}

export const WithSave: Story = {
  args: {
    label: "Editable file",
    repository: "gramercy/demo",
    branch: "main",
    path: "src/index.ts",
    onLoadBranches: mockLoadBranches(),
    onLoadFile: mockLoadFile(),
    onSaveFile: mockSaveFile(),
  },
}

export const Loading: Story = {
  args: {
    label: "Loading",
    repository: "gramercy/demo",
    branch: "main",
    path: "src/index.ts",
    onLoadBranches: mockLoadBranches(2_000_000),
    onLoadFile: () => new Promise(() => {}),
  },
}

export const ErrorState: Story = {
  args: {
    label: "Editor",
    repository: "gramercy/demo",
    branch: "main",
    path: "missing.md",
    onLoadBranches: mockLoadBranches(),
    onLoadFile: () =>
      Promise.reject(new globalThis.Error("File not found in branch main")),
  },
}

export const Showcase: Story = {
  args: {} as never,
  render: () => ({
    components: { GitCodeEditor },
    setup() {
      return {
        onLoadBranches: mockLoadBranches(),
        onLoadFile: mockLoadFile(),
        onSaveFile: mockSaveFile(),
      }
    },
    template: `
      <div class="flex flex-col gap-4">
        <GitCodeEditor
          label="README"
          repository="gramercy/demo"
          branch="main"
          path="README.md"
          :on-load-branches="onLoadBranches"
          :on-load-file="onLoadFile"
        />
        <GitCodeEditor
          label="Editable"
          repository="gramercy/demo"
          branch="develop"
          path="src/index.ts"
          :on-load-branches="onLoadBranches"
          :on-load-file="onLoadFile"
          :on-save-file="onSaveFile"
        />
      </div>
    `,
  }),
}
