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

import FormWrapper from '@composed-components/storybook/FormWrapper';
import Button from '@design-system/Buttons/Button';
import { segmentations } from '@src/mock/data/segmentations';
import { type Meta, type StoryObj } from '@storybook/react';

import FormConditionLine from './form';
import {
  type ConditionLineProps,
  type ConditionLineValues,
  ConditionOperator,
  type DefaultItemType,
  JoinOperator,
} from './types';
import ConditionLine from './index';

const meta: Meta<typeof ConditionLine> = {
  title: 'Composed Components/ConditionLine',
  component: ConditionLine,
  parameters: {
    layout: 'centered',
  },
  tags: ['autodocs'],
};

export default meta;
type Story = StoryObj<typeof meta>;

const defaultSlotProps: Partial<
  ConditionLineProps<DefaultItemType, DefaultItemType>['slotProps']
> = {
  conditionOperatorSelector: {
    children: 'está en',
  },
  fieldSelector: {
    getTriggerTitle: _value => _value[0]?.name || 'Selecciona un campo',
  },
  valueSelector: {
    maxSelection: 10,
    getTriggerTitle: _value =>
      _value.map(item => item.name).join(', ') || 'Selecciona un valor',
  },
};

const fieldItems = segmentations.map(seg => ({
  id: seg.id,
  name: seg.name,
}));

const getValueItemsForField = (fieldId: number) => {
  const segmentation = segmentations.find(seg => seg.id === fieldId);
  return segmentation?.items || [];
};

const StoryWrapper = ({ children }: { children: React.ReactNode }) => {
  return <div style={{ width: '800px', padding: '20px' }}>{children}</div>;
};

export const Default: Story = {
  render: args => {
    const [conditionValues, setConditionValues] = useState<
      ConditionLineValues<DefaultItemType, DefaultItemType>
    >({
      joinOperator: JoinOperator.AND,
      field: null,
      conditionOperator: ConditionOperator.IS_IN,
      value: [],
    });

    const valueItems = conditionValues.field
      ? getValueItemsForField(conditionValues.field.id)
      : [];

    return (
      <StoryWrapper>
        <ConditionLine
          {...args}
          value={conditionValues}
          onChange={setConditionValues}
          fieldSelectorItems={fieldItems}
          valueSelectorItems={valueItems}
          slotProps={{
            ...args.slotProps,
            valueSelector: {
              ...args.slotProps?.valueSelector,
              disabled: conditionValues.field === null,
            },
          }}
        />
      </StoryWrapper>
    );
  },
  args: {
    disabled: false,
    slotProps: defaultSlotProps,
    onDelete: () => alert('Línea eliminada'),
  },
};

export const Disabled: Story = {
  render: args => {
    const conditionValues: ConditionLineValues<
      DefaultItemType,
      DefaultItemType
    > = {
      joinOperator: JoinOperator.AND,
      field: fieldItems[0],
      conditionOperator: ConditionOperator.IS_IN,
      value: [segmentations[0].items[0], segmentations[0].items[1]],
    };

    return (
      <StoryWrapper>
        <ConditionLine
          {...args}
          value={conditionValues}
          fieldSelectorItems={fieldItems}
          valueSelectorItems={segmentations[0].items}
          disabled={true}
        />
      </StoryWrapper>
    );
  },
  args: {
    slotProps: defaultSlotProps,
  },
};

export const Loading: Story = {
  render: args => {
    const conditionValues: ConditionLineValues<
      DefaultItemType,
      DefaultItemType
    > = {
      joinOperator: JoinOperator.AND,
      field: fieldItems[0],
      conditionOperator: ConditionOperator.IS_IN,
      value: [segmentations[0].items[0], segmentations[0].items[1]],
    };

    return (
      <StoryWrapper>
        <ConditionLine
          {...args}
          value={conditionValues}
          fieldSelectorItems={fieldItems}
          valueSelectorItems={segmentations[0].items}
          disabled={true}
        />
      </StoryWrapper>
    );
  },
  args: {
    slotProps: {
      ...defaultSlotProps,
      valueSelector: {
        ...defaultSlotProps?.valueSelector,
        loading: true,
      },
      fieldSelector: {
        ...defaultSlotProps?.fieldSelector,
        loading: true,
      },
    },
  },
};

export const Error: Story = {
  render: args => {
    const conditionValues: ConditionLineValues<
      DefaultItemType,
      DefaultItemType
    > = {
      joinOperator: JoinOperator.AND,
      field: fieldItems[0],
      conditionOperator: ConditionOperator.IS_IN,
      value: [segmentations[0].items[0], segmentations[0].items[1]],
    };

    return (
      <StoryWrapper>
        <ConditionLine
          {...args}
          value={conditionValues}
          fieldSelectorItems={fieldItems}
          valueSelectorItems={segmentations[0].items}
          disabled={true}
        />
      </StoryWrapper>
    );
  },
  args: {
    slotProps: {
      ...defaultSlotProps,
      valueSelector: {
        ...defaultSlotProps?.valueSelector,
        error: true,
        errorText: 'Error text',
      },
      fieldSelector: {
        ...defaultSlotProps?.fieldSelector,
        error: true,
        errorText: 'Error text',
      },
    },
  },
};

const ConditionArrayForm = () => {
  const form = useForm<{
    conditions: ConditionLineValues<DefaultItemType, DefaultItemType>[];
  }>({
    defaultValues: {
      conditions: [
        {
          joinOperator: JoinOperator.AND,
          field: null,
          conditionOperator: ConditionOperator.IS_IN,
          value: [],
        },
      ],
    },
  });

  const { fields, append, remove } = useFieldArray({
    control: form.control,
    name: 'conditions',
  });

  const addCondition = () => {
    append({
      joinOperator: form.getValues('conditions')[0].joinOperator,
      field: null,
      conditionOperator: ConditionOperator.IS_IN,
      value: [],
    });
  };

  const handleConditionDelete = (index: number) => {
    if (fields.length > 1) {
      remove(index);
    } else {
      alert('Debe haber al menos una condición');
    }
  };

  return (
    <FormWrapper form={form}>
      {fields.map((field, index) => {
        const watchedField = form.watch(`conditions.${index}.field`);
        const valueItems = watchedField
          ? getValueItemsForField(watchedField.id)
          : [];

        return (
          <FormConditionLine
            key={field.id}
            name={`conditions.${index}`}
            rules={{
              field: {
                required: 'Selecciona un campo para filtrar',
              },
              value: {
                validate: (items: any[]) =>
                  items && items.length > 0
                    ? true
                    : 'Selecciona al menos un valor',
              },
            }}
            conditionLineProps={{
              fieldSelectorItems: fieldItems,
              valueSelectorItems: valueItems,
              onDelete: () => handleConditionDelete(index),
              slotProps: {
                joinOperatorSelector: {
                  readOnly: index !== 0,
                  onChange: option => {
                    fields.forEach((_, _index) => {
                      form.setValue(
                        `conditions.${_index}.joinOperator`,
                        option.value,
                      );
                    });
                  },
                  options: [
                    {
                      label: 'Y',
                      value: JoinOperator.AND,
                    },
                    {
                      label: 'O',
                      value: JoinOperator.OR,
                    },
                  ],
                },
                conditionOperatorSelector: {
                  children: 'está en',
                },
                fieldSelector: {
                  title: 'Seleccionar campo',
                },
                valueSelector: {
                  title: 'Seleccionar valores',
                },
              },
            }}
          />
        );
      })}
      <Button
        variant="secondary"
        onClick={addCondition}
        type="button"
      >
        + Agregar condición
      </Button>
    </FormWrapper>
  );
};

export const WithForm: Story = {
  render: () => (
    <StoryWrapper>
      <ConditionArrayForm />
    </StoryWrapper>
  ),
};
