import type { Meta, StoryObj } from '@storybook/react-vite'
import React from 'react'
import { expect, screen, userEvent } from 'storybook/test'

import { DocsTemplate } from '../../../.storybook'
import { toast } from '../Toast/Toast'
import Alert from './Alert'
import { type ButtonProps } from '../ComponentTypes.models'

const meta: Meta<typeof Alert> = {
  title: 'Components/Alert',
  component: Alert,
  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-333&t=47NWXExemisHjPrj-0',
    },
    docs: {
      page: () => (
        <DocsTemplate
          figmaLink='https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-333&t=47NWXExemisHjPrj-0'
          description={
            <span>
              An <code>Alert</code> is system generated and contextual, and may
              appear without the user initiating an action. They can be
              dismissable. Generally, they appear within the page
              section/container.
            </span>
          }
          infoBullets={[
            <span key='first-line'>
              The <strong>information</strong> variant should provide additional
              information to the user in regards to the current context or
              action they are about to take.
            </span>,
            <span key='second-line'>
              The <strong>success</strong> variant should reaffirm to the user
              that a prior action they have taken, often in a different location
              within the application, has been successful.
            </span>,
            <span key='third-line'>
              The <strong>warning</strong> variant should be used to display
              cautious information that may need the user's attention but may
              not be critical.
            </span>,
            <span key='fourth-line'>
              The <strong>error</strong> variant should be used to alert the
              user about an error in the current/prior context that needs
              immediate attention.
            </span>,
          ]}
        />
      ),
    },
  },
}
export default meta

type Story = StoryObj<typeof Alert>

const Template: Story = {
  render: ({ ...args }) => <Alert {...args} />,
}

export const Success: Story = {
  ...Template,
  args: {
    type: 'success',
    text: 'This is an Alert!',
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertSuccess')
  },
}

export const Error: Story = {
  ...Template,
  args: {
    type: 'error',
    text: 'This is an Alert!',
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertError')
  },
}

export const Warning: Story = {
  ...Template,
  args: {
    type: 'warning',
    text: 'This is an Alert!',
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertWarning')
  },
}

export const Info: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertInfo')
  },
}

export const InfoWithClose: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
    close: {
      show: true,
      callout: () => {
        toast({ message: 'You clicked the close button!', type: 'info' })
      },
    },
  },
  play: async ({ canvas, userEvent }) => {
    const closeButton = canvas.getByRole('button')
    await userEvent.click(closeButton)
    await expect(
      canvas.getByText('You clicked the close button!'),
    ).toBeInTheDocument()
  },
}

export const CloseSuccessConfirmation: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
    close: {
      show: true,
      callout: () => {
        toast({ message: 'You clicked the close button!', type: 'info' })
      },
      confirmation: {
        type: 'green',
        header: 'Are you sure?',
        body: 'This will perform some action. Would you like to continue?',
        confirmCallout: () => {
          toast({ message: 'You did it!', type: 'success' })
        },
      },
    },
  },
}

export const CloseErrorConfirmation: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
    close: {
      show: true,
      callout: () => {
        toast({ message: 'You clicked the close button!', type: 'info' })
      },
      confirmation: {
        type: 'red',
        header: 'Are you sure?',
        body: 'This will perform some action. Would you like to continue?',
        confirmCallout: () => {
          toast({ message: 'You did it!', type: 'success' })
        },
      },
    },
  },
}

export const CloseInfoConfirmation: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
    close: {
      show: true,
      callout: () => {
        toast({ message: 'You clicked the close button!', type: 'info' })
      },
      confirmation: {
        type: 'blue',
        header: 'Are you sure?',
        body: 'This will perform some action. Would you like to continue?',
        confirmCallout: () => {
          toast({ message: 'You did it!', type: 'success' })
        },
      },
    },
  },
}

const buttons = [
  {
    as: 'link',
    to: '/',
    routerComponent: 'a',
    children: 'Link Button',
  },
  {
    children: 'Button',
    onClick: () => {
      toast({ message: 'You clicked the button!', type: 'success' })
    },
  },
] as [ButtonProps, ButtonProps?]

export const ButtonsAndClose: Story = {
  ...Template,
  args: {
    type: 'success',
    text: 'This is an Alert!',
    buttons,
    close: {
      show: true,
      callout: () => {
        toast({ message: 'You clicked the close button!', type: 'info' })
      },
    },
  },
  play: async ({ canvas }) => {
    await expect(canvas.getByText('This is an Alert!')).toBeInTheDocument()

    const linkButton = canvas.getByText('Link Button')
    const actionButton = canvas.getByText('Button')
    const xButton = canvas.getByTestId('icon-x')

    await expect(linkButton).toBeInTheDocument()
    await expect(actionButton).toBeInTheDocument()
    await expect(xButton).toBeInTheDocument()

    await userEvent.click(actionButton)
    // Check for toast message after action button click
    const toastAction = document.body.querySelector('.Toastify__toast')
    await expect(toastAction).toHaveTextContent('You clicked the button!')

    await userEvent.click(xButton)
    // Check for toast message after close button click
    await expect(
      screen.getByText('You clicked the close button!'),
    ).toBeInTheDocument()
  },
}

export const SuccessWithButtons: Story = {
  ...Template,
  args: {
    type: 'success',
    text: 'This is an Alert!',
    buttons,
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertSuccess')

    await expect(canvas.getByText('This is an Alert!')).toBeInTheDocument()

    const linkButton = canvas.getByText('Link Button')
    const actionButton = canvas.getByText('Button')

    await expect(linkButton).toBeInTheDocument()
    await expect(actionButton).toBeInTheDocument()

    await userEvent.click(actionButton)

    // Check for toast message after button click
    const toastEl = document.body.querySelector('.Toastify__toast')
    await expect(toastEl).toHaveTextContent('You clicked the button!')
  },
}

export const ErrorWithButtons: Story = {
  ...Template,
  args: {
    type: 'error',
    text: 'This is an Alert!',
    buttons,
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertError')

    await expect(canvas.getByText('This is an Alert!')).toBeInTheDocument()

    const linkButton = canvas.getByText('Link Button')
    const actionButton = canvas.getByText('Button')

    await expect(linkButton).toBeInTheDocument()
    await expect(actionButton).toBeInTheDocument()

    await userEvent.click(actionButton)

    // Check for toast message after button click
    const toastEl = document.body.querySelector('.Toastify__toast')
    await expect(toastEl).toHaveTextContent('You clicked the button!')
  },
}

export const WarningWithButtons: Story = {
  ...Template,
  args: {
    type: 'warning',
    text: 'This is an Alert!',
    buttons,
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertWarning')

    await expect(canvas.getByText('This is an Alert!')).toBeInTheDocument()

    const linkButton = canvas.getByText('Link Button')
    const actionButton = canvas.getByText('Button')

    await expect(linkButton).toBeInTheDocument()
    await expect(actionButton).toBeInTheDocument()

    await userEvent.click(actionButton)

    // Check for toast message after button click
    const toastEl = document.body.querySelector('.Toastify__toast')
    await expect(toastEl).toHaveTextContent('You clicked the button!')
  },
}

export const InfoWithButtons: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert!',
    buttons,
  },
  play: async ({ canvas }) => {
    const alertContainer = canvas.getByTestId('Alert')
    await expect(alertContainer).toBeInTheDocument()
    await expect(alertContainer?.className).toContain('alertInfo')

    await expect(canvas.getByText('This is an Alert!')).toBeInTheDocument()

    const linkButton = canvas.getByText('Link Button')
    const actionButton = canvas.getByText('Button')

    await expect(linkButton).toBeInTheDocument()
    await expect(actionButton).toBeInTheDocument()

    await userEvent.click(actionButton)

    // Check for toast message after confirming
    const toastEl = document.body.querySelector('.Toastify__toast')
    await expect(toastEl).toHaveTextContent('You clicked the button!')
  },
}

export const CustomIcon: Story = {
  ...Template,
  args: {
    type: 'info',
    text: 'This is an Alert with a custom icon!',
    customIcon: 'calendar',
  },
  play: async ({ canvas }) => {
    await expect(
      canvas.getByText('This is an Alert with a custom icon!'),
    ).toBeInTheDocument()

    // Test that the custom calendar icon is displayed
    const calendarIcon = canvas.getByTestId('icon-calendar')
    await expect(calendarIcon).toBeInTheDocument()
  },
}
