import {
  Canvas,
  Controls,
  Meta,
  Story,
  Title,
  Subtitle,
} from '@storybook/addon-docs/blocks'
import * as FieldInputPrimitivesStories from './FieldInputPrimitives.stories'
import { LifecycleTag } from '../../docs/components'

<Meta title="Form/FieldInput/Primitives" of={FieldInputPrimitivesStories} />

<Title>FieldInput Primitives</Title>
<Subtitle>
  Composable input components that can be assembled together for custom input
  layouts with icons, actions, and state indicators.
</Subtitle>

<LifecycleTag variant="In Development" />

<Canvas of={FieldInputPrimitivesStories.Default} sourceState="shown" />

## Components

The FieldInput primitive family consists of the following components:

- `FieldInputRoot`: The container component that provides context to all child components. Manages state, handles input changes, and coordinates between sub-components.
- `FieldInputIcon`: Renders an icon on the left side of the input. Automatically positions and sizes based on context.
- `FieldInputControl`: The actual input element. Consumes context for size, type, error state, and change handlers.
- `FieldInputAction`: Renders content on the right side of the input. By default shows state indicators (loading, valid, invalid, clear), but can render custom actions like buttons.

## Import

```tsx
import {
  FieldInputRoot,
  FieldInputIcon,
  FieldInputControl,
  FieldInputAction,
} from '@chainlink/blocks'
```

## Usage

### Basic Composition

```tsx
import {
  FieldInputRoot,
  FieldInputIcon,
  FieldInputControl,
  FieldInputAction,
} from '@chainlink/blocks'
import { SvgCoinsStack } from '@chainlink/blocks-icons'

export function MyInput() {
  const [value, setValue] = React.useState('')

  return (
    <FieldInputRoot
      type="text"
      value={value}
      onChange={(e) => setValue(e.target.value)}
    >
      <FieldInputIcon>
        <SvgCoinsStack />
      </FieldInputIcon>
      <FieldInputControl placeholder="Enter amount" />
      <FieldInputAction />
    </FieldInputRoot>
  )
}
```

### Custom Action

Custom actions like buttons or tags can be rendered instead of the default state indicators:

```tsx
import { Tag } from '@chainlink/blocks'

export function InputWithMaxButton() {
  return (
    <form>
      <FieldInputRoot type="number" name="amount">
        <FieldInputIcon>
          <SvgCoinsStack />
        </FieldInputIcon>
        <FieldInputControl placeholder="Enter amount" />
        <FieldInputAction>
          <Tag
            variant="muted"
            size="sm"
            className="cursor-pointer"
            onClick={(e) => {
              const input = e.currentTarget
                .closest('form')
                ?.querySelector('input')
              if (input) {
                input.value = '1000'
              }
            }}
          >
            Max
          </Tag>
        </FieldInputAction>
      </FieldInputRoot>
    </form>
  )
}
```

### Custom Clear Handler

The `FieldInputAction` supports a composition pattern for the clear handler, allowing you to add custom logic while preserving the default clear behavior:

```tsx
export function InputWithCustomClear() {
  const [value, setValue] = React.useState('')
  const [searchResults, setSearchResults] = React.useState([])

  return (
    <FieldInputRoot
      type="search"
      value={value}
      onChange={(e) => setValue(e.target.value)}
    >
      <FieldInputControl placeholder="Search..." />
      <FieldInputAction
        onClear={(clearInput) => {
          // Your custom logic
          setSearchResults([])
          trackEvent('search_cleared')

          // Call the default clear
          clearInput()
        }}
      />
    </FieldInputRoot>
  )
}
```

### Preventing Default Clear

You can prevent the input from being cleared based on conditions:

```tsx
export function InputWithConfirmation() {
  const [value, setValue] = React.useState('')
  const [hasUnsavedChanges, setHasUnsavedChanges] = React.useState(false)

  return (
    <FieldInputRoot
      type="text"
      value={value}
      onChange={(e) => {
        setValue(e.target.value)
        setHasUnsavedChanges(true)
      }}
    >
      <FieldInputControl placeholder="Enter text..." />
      <FieldInputAction
        onClear={(clearInput) => {
          if (hasUnsavedChanges) {
            // Show confirmation dialog
            if (confirm('Clear unsaved changes?')) {
              clearInput()
              setHasUnsavedChanges(false)
            }
            // Don't call clearInput() - prevents clearing
          } else {
            clearInput()
          }
        }}
      />
    </FieldInputRoot>
  )
}
```

## State Indicators

The `FieldInputAction` component automatically displays state indicators when no custom children are provided:

- **Loading**: Shows a loading spinner when `isLoading` prop is true
- **Valid**: Shows a checkmark when `isValid` prop is true
- **Invalid**: Shows an error icon that clears the input when clicked
- **Clear**: Shows a clear button on hover when input has a value
- **Password Toggle**: Automatically shows for password inputs

```tsx
<FieldInputRoot type="password" error={error}>
  <FieldInputControl placeholder="Password" />
  <FieldInputAction
    isLoading={isValidating}
    isValid={isPasswordValid}
    isInvalid={!!error}
  />
</FieldInputRoot>
```

## Error Handling

Error messages are automatically displayed when the `error` prop contains a string:

```tsx
<FieldInputRoot
  type="email"
  value={email}
  onChange={(e) => setEmail(e.target.value)}
  error={emailError}
>
  <FieldInputControl placeholder="email@example.com" />
  <FieldInputAction />
</FieldInputRoot>
```

## Examples

### With Max Button (uncontrolled)

A number input with a custom "Max" button that fills in the maximum allowed value.

<Canvas of={FieldInputPrimitivesStories.WithMaxButton} />

```tsx
export function InputWithMaxButton() {
  return (
    <form>
      <FieldInputRoot type="number" name="amount">
        <FieldInputIcon>
          <SvgCoinsStack />
        </FieldInputIcon>
        <FieldInputControl placeholder="Enter amount" />
        <FieldInputAction>
          <Tag
            variant="muted"
            size="sm"
            className="cursor-pointer"
            onClick={(e) => {
              const input = e.currentTarget
                .closest('form')
                ?.querySelector('input')
              if (input) {
                input.value = '10000'
              }
            }}
          >
            Max
          </Tag>
        </FieldInputAction>
      </FieldInputRoot>
    </form>
  )
}
```

### With Max Button And Invalid State (controlled)

A controlled example where the "Max" button fills in the maximum allowed value, and an error message is displayed when the input exceeds the allowed range.

<Canvas of={FieldInputPrimitivesStories.WithMaxButtonAndInvalidState} />

```tsx
export function InputWithMaxAndValidation() {
  const [value, setValue] = React.useState('50000')
  const maxValue = '1000'
  const error =
    parseFloat(value) > parseFloat(maxValue)
      ? `Amount cannot exceed ${maxValue}`
      : undefined

  return (
    <FieldInputRoot
      type="number"
      error={error}
      value={value}
      onChange={(e) => setValue(e.target.value)}
    >
      <FieldInputIcon>
        <SvgCoinsStack />
      </FieldInputIcon>
      <FieldInputControl placeholder="Enter amount" />
      <FieldInputAction isInvalid={!!error}>
        <Tag
          variant="muted"
          size="sm"
          className="cursor-pointer"
          onClick={() => setValue(maxValue)}
        >
          Max
        </Tag>
      </FieldInputAction>
    </FieldInputRoot>
  )
}
```
