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

import { Divider } from '@mui/material';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { addMonths, format } from 'date-fns';
import es from 'date-fns/locale/es';

import { type DateRange } from '../Base/CustomRangeDatePicker/types';

import FormRangeDatePicker from './form';
import RangeDatePicker from '.';

const INITIAL_VALUE: DateRange = {
  fromDate: null,
  toDate: null,
};

const meta: Meta<typeof RangeDatePicker> = {
  component: RangeDatePicker,
  title: 'Design System/Inputs/DatePickers/Range',
  tags: ['autodocs'],
  argTypes: {
    label: { control: 'text' },
    helperText: { control: 'text' },
    datePlaceholder: { control: 'text' },
    disabled: { control: 'boolean' },
    error: { control: 'boolean' },
    errorText: { control: 'text' },
    enableClear: { control: 'boolean' },
    minMaxDatesDifference: { control: 'number' },
    value: { control: false },
    onChange: { control: false },
    dateFormatter: { control: false },
    minDate: { control: false },
    maxDate: { control: false },
    slotProps: { control: false },
  },
  args: {
    label: 'Label',
    helperText: 'Helper Text',
    datePlaceholder: 'DD/MM/YYYY',
    dateFormatter: (date: Date, pattern = 'dd/MM/yyyy') => {
      const dateToFormat = new Date(date);
      try {
        return format(dateToFormat, pattern, { locale: es });
      } catch (err) {
        return '';
      }
    },
    slotProps: {
      CalendarHeader: {
        previousMonthText: 'Previous Month',
        nextMonthText: 'Next Month',
        changeMonthText: 'Change Month',
      },
      RangeSelector: {
        clearDatesText: 'Clear',
        applyDatesText: 'Apply',
      },
    },
    enableClear: false,
  },
};

export default meta;

type Story = StoryObj<typeof RangeDatePicker>;

const DateValueDisplay = ({
  fromDate,
  toDate,
}: {
  fromDate: Date | null;
  toDate: Date | null;
}) => (
  <>
    <pre>
      From Date: {fromDate?.toISOString() || 'null'}
      <br />
      To Date: {toDate?.toISOString() || 'null'}
    </pre>
    <Divider sx={{ mb: 2 }} />
  </>
);

export const Default: Story = {
  render: args => {
    const [value, setValue] = useState<DateRange>({ ...INITIAL_VALUE });

    return (
      <>
        <DateValueDisplay
          fromDate={value.fromDate}
          toDate={value.toDate}
        />
        <RangeDatePicker
          {...args}
          value={value}
          onChange={setValue}
        />
      </>
    );
  },
};

export const LimitedFixedRange: Story = {
  render: args => {
    const [value, setValue] = useState<DateRange>({ ...INITIAL_VALUE });

    return (
      <>
        <DateValueDisplay
          fromDate={value.fromDate}
          toDate={value.toDate}
        />
        <RangeDatePicker
          {...args}
          value={value}
          onChange={setValue}
          minDate={new Date()} // Today
          maxDate={addMonths(new Date(), 1)} // 1 month from today
        />
      </>
    );
  },
  parameters: {
    docs: {
      description: {
        story:
          'RangeDatePicker with limited range (today to 1 month from today)',
      },
    },
  },
};

export const LimitedDynamicRange: Story = {
  render: args => {
    const [value, setValue] = useState<DateRange>({ ...INITIAL_VALUE });

    return (
      <>
        <DateValueDisplay
          fromDate={value.fromDate}
          toDate={value.toDate}
        />
        <RangeDatePicker
          {...args}
          value={value}
          onChange={setValue}
          minMaxDatesDifference={14}
        />
      </>
    );
  },
  parameters: {
    docs: {
      description: {
        story:
          'RangeDatePicker with limited dynamic range (range cannot span more than 14 days)',
      },
    },
  },
};

export const Form: Story = {
  render: args => {
    const form = useForm({
      defaultValues: { dateRange: INITIAL_VALUE },
    });

    const { fromDate, toDate } = useWatch({
      name: 'dateRange',
      control: form.control,
    });

    return (
      <>
        <DateValueDisplay
          fromDate={fromDate}
          toDate={toDate}
        />
        <FormProvider {...form}>
          <FormRangeDatePicker
            name="dateRange"
            inputProps={{
              ...args,
            }}
          />
        </FormProvider>
      </>
    );
  },
};

export const Disabled: Story = {
  render: args => {
    const [value, setValue] = useState<DateRange>({ ...INITIAL_VALUE });

    return (
      <>
        <p>From Date: {value.fromDate?.toISOString() || 'null'}</p>
        <p>To Date: {value.toDate?.toISOString() || 'null'}</p>
        <RangeDatePicker
          {...args}
          value={value}
          onChange={setValue}
          disabled
        />
      </>
    );
  },
};

export const Error: Story = {
  render: args => {
    const [value, setValue] = useState<DateRange>({ ...INITIAL_VALUE });

    return (
      <>
        <DateValueDisplay
          fromDate={value.fromDate}
          toDate={value.toDate}
        />
        <RangeDatePicker
          {...args}
          value={value}
          onChange={setValue}
          error
          errorText="Please select a valid date range"
        />
      </>
    );
  },
};
