import type { Meta, StoryObj } from '@storybook/react'
import { useCallback, useEffect, useRef } from 'react'
import { Button } from '../Button/Button'
import { Toaster } from '../Toaster/Toaster'
import { toast, Toast, type ToastProps } from './Toast'

const ToastRenderer = (props: { toastProps: ToastProps; viewMode: string }) => {
  const { toastProps, viewMode } = props
  const hasToastBeenShown = useRef(false)

  const handleShowToast = useCallback(() => {
    toast(toastProps)
  }, [toastProps])

  useEffect(() => {
    if (viewMode === 'story' && !hasToastBeenShown.current) {
      setTimeout(() => handleShowToast(), 0)
      hasToastBeenShown.current = true
    }
  }, [viewMode, handleShowToast])

  return <Button onClick={handleShowToast}>Trigger Toast</Button>
}

const meta: Meta<typeof Toast> = {
  title: 'Blocks/Toast',
  component: Toast,
  decorators: [
    (Story, context) => {
      if (context.id === 'blocks-toast--all-variants') {
        return (
          <>
            <Story />
            <Toaster />
          </>
        )
      }

      return (
        <div className="flex h-24 w-full items-center justify-center">
          <Story />
          <Toaster />
        </div>
      )
    },
  ],
  render: (args, context) => (
    <ToastRenderer
      toastProps={args as ToastProps}
      viewMode={context.viewMode}
    />
  ),
}

export default meta

type Story = StoryObj<ToastProps>

const createSourceCode = (args: ToastProps) => {
  const props = Object.entries(args)
    .filter(([, value]) => value !== undefined && value !== '')
    .map(([key, value]) => {
      if (key === 'action') {
        return `    action: { label: 'Undo', onClick: () => alert('Action clicked!') }`
      }
      if (typeof value === 'string') {
        return `    ${key}: '${value}'`
      }
      return `    ${key}: ${value}`
    })
    .join(',\n')

  return `
const Component = () => {
  const handleShowToast = () => {
    toast({
${props}
    });
  };

  return (
    <>
      <Button onClick={handleShowToast}>Trigger Toast</Button>
      <Toaster />
    </>
  );
}
`
}

export const AllVariants: Story = {
  render: () => (
    <div className="flex w-full max-w-[600px] flex-col gap-2">
      <Toast
        title="This is the toast's title"
        description="This is an Info toast!"
        close={true}
        action={{ label: 'Undo', onClick: () => alert('Action clicked!') }}
      />
      <Toast
        title="This is the toast's title"
        variant="error"
        description="This is an Error toast!"
        close={true}
        action={{ label: 'Undo', onClick: () => alert('Action clicked!') }}
      />
      <Toast
        title="This is the toast's title"
        variant="warning"
        description="This is a Warning toast!"
        close={true}
        action={{ label: 'Undo', onClick: () => alert('Action clicked!') }}
      />
      <Toast
        title="This is the toast's title"
        variant="success"
        description="This is a Success toast!"
        close={true}
        action={{ label: 'Undo', onClick: () => alert('Action clicked!') }}
      />
    </div>
  ),
}

const allArgs: ToastProps = {
  title: 'Success toast',
  variant: 'success',
  description: 'This toast has all elements.',
}

export const AllElements: Story = {
  args: {
    ...allArgs,
    action: { label: 'Undo', onClick: () => alert('Action clicked!') },
  },
}
AllElements.parameters = {
  docs: {
    source: { code: createSourceCode(AllElements.args as ToastProps) },
  },
}

export const WithoutAction: Story = {
  args: {
    ...allArgs,
    title: 'Warning toast',
    variant: 'warning',
    description: 'This toast has no action.',
  },
}
WithoutAction.parameters = {
  docs: {
    source: { code: createSourceCode(WithoutAction.args as ToastProps) },
  },
}

export const WithoutClose: Story = {
  args: {
    ...allArgs,
    title: 'Error toast',
    variant: 'error',
    close: false,
    description: 'This toast has no close button.',
    action: { label: 'Undo', onClick: () => alert('Action clicked!') },
  },
}
WithoutClose.parameters = {
  docs: {
    source: { code: createSourceCode(WithoutClose.args as ToastProps) },
  },
}

export const WithoutCountdown: Story = {
  args: {
    ...allArgs,
    title: 'Info toast',
    variant: 'info',
    countdown: false,
    description: 'This toast has no countdown.',
  },
}
WithoutCountdown.parameters = {
  docs: {
    source: { code: createSourceCode(WithoutCountdown.args as ToastProps) },
  },
}
