import { useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';

import { Divider } from '@mui/material';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { type Meta, type StoryObj } from '@storybook/react-vite';

import FormInputTimeRange from './form';
import { type FormInputTimeRangeProps, type TimeRangeValue } from './types';
import InputTimeRange from '.';

const meta: Meta<typeof InputTimeRange> = {
  component: InputTimeRange,
  title: 'Design System/Inputs/TimeRange',
  tags: ['autodocs'],
  parameters: {
    docs: {
      description: {
        component:
          'Two `InputTime` fields connected by a translated separator ("to" / "a"). ' +
          'Shares a single label, helper text, and error state across both inputs. ' +
          'Value is a tuple `[Date | null, Date | null]`. Includes a `FormInputTimeRange` ' +
          'variant for react-hook-form integration.',
      },
    },
  },
  argTypes: {
    value: {
      description: 'Tuple of start and end times.',
      control: false,
      table: { type: { summary: '[Date | null, Date | null]' } },
    },
    onChange: {
      description: 'Callback fired when either time changes.',
      control: false,
      table: { type: { summary: '(value: TimeRangeValue) => void' } },
    },
    label: {
      description: 'Label displayed above both inputs.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    helperText: {
      description: 'Helper text shown below the inputs.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    errorText: {
      description: 'Error message shown when `error` is true.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    error: {
      description: 'Applies error styling to both inputs.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    disabled: {
      description: 'Disables both inputs.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    fullWidth: {
      description: 'Makes the component expand to fill its container width.',
      control: { type: 'boolean' },
      table: {
        type: { summary: 'boolean' },
        defaultValue: { summary: 'false' },
      },
    },
    startProps: {
      description:
        'Props forwarded to the start `InputTime` (overrides shared props).',
      control: false,
      table: { type: { summary: 'SharedInputTimeProps' } },
    },
    endProps: {
      description:
        'Props forwarded to the end `InputTime` (overrides shared props).',
      control: false,
      table: { type: { summary: 'SharedInputTimeProps' } },
    },
    sx: {
      description:
        'MUI `sx` style overrides applied to the root `FormControl`.',
      control: false,
      table: { type: { summary: 'SxProps' } },
    },
  },
  render: props => {
    const [value, setValue] = useState<TimeRangeValue>(props.value);

    return (
      <LocalizationProvider dateAdapter={AdapterDateFns}>
        <InputTimeRange
          {...props}
          value={value}
          onChange={setValue}
        />
      </LocalizationProvider>
    );
  },
  decorators: [
    Story => (
      <LocalizationProvider dateAdapter={AdapterDateFns}>
        <Story />
      </LocalizationProvider>
    ),
  ],
};

export default meta;

type Story = StoryObj<typeof InputTimeRange>;

export const Default: Story = {
  args: {
    label: 'Time range',
    helperText: 'Select start and end time',
    value: [null, null],
    sx: { width: 400 },
  },
  parameters: {
    docs: {
      description: {
        story: 'Default state with empty start and end times.',
      },
    },
  },
};

export const WithValues: Story = {
  args: {
    label: 'Working hours',
    helperText: '9:00 to 17:00',
    value: [new Date(2024, 0, 1, 9, 0), new Date(2024, 0, 1, 17, 0)],
    sx: { width: 400 },
  },
  parameters: {
    docs: {
      description: {
        story: 'Pre-filled with a 9:00–17:00 range.',
      },
    },
  },
};

export const WithError: Story = {
  args: {
    label: 'Time range',
    error: true,
    errorText: 'End time must be after start time',
    value: [null, null],
    sx: { width: 400 },
  },
  parameters: {
    docs: {
      description: {
        story: 'Error state with error message below both inputs.',
      },
    },
  },
};

export const Disabled: Story = {
  args: {
    label: 'Time range',
    helperText: 'Disabled state',
    disabled: true,
    value: [new Date(2024, 0, 1, 8, 0), new Date(2024, 0, 1, 16, 0)],
    sx: { width: 400 },
  },
  parameters: {
    docs: {
      description: {
        story: 'Both inputs disabled with pre-filled values.',
      },
    },
  },
};

export const FullWidth: Story = {
  args: {
    label: 'Time range',
    helperText: 'Full width',
    fullWidth: true,
    value: [null, null],
  },
  parameters: {
    docs: {
      description: {
        story: 'Expands to fill the parent container width.',
      },
    },
  },
};

type FormStoryProps = {
  defaultValues?: Record<string, TimeRangeValue>;
  inputTimeRangeProps: FormInputTimeRangeProps;
};

const FormStoryTemplate = ({
  defaultValues,
  inputTimeRangeProps,
}: FormStoryProps) => {
  const form = useForm({
    defaultValues: defaultValues || { timeRange: [null, null] },
    mode: 'onChange',
  });

  return (
    <>
      <pre>{JSON.stringify(form.watch(), null, 2)}</pre>
      <Divider sx={{ my: 2 }} />
      <FormProvider {...form}>
        <FormInputTimeRange {...inputTimeRangeProps} />
      </FormProvider>
    </>
  );
};

type FormStory = StoryObj<typeof FormInputTimeRange>;

export const FormDefault: FormStory = {
  render: () => (
    <FormStoryTemplate
      inputTimeRangeProps={{
        name: 'timeRange',
        inputProps: {
          label: 'Time range',
          helperText: 'Select a time range',
          sx: { width: 400 },
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Integration with react-hook-form via `FormInputTimeRange` and `Controller`.',
      },
    },
  },
};

export const FormWithValidation: FormStory = {
  render: () => (
    <FormStoryTemplate
      inputTimeRangeProps={{
        name: 'timeRange',
        inputProps: {
          label: 'Time range',
          helperText: 'Both times are required',
          sx: { width: 400 },
        },
        rules: {
          validate: {
            bothRequired: (value: TimeRangeValue) =>
              (value[0] !== null && value[1] !== null) ||
              'Both start and end times are required',
          },
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Validation example: both start and end times must be selected. ' +
          'Error message appears when submitting with a missing time.',
      },
    },
  },
};
