import type { Meta, StoryObj } from '@storybook/react-vite'
import { useState } from 'react'

import { Input } from './input'
import { expect, userEvent, screen } from 'storybook/test'
import { Button } from '@components/ui/button/button'

const meta = {
  title: 'Input',
  component: Input,
  tags: ['autodocs'],
  parameters: {
    layout: 'centered',
  },
  argTypes: {
    variant: {
      control: 'select',
      options: ['default', 'simple'],
    },
  },
} satisfies Meta<typeof Input>
export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
  args: { variant: 'default' },
  render: (args) => {
    const [value, setValue] = useState('')
    return (
      <div className="flex items-center gap-2">
        <Input
          placeholder="Enter text..."
          {...args}
          value={value}
          onChange={(e) => setValue(e.target.value)}
          className="w-[200px]"
        />
        <span data-testid="input-value">
          {value ? 'value: ' : ''}
          {value}
        </span>
      </div>
    )
  },
  play: async () => {
    const input = screen.getByPlaceholderText('Enter text...')
    await userEvent.type(input, 'test')
    const valueSpan = screen.getByTestId('input-value')
    expect(valueSpan).toHaveTextContent('test')
  },
}

export const Variants: Story = {
  render: () => (
    <div className="flex flex-wrap gap-2 items-center">
      <Input placeholder="default" variant="default" className="w-48" />
      <Input placeholder="simple" variant="simple" className="w-48" />
    </div>
  ),
}

export const Disabled: Story = {
  render: (args) => (
    <div className="flex flex-wrap gap-4 items-center">
      <Input disabled {...args} className="w-[200px]" placeholder="Disabled" />
    </div>
  ),
}

export const EmailForm: Story = {
  render: () => {
    const [value, setValue] = useState('')
    const [error, setError] = useState<string | null>(null)
    const [submitted, setSubmitted] = useState(false)
    const [touched, setTouched] = useState(false)

    function validateEmail(email: string) {
      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
    }

    function validate(value: string) {
      if (!value) return 'Field is required.'
      if (!validateEmail(value)) return 'Not a valid email.'
      return null
    }

    const handleSubmit = (e: React.FormEvent) => {
      e.preventDefault()
      setSubmitted(true)
      setError(validate(value))
    }

    const handleBlur = () => {
      setTouched(true)
      setError(validate(value))
    }

    return (
      <form className="flex flex-col gap-2 items-center w-[350px]" onSubmit={handleSubmit} noValidate>
        <Input
          className="w-full"
          placeholder="Enter an email..."
          value={value}
          onChange={(e) => {
            setValue(e.target.value)
            if (submitted || touched) setError(validate(e.target.value))
          }}
          onBlur={handleBlur}
          aria-invalid={!!error}
        />
        {error && (touched || submitted) && (
          <span className="text-destructive mt-1" role="alert">
            {error}
          </span>
        )}
        <Button type="submit" size="smLow">
          Submit
        </Button>
      </form>
    )
  },
  play: async () => {
    const input = screen.getByPlaceholderText('Enter an email...')
    const submitButton = screen.getByRole('button', { name: /submit/i })

    // Submit with empty input
    await userEvent.clear(input)
    await userEvent.click(submitButton)
    await expect(await screen.findByRole('alert')).toHaveTextContent('Field is required.')
    // Enter invalid email and submit
    await userEvent.type(input, 'not-an-email')
    await userEvent.click(submitButton)
    await expect(await screen.findByRole('alert')).toHaveTextContent('Not a valid email.')
    // Enter valid email and submit
    await userEvent.clear(input)
    await userEvent.type(input, 'test@example.com')
    await userEvent.click(submitButton)
    await expect(screen.queryByRole('alert')).toBeNull()
  },
}
