import type { Meta, StoryObj } from "@storybook/vue3-vite"
import { onBeforeUnmount, ref, type Ref } from "vue"
import BuildStatus from "./BuildStatus.vue"
import type { BuildStatusEvent } from "./BuildStatus.vue"
import { componentDoc } from "@/lib/storybook"

const meta = {
  title: "Elements/Code/BuildStatus",
  component: BuildStatus,
  tags: ["autodocs"],
  args: {
    label: "Build Status",
    initial: { status: "pending" },
    showLogs: true,
  },
  parameters: componentDoc("BuildStatus", { barrel: "code" }),
  decorators: [
    () => ({
      template: '<div class="w-[640px] p-4"><story /></div>',
    }),
  ],
} satisfies Meta<typeof BuildStatus>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
  args: {
    initial: {
      status: "running",
      commitSha: "f3a1c2d4b5",
      commitMessage: "Add ChatMessage variants",
      triggeredBy: "alice",
      durationMs: 32_000,
      logs: ["> npm ci", "> npm run build", "Compiling..."],
    },
  },
}

export const Success: Story = {
  args: {
    initial: {
      status: "success",
      commitSha: "abc1234",
      commitMessage: "Fix dashboard crash",
      triggeredBy: "bob",
      durationMs: 124_000,
      logs: ["> npm run test", "All tests passed."],
    },
  },
}

export const Failed: Story = {
  args: {
    initial: {
      status: "failed",
      commitSha: "deadbee",
      commitMessage: "Refactor billing service",
      triggeredBy: "carol",
      durationMs: 60_000,
      logs: ["FAIL src/billing.test.ts", "Expected 3, got 2"],
    },
  },
}

export const Loading: Story = {
  args: {
    initial: { status: "pending" },
  },
}

export const ErrorState: Story = {
  args: {
    initial: {
      status: "failed",
      commitMessage: "Deploy failed before build started.",
      triggeredBy: "ci",
    },
  },
}

interface DemoEmitter {
  addEventListener: (
    type: string,
    listener: (e: { data: unknown }) => void,
  ) => void
  removeEventListener: (
    type: string,
    listener: (e: { data: unknown }) => void,
  ) => void
}

function makeDemoStream(
  timer: Ref<ReturnType<typeof setInterval> | null>,
): DemoEmitter {
  let handler: ((e: { data: unknown }) => void) | null = null
  let step = 0
  const sequence: BuildStatusEvent[] = [
    { status: "pending", commitMessage: "Queued..." },
    {
      status: "running",
      commitMessage: "Building artifact",
      commitSha: "feedbac",
      triggeredBy: "alice",
      logs: ["> npm ci"],
    },
    {
      status: "running",
      commitMessage: "Building artifact",
      commitSha: "feedbac",
      triggeredBy: "alice",
      logs: ["> npm ci", "> npm run build"],
    },
    {
      status: "success",
      commitMessage: "Building artifact",
      commitSha: "feedbac",
      triggeredBy: "alice",
      durationMs: 22_000,
      logs: ["> npm ci", "> npm run build", "Done."],
    },
  ]
  timer.value = setInterval(() => {
    const next = sequence[step % sequence.length]
    if (handler && next) {
      handler({ data: JSON.stringify(next) })
    }
    step += 1
  }, 1500)
  return {
    addEventListener(_type, h) {
      handler = h
    },
    removeEventListener() {
      handler = null
    },
  }
}

export const LiveStream: Story = {
  args: {} as never,
  render: () => ({
    components: { BuildStatus },
    setup() {
      const timer = ref<ReturnType<typeof setInterval> | null>(null)
      const stream = makeDemoStream(timer)
      onBeforeUnmount(() => {
        if (timer.value !== null) {
          clearInterval(timer.value)
        }
      })
      return { stream }
    },
    template: `
      <BuildStatus
        label="Live pipeline"
        :event-stream="stream"
        :initial="{ status: 'pending' }"
      />
    `,
  }),
}

export const Showcase: Story = {
  args: {} as never,
  render: () => ({
    components: { BuildStatus },
    template: `
      <div class="flex flex-col gap-4">
        <BuildStatus
          label="Pending"
          :initial="{ status: 'pending', commitMessage: 'Queued' }"
        />
        <BuildStatus
          label="Running"
          :initial="{
            status: 'running',
            commitSha: 'abcdef1',
            commitMessage: 'Implement Card variants',
            triggeredBy: 'alice',
            logs: ['> npm ci', '> npm run build']
          }"
        />
        <BuildStatus
          label="Success"
          :initial="{
            status: 'success',
            commitSha: 'beadcaf',
            commitMessage: 'Ship feature',
            triggeredBy: 'bob',
            durationMs: 95000
          }"
        />
        <BuildStatus
          label="Failed"
          :initial="{
            status: 'failed',
            commitSha: 'deadbee',
            commitMessage: 'Fix flaky test',
            triggeredBy: 'carol',
            durationMs: 41000,
            logs: ['FAIL src/x.test.ts']
          }"
        />
        <BuildStatus
          label="Cancelled"
          :initial="{
            status: 'cancelled',
            commitSha: 'cafebab',
            commitMessage: 'Manual cancel',
            triggeredBy: 'dave'
          }"
        />
      </div>
    `,
  }),
}
