import type { Meta, StoryObj } from '@storybook/react'
import React from 'react'
import { viewports } from '../../utils/viewports'
import { Modal, ModalContent, ModalTitle } from '../Modal'
import { TransactionalModalTemplate } from './TransactionalModalTemplate'
import type { TransactionModalState } from './types'
import { initialState, reducer } from './useTransactionalModal'

const meta: Meta<typeof TransactionalModalTemplate> = {
  title: 'Blocks/TransactionalModal',
  component: TransactionalModalTemplate,
  parameters: {
    chromatic: { viewports: viewports.all },
    layout: 'centered',
  },
}

export default meta

type Story = StoryObj<typeof TransactionalModalTemplate>

const baseState: TransactionModalState = {
  currentStepIndex: 1,
  nextStepIndex: 2,
  error: undefined,
  isTransactionComplete: false,
  progressBarSteps: [
    { label: 'Label', status: 'DONE' },
    { label: 'Label', status: 'ACTIVE' },
    { label: 'Label', status: 'PENDING' },
  ],
  steps: [
    { id: 'step-1', label: 'Initiating' },
    {
      id: 'step-2',
      label: 'Transaction title',
      description: 'Transaction description',
    },
    { id: 'step-3', label: 'Completed' },
  ],
  successHeading: 'Transaction complete',
  successBody: 'Everything was processed.',
  context: 'transaction-modal',
  closeButtonText: 'Close',
}

const txHash = '012378E2f3b02dCC8A00c420b99Ae06a474A1327'

const closeHiddenState: TransactionModalState = {
  ...baseState,
  steps: baseState.steps.map((step) =>
    step.id === 'step-2' ? { ...step, isCloseHidden: true } : step,
  ),
}

const longStepLabelsState: TransactionModalState = {
  ...baseState,
  currentStepIndex: 1,
  nextStepIndex: 2,
  progressBarSteps: [
    { label: 'Approve registration request cancellation', status: 'DONE' },
    { label: 'Receive Log Trigger upkeep edit confirmation', status: 'ACTIVE' },
    { label: 'Await native token transfer confirmation', status: 'PENDING' },
  ],
  steps: [
    { id: 'step-1', label: 'Approve registration request cancellation' },
    {
      id: 'step-2',
      label: 'Receive Log Trigger upkeep edit confirmation',
      description:
        'Waiting for on-chain confirmation for the requested operation.',
    },
    { id: 'step-3', label: 'Await native token transfer confirmation' },
  ],
}

const singleTransactionHashOnlyState: TransactionModalState = {
  ...baseState,
  transactions: [{ hash: txHash }],
}

const typedTransactionsState: TransactionModalState = {
  ...baseState,
  transactions: [
    { hash: txHash, type: '10 Testnet ETH' },
    { hash: txHash, type: '10 Testnet LINK' },
  ],
  successLinkText: 'View transaction',
  successLinkHref: '/details',
}

const successWithMultipleTransactionsState: TransactionModalState = {
  ...typedTransactionsState,
  isTransactionComplete: true,
  currentStepIndex: 2,
  progressBarSteps: [
    { label: 'Label', status: 'DONE' },
    { label: 'Label', status: 'DONE' },
    { label: 'Label', status: 'DONE' },
  ],
  successHeading: 'Transaction title',
  successBody: 'Transaction description',
}

const renderTemplate = (
  state: TransactionModalState,
  isInescapable = false,
  {
    onCloseClick,
    onSuccessClick,
  }: {
    onCloseClick?: VoidFunction
    onSuccessClick?: VoidFunction
  } = {},
) => (
  <Modal open>
    <ModalContent showCloseButton={false} size="lg">
      <ModalTitle className="sr-only">Transactional Modal</ModalTitle>
      <TransactionalModalTemplate
        state={state}
        networkExplorerTxUrl="https://example-explorer.com/tx/{resourceId}"
        onSuccessClick={onSuccessClick ?? (() => undefined)}
        onCloseClick={onCloseClick ?? (() => undefined)}
        stepId={state.steps[state.currentStepIndex]?.id ?? 'step'}
        contextId={state.context}
        isInescapable={isInescapable}
      />
    </ModalContent>
  </Modal>
)

const animatedTransactionConfig = {
  steps: [
    {
      id: 'approve-registration',
      label: 'Approve upkeep registration',
      description:
        'Confirm the LINK transfer and upkeep registration in your wallet.',
    },
    {
      id: 'wait-confirmation',
      label: 'Receive onchain confirmation',
      description:
        'Waiting for the registry and billing transactions to be confirmed.',
    },
    {
      id: 'sync-dashboard',
      label: 'Sync dashboard state',
      description:
        'Refreshing your upkeep details so the new registration appears in the UI.',
    },
  ],
  successHeading: 'Upkeep registration complete',
  successBody:
    'Your upkeep is now registered and the billing transactions were confirmed successfully.',
  context: 'storybook-animated-transaction',
}

const getAnimatedInitialState = () =>
  reducer(initialState, {
    type: 'START_TRANSACTION',
    ...animatedTransactionConfig,
  })

const AnimatedFlowTemplate = () => {
  const [state, dispatch] = React.useReducer(
    reducer,
    undefined,
    getAnimatedInitialState,
  )
  const [runId, setRunId] = React.useState(0)

  React.useEffect(() => {
    dispatch({ type: 'START_TRANSACTION', ...animatedTransactionConfig })

    const showSignedTransactions = setTimeout(() => {
      dispatch({
        type: 'NEXT_STEP',
        transactions: [
          { hash: txHash, type: '5 LINK billing approval' },
          { hash: `${txHash}9`, type: 'Automation upkeep registration' },
        ],
      })
    }, 1500)

    const finishFlow = setTimeout(() => {
      dispatch({
        type: 'COMPLETE_TRANSACTION',
        successLinkText: 'View upkeep',
        successLinkHref: '/automation/upkeeps/123',
        closeButtonText: 'Animate Again',
      })
    }, 3200)

    return () => {
      clearTimeout(showSignedTransactions)
      clearTimeout(finishFlow)
    }
  }, [runId])

  return renderTemplate(state, true, {
    onCloseClick: () => {
      if (state.isTransactionComplete) {
        setRunId((currentRunId) => currentRunId + 1)
      }
    },
  })
}

export const Default: Story = {
  render: () =>
    renderTemplate({
      ...baseState,
      transactions: [
        { hash: txHash, type: 'Request' },
        { hash: txHash, type: 'Request' },
      ],
      successLinkText: 'Label',
      successLinkHref: '/details',
    }),
}

export const DefaultInescapable: Story = {
  render: () =>
    renderTemplate(
      {
        ...baseState,
        transactions: [{ hash: txHash, type: 'Request' }],
      },
      true,
    ),
}

export const DefaultCloseHidden: Story = {
  render: () =>
    renderTemplate({
      ...closeHiddenState,
      transactions: [
        { hash: txHash, type: 'Request' },
        { hash: txHash, type: 'Request' },
      ],
      successLinkText: 'Label',
      successLinkHref: '/details',
    }),
}

export const ErrorState: Story = {
  render: () =>
    renderTemplate({
      ...baseState,
      error: 'Transaction failed.',
      progressBarSteps: [
        { label: 'Label', status: 'DONE' },
        { label: 'Label', status: 'ERROR' },
        { label: 'Label', status: 'PENDING' },
      ],
      transactions: [{ hash: txHash, type: 'Request' }],
    }),
}

export const SuccessState: Story = {
  render: () =>
    renderTemplate({
      ...successWithMultipleTransactionsState,
      successLinkText: 'Label',
      successLinkHref: '/details',
    }),
}

export const LongStepLabels: Story = {
  render: () =>
    renderTemplate({
      ...longStepLabelsState,
      transactions: [{ hash: txHash, type: 'Request' }],
      successLinkText: 'Label',
      successLinkHref: '/details',
    }),
}

export const SingleTransactionHashOnly: Story = {
  render: () => renderTemplate(singleTransactionHashOnlyState),
}

export const SingleTransactionHashOnlyInescapable: Story = {
  render: () =>
    renderTemplate(
      {
        ...closeHiddenState,
        transactions: [{ hash: txHash }],
      },
      true,
    ),
}

export const ErrorWithTransactionType: Story = {
  render: () =>
    renderTemplate({
      ...typedTransactionsState,
      error: 'Something went real bad...',
      progressBarSteps: [
        { label: 'Label', status: 'DONE' },
        { label: 'Label', status: 'ERROR' },
        { label: 'Label', status: 'PENDING' },
      ],
    }),
}

export const SuccessStateTerminal: Story = {
  render: () => renderTemplate(successWithMultipleTransactionsState, true),
}

export const AnimatedFlow: Story = {
  parameters: {
    chromatic: { disableSnapshot: true },
  },
  render: () => <AnimatedFlowTemplate />,
}
