import type { Meta, StoryObj } from '@storybook/react'
import * as React from 'react'
import { within, userEvent, expect } from 'storybook/test'
import { SvgPasswordBlock, SvgUserCircleSingle } from '@chainlink/blocks-icons'
import { createSizeDecorator } from '../../utils/decorators'
import { Card } from '../Card'
import { Field, FieldLabel, FieldHelper } from '../Field'
import { FieldInput } from './FieldInput'
import { INPUT_SIZE_OPTIONS, INPUT_WIDTH_OPTIONS } from './Input'

const FIELD_INPUT_TYPE_OPTIONS = [
  'text',
  'password',
  'email',
  'number',
  'tel',
  'url',
  'search',
] satisfies React.HTMLInputTypeAttribute[]

const meta = {
  title: 'Form/Input/FieldInput',
  component: FieldInput,
  decorators: [createSizeDecorator('XS')],
  argTypes: {
    width: {
      control: 'select',
      options: INPUT_WIDTH_OPTIONS,
      table: {
        type: {
          summary: INPUT_WIDTH_OPTIONS.map((value) => value).join(' | '),
        },
        defaultValue: { summary: 'responsive' },
      },
    },
    size: {
      control: {
        type: 'select',
      },
      options: INPUT_SIZE_OPTIONS,
      table: {
        type: { summary: INPUT_SIZE_OPTIONS.map((value) => value).join(' | ') },
        defaultValue: { summary: 'default' },
      },
    },
    type: {
      control: 'select',
      options: FIELD_INPUT_TYPE_OPTIONS,
      defaultValue: 'text',
      description: 'Specifies the type of the input element.',
      table: {
        type: { summary: 'string' },
        defaultValue: { summary: 'text' },
      },
    },
    placeholder: {
      control: 'text',
      description: 'Placeholder text for the input field.',
      table: {
        type: { summary: 'string' },
      },
    },
    disabled: {
      control: 'boolean',
      defaultValue: false,
      description: 'Disables the input if set to true.',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    isLoading: {
      control: 'boolean',
      defaultValue: false,
      description: 'Shows a loading spinner and disables other state icons.',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    isValid: {
      control: 'boolean',
      defaultValue: false,
      description: 'Shows a valid checkmark icon.',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    isInvalid: {
      control: 'boolean',
      defaultValue: false,
      description: 'Shows an invalid error icon.',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },

    required: {
      control: 'boolean',
      defaultValue: false,
      description: 'Marks the input as required.',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    clearable: {
      control: 'boolean',
      description:
        'When false, the hover clear control is not shown (default true).',
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'true' },
      },
    },
  },
} satisfies Meta<typeof FieldInput>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
  render: (args) => <FieldInput {...args} />,
  args: {
    placeholder: 'Placeholder',
    type: 'text',
    clearable: true,
  },
}

export const NotClearable: Story = {
  render: (args) => (
    <Field size="default">
      <FieldLabel>Read-only style value</FieldLabel>
      <FieldInput {...args} />
    </Field>
  ),
  args: {
    defaultValue: 'Value without hover clear',
    clearable: false,
  },
  parameters: {
    docs: {
      description: {
        story:
          'Set clearable to false when the field value should not expose the hover clear action.',
      },
    },
  },
  play: async ({ canvasElement }) => {
    await expect(
      canvasElement.querySelector('[aria-label="Clear input"]'),
    ).toBeNull()
  },
}

export const Small: Story = {
  render: (args) => (
    <Field size="sm">
      <FieldLabel>Username</FieldLabel>
      <FieldInput {...args} placeholder="Enter username" />
    </Field>
  ),
}

export const LeftIcon: Story = {
  render: (args) => (
    <FieldInput {...args} placeholder="Enter username">
      <SvgUserCircleSingle />
    </FieldInput>
  ),
}

export const Disabled: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Disabled Input</FieldLabel>
      <FieldInput {...args} placeholder="This input is disabled" />
    </Field>
  ),
  args: {
    disabled: true,
    type: 'text',
  },
}

export const WithError: Story = {
  render: (args) => <FieldInput {...args} />,
  args: {
    error: true,
  },
}
export const WithErrorMessage: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Email Address</FieldLabel>
      <FieldInput {...args} placeholder="you@example.com" />
    </Field>
  ),
  args: {
    type: 'email',
    error: 'Please enter a valid email address.',
  },
}

export const WithErrorMessageAndLeftIcon: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Email Address</FieldLabel>
      <FieldInput {...args} placeholder="you@example.com">
        <SvgUserCircleSingle />
      </FieldInput>
    </Field>
  ),
  args: {
    type: 'email',
    error: 'Please enter a valid email address.',
  },
}

export const LoadingState: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Search</FieldLabel>
      <FieldInput {...args} placeholder="Searching..." />
    </Field>
  ),
  args: {
    isLoading: true,
    type: 'search',
  },
}

export const ValidState: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Email Address</FieldLabel>
      <FieldHelper>Email address is valid!</FieldHelper>
      <FieldInput {...args} placeholder="you@example.com" />
    </Field>
  ),
  args: {
    type: 'email',
    isValid: true,
    value: 'user@example.com',
  },
}

export const InvalidState: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Email Address</FieldLabel>
      <FieldInput
        {...args}
        defaultValue="invalid-email"
        placeholder="you@example.com"
      />
    </Field>
  ),
  args: {
    type: 'email',
    isInvalid: true,
  },
}

export const Number: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Age</FieldLabel>
      <FieldHelper>Must be 18 or older</FieldHelper>
      <FieldInput {...args} placeholder="Enter your age" />
    </Field>
  ),
  args: {
    type: 'number',
    min: 18,
  },
}

export const Email: Story = {
  render: (args) => (
    <Field>
      <FieldLabel>Email Address</FieldLabel>
      <FieldHelper>
        We&apos;ll use this to contact you about your account.
      </FieldHelper>
      <FieldInput {...args} placeholder="Enter your email" />
    </Field>
  ),
  args: {
    type: 'email',
    autoComplete: 'email',
  },
}

export const Widths: Story = {
  render: (args) => (
    <Card className="flex min-w-[360px] flex-col gap-4 p-6">
      <Field>
        <FieldLabel>Responsive Width (default)</FieldLabel>
        <FieldInput
          {...args}
          width="responsive"
          placeholder="Responsive input"
        />
      </Field>
      <Field>
        <FieldLabel>Full Width</FieldLabel>
        <FieldInput {...args} width="full" placeholder="Full width input" />
      </Field>
      <Field>
        <FieldLabel>Hug Content</FieldLabel>
        <FieldInput {...args} width="hug" placeholder="Hug content" />
      </Field>
    </Card>
  ),
  args: {
    type: 'text',
  },
}

export const Clearable: Story = {
  render: (args) => {
    function ClearableDemo() {
      const [value, setValue] = React.useState('Hover to see clear button')

      return (
        <Field>
          <FieldLabel>Clearable Input</FieldLabel>
          <FieldHelper>
            Hover over the input to see the clear button
          </FieldHelper>
          <FieldInput
            {...args}
            placeholder="Type something to see clear button"
            value={value}
            onChange={(e) => setValue(e.target.value)}
          />
        </Field>
      )
    }

    return <ClearableDemo />
  },
}

export const PasswordHidden: Story = {
  render: (args) => {
    return (
      <Field>
        <FieldLabel>Password</FieldLabel>
        <FieldHelper>
          Type in the password field to see the show/hide toggle icon
        </FieldHelper>
        <FieldInput
          {...args}
          type="password"
          placeholder="Enter your password"
        />
      </Field>
    )
  },
  args: {
    type: 'password',
    defaultValue: 'password123',
  },
}

export const PasswordShown: Story = {
  render: (args) => {
    return (
      <Field>
        <FieldLabel>Password</FieldLabel>
        <FieldHelper>
          Password is shown (toggle button was clicked automatically)
        </FieldHelper>
        <FieldInput
          {...args}
          type="password"
          placeholder="Enter your password"
        />
      </Field>
    )
  },
  args: {
    type: 'password',
    defaultValue: 'password123',
  },
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement)

    // Wait for the password toggle button to appear
    const toggleButton = await canvas.findByRole('button', {
      name: /show password/i,
    })

    // Click the toggle button to show the password
    await userEvent.click(toggleButton)
  },
}

export const PasswordWithLeftIcon: Story = {
  render: (args) => {
    return (
      <Field>
        <FieldLabel>Password with Left Icon</FieldLabel>
        <FieldHelper>
          Type in the password field to see the show/hide toggle icon
        </FieldHelper>
        <FieldInput {...args} type="password" placeholder="Enter your password">
          <SvgPasswordBlock />
        </FieldInput>
      </Field>
    )
  },
  args: {
    type: 'password',
    defaultValue: 'password123',
  },
}

export const PasswordWithLeftIconSmall: Story = {
  render: (args) => {
    return (
      <Field size="sm">
        <FieldLabel>Password with Left Icon</FieldLabel>
        <FieldHelper>
          Type in the password field to see the show/hide toggle icon
        </FieldHelper>
        <FieldInput {...args} type="password" placeholder="Enter your password">
          <SvgPasswordBlock />
        </FieldInput>
      </Field>
    )
  },
  args: {
    type: 'password',
    defaultValue: 'password123',
  },
}
