import React, { useState } from 'react'
import { ComponentSlotsProvider } from '../component-slots'
import { Input } from '../inputs'
import { Button } from '../button'
import { View } from '../view'
import {
  Fields,
  applyFieldChange,
  FIELD_TYPES,
  DEFAULT_FORM_FIELD_SLOTS,
} from './index.js'

const mutedTextStyle = {
  fontSize: 14,
  color: 'color-mix(in srgb, var(--text-default-color, CanvasText) 72%, transparent)',
  marginBottom: 'var(--space-m)',
}

const dataPreviewStyle = {
  margin: 0,
  padding: 'var(--space-s)',
  background: 'var(--color-secondary)',
  color: 'var(--text-default-color, CanvasText)',
  borderRadius: 'var(--space-xs)',
  border: '1px solid var(--separator-primary)',
  fontSize: 12,
  overflow: 'auto',
}

export default {
  title: 'Design System/Forms/Fields',
  component: Fields,
  parameters: {
    layout: 'fullscreen',
    docs: {
      story: {
        inline: true,
        height: 'auto',
      },
    },
  },
}

const shell = (story, initial = {}) => {
  const Shell = () => {
    const [data, setData] = useState(initial)
    return (
      <View
        surface="primary"
        inset="m"
        roundness="m"
        gap="m"
        style={{ maxWidth: 480, fontFamily: 'system-ui, sans-serif' }}
      >
        {story(data, e => setData(prev => applyFieldChange(prev, e)))}
        <pre style={dataPreviewStyle}>{JSON.stringify(data, null, 2)}</pre>
      </View>
    )
  }
  return <Shell />
}

export const AllAllowedTypes = () =>
  shell((data, onChange) => (
    <>
      <p style={mutedTextStyle}>
        Allowed API types: {FIELD_TYPES.join(', ')}
      </p>
      <Fields
        data={data}
        onChange={onChange}
        fields={[
          { name: 'Title', type: 'text', required: true },
          { name: 'Summary', type: 'textarea' },
          { name: 'Body', type: 'richtext' },
          { name: 'Count', type: 'number' },
          { name: 'Kind', type: 'select', options: ['A', 'B', 'C'] },
          { name: 'Tags', type: 'multiselect', options: ['x', 'y', 'z'] },
          { name: 'Hero', type: 'file', accept: 'image/*' },
          { name: 'Attachments', type: 'file', max: 3 },
          { name: 'Cover', type: 'image' },
          { name: 'Published', type: 'boolean' },
          { name: 'Start date', type: 'date' },
          { name: 'Vacation', type: 'date-range' },
          { name: 'Blackouts', type: 'date-ranges' },
        ]}
      />
    </>
  ), {
    Title: 'Example',
    Kind: 'B',
    Tags: ['x'],
    Published: false,
    'Start date': Date.parse('2025-01-15T00:00:00.000Z'),
    Vacation: { start: Date.parse('2025-07-01T00:00:00.000Z'), end: Date.parse('2025-07-14T00:00:00.000Z') },
    Blackouts: [
      { start: Date.parse('2025-12-24T00:00:00.000Z'), end: Date.parse('2025-12-26T00:00:00.000Z') },
    ],
  })

export const Text = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Label', type: 'text' }]} />
    ),
    { Label: 'Hello' },
  )

export const Textarea = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Notes', type: 'textarea' }]}
      />
    ),
    { Notes: 'Multi\nline' },
  )

export const Richtext = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Article', type: 'richtext' }]} />
    ),
    { Article: '# Heading\n\nParagraph.' },
  )

export const Number = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Amount', type: 'number' }]} />
    ),
    { Amount: 42 },
  )

export const Select = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Choice', type: 'select', options: ['One', 'Two', 'Three'] }]}
      />
    ),
    { Choice: 'Two' },
  )

export const MultiselectTags = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[
          {
            name: 'Skills',
            type: 'multiselect',
            options: ['React', 'Design', 'Writing'],
          },
        ]}
      />
    ),
    { Skills: ['React', 'Custom skill'] },
  )

export const File = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Attachment', type: 'file', accept: '.pdf,image/*' }]}
      />
    ),
    {},
  )

export const FileMulti = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Gallery', type: 'file', accept: 'image/*', max: 3 }]}
      />
    ),
    { Gallery: [{ resourceId: 'mock-res-1' }] },
  )

export const Image = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Cover', type: 'image' }]} />
    ),
    {},
  )

const MockUploadFileField = ({ name, onChange }) => (
  <Button
    type="button"
    variant="neutral"
    onClick={() =>
      onChange({
        target: {
          name,
          id: name,
          dataset: { ossyFileResourceReplace: 'true' },
          value: JSON.stringify({ resourceId: 'storybook-mock-resource' }),
        },
      })
    }
  >
    Mock upload
  </Button>
)

/** Mock `@ossy/design-system/input/file` via component slots. */
export const FileWithMockPlatformSlot = () => {
  const Shell = () => {
    const [data, setData] = useState({})
    return (
      <View
        surface="primary"
        inset="m"
        roundness="m"
        gap="m"
        style={{ maxWidth: 480, fontFamily: 'system-ui, sans-serif' }}
      >
        <ComponentSlotsProvider
          slots={{
            ...DEFAULT_FORM_FIELD_SLOTS,
            '@ossy/design-system/input/file': MockUploadFileField,
          }}
        >
          <Fields
            data={data}
            onChange={e => setData(prev => applyFieldChange(prev, e))}
            fields={[{ name: 'Avatar', type: 'file', accept: 'image/*' }]}
          />
        </ComponentSlotsProvider>
        <pre style={dataPreviewStyle}>{JSON.stringify(data, null, 2)}</pre>
      </View>
    )
  }
  return <Shell />
}

export const Boolean = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Agree', type: 'boolean' }]} />
    ),
    { Agree: true },
  )

export const DateField = () =>
  shell(
    (data, onChange) => (
      <Fields data={data} onChange={onChange} fields={[{ name: 'Due', type: 'date' }]} />
    ),
    { Due: '2026-06-01' },
  )

DateField.storyName = 'Date'

export const DateRange = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Vacation', type: 'date-range' }]}
      />
    ),
    {
      Vacation: {
        start: Date.parse('2025-07-01T00:00:00.000Z'),
        end: Date.parse('2025-07-14T00:00:00.000Z'),
      },
    },
  )

export const DateRanges = () =>
  shell(
    (data, onChange) => (
      <Fields
        data={data}
        onChange={onChange}
        fields={[{ name: 'Blackouts', type: 'date-ranges' }]}
      />
    ),
    {
      Blackouts: [
        {
          start: Date.parse('2025-12-24T00:00:00.000Z'),
          end: Date.parse('2025-12-26T00:00:00.000Z'),
        },
        {
          start: Date.parse('2026-01-01T00:00:00.000Z'),
          end: Date.parse('2026-01-02T00:00:00.000Z'),
        },
      ],
    },
  )

const TomatoTextField = ({ label, value, onChange, style = {}, ...rest }) => (
  <Input
    {...rest}
    id={label}
    type="text"
    value={value ?? ''}
    onChange={onChange}
    style={{
      minWidth: '50%',
      ...style,
      borderColor: 'tomato',
      borderWidth: 2,
      borderStyle: 'solid',
    }}
  />
)

/** Override `@ossy/design-system/input/text` via component slots. */
export const SlotOverrideFormFieldText = () => {
  const Shell = () => {
    const [data, setData] = useState({ Title: 'Custom slot' })
    return (
      <View
        surface="primary"
        inset="m"
        roundness="m"
        gap="m"
        style={{ maxWidth: 480, fontFamily: 'system-ui, sans-serif' }}
      >
        <p style={{ ...mutedTextStyle, marginBottom: 'var(--space-s)' }}>
          <code>@ossy/design-system/input/text</code> uses a custom component registered on that
          slot key.
        </p>
        <ComponentSlotsProvider
          slots={{
            ...DEFAULT_FORM_FIELD_SLOTS,
            '@ossy/design-system/input/text': TomatoTextField,
          }}
        >
          <Fields
            data={data}
            onChange={e => setData(prev => applyFieldChange(prev, e))}
            fields={[{ name: 'Title', type: 'text', required: true }]}
          />
        </ComponentSlotsProvider>
        <pre style={dataPreviewStyle}>{JSON.stringify(data, null, 2)}</pre>
      </View>
    )
  }
  return <Shell />
}
