import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { QueryClient, QueryClientProvider } from 'react-query';

import { emptyCondition } from '@composed-components/ConditionGroup/constants';
import {
  fieldItems,
  valueItems,
} from '@composed-components/ConditionGroup/mocks';
import { type AlertProps } from '@design-system/Alert/types';
import { type TitleProps } from '@design-system/Title/types';
import { type Meta, type StoryObj } from '@storybook/react-vite';

import { mockDataParser, useMockUsersQuery } from '../mocks';

import {
  getIndividualDescription,
  getSegmentationDescription,
  mockService,
  useMockCount,
  useMockService,
} from './mocks';
import {
  type AudienceFormValues,
  type CriteriaEntry,
  CriteriaType,
} from './types';
import Audience from './index';

const queryClient = new QueryClient({
  defaultOptions: { queries: { retry: false } },
});

const AudienceStory = ({
  defaultCriterias = [],
  title,
  description,
  onBeforeDelete,
  slotProps,
  showCriteriaInfo,
}: {
  defaultCriterias?: AudienceFormValues['criterias'];
  title?: string;
  description?: string;
  onBeforeDelete?: (
    index: number,
    entry: CriteriaEntry,
    confirmDelete: () => void,
  ) => void;
  slotProps?: { title?: Partial<TitleProps>; alert?: AlertProps };
  showCriteriaInfo?: boolean;
}) => {
  const form = useForm<AudienceFormValues>({
    defaultValues: {
      criterias: defaultCriterias,
    },
  });

  useEffect(() => {
    const subscription = form.watch(values => {
      console.debug('[Audience] form values:', values);
    });
    return () => subscription.unsubscribe();
  }, [form]);

  return (
    <FormProvider {...form}>
      <Audience
        title={title}
        description={description}
        segmentationDrawerProps={{
          collaboratorsReach: {
            useCount: useMockCount,
            useService: useMockService,
            queryKey: 'audience-segmentation',
          },
          inputProps: {
            slotProps: {
              conditionLine: {
                fieldSelectorItems: fieldItems,
                valueSelectorItems: valueItems,
              },
            },
          },
        }}
        individualDrawerProps={{
          inputProps: {
            useUsersQuery: useMockUsersQuery,
            usersQueryDataParser: mockDataParser,
          },
          collaboratorsReach: {
            useCount: useMockCount,
            useService: useMockService,
            queryKey: 'audience-individual',
          },
        }}
        selectedCollaboratorsDrawerProps={{
          service: mockService,
          queryKey: 'audience-selected',
        }}
        getSegmentationDescription={getSegmentationDescription}
        getIndividualDescription={getIndividualDescription}
        useCount={useMockCount}
        onBeforeDelete={onBeforeDelete}
        showCriteriaInfo={showCriteriaInfo}
        slotProps={slotProps}
      />
    </FormProvider>
  );
};

const meta: Meta<typeof Audience> = {
  component: Audience,
  title: 'Composed Components/Audience/Audience',
  tags: ['autodocs'],
  decorators: [
    Story => (
      <QueryClientProvider client={queryClient}>
        <div style={{ maxWidth: 700, width: '100%', margin: '2em auto' }}>
          <Story />
        </div>
      </QueryClientProvider>
    ),
  ],
  parameters: {
    docs: {
      description: {
        component:
          'High-level audience assignment component that orchestrates criteria selection, ' +
          'summary display, and drawer interactions. Uses `useFormContext` from react-hook-form ' +
          'to persist selected criteria in a parent form. Supports segmentation, individual, ' +
          'and all-community criteria types. When no criteria are selected, shows the three ' +
          'criteria cards. When criteria are selected, shows summary cards, a total collaborators ' +
          'button, and an autocomplete to add more criteria.',
      },
    },
  },
  argTypes: {
    title: {
      description:
        'Custom title displayed at the top. Falls back to a translated default.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    description: {
      description:
        'Custom description text. Falls back to a translated default.',
      control: { type: 'text' },
      table: { type: { summary: 'string' } },
    },
    segmentationDrawerProps: {
      description:
        'Props forwarded to `useSegmentationCriteriaDrawer` (excluding `defaultValues`).',
      control: false,
      table: {
        type: {
          summary: 'Omit<UseSegmentationCriteriaDrawerProps, "defaultValues">',
        },
      },
    },
    individualDrawerProps: {
      description:
        'Props forwarded to `useIndividualCriteriaDrawer` (excluding `defaultValues`).',
      control: false,
      table: {
        type: {
          summary: 'Omit<UseIndividualCriteriaDrawerProps, "defaultValues">',
        },
      },
    },
    selectedCollaboratorsDrawerProps: {
      description: 'Props for the selected collaborators drawer.',
      control: false,
      table: {
        type: {
          summary:
            'Pick<SelectedCollaboratorsDrawerProps, "service" | "queryKey">',
        },
      },
    },
    getSegmentationDescription: {
      description:
        'Callback that returns a human-readable description for a segmentation criteria entry.',
      control: false,
      table: {
        type: { summary: '(entry: SegmentationCriteriaEntry) => string' },
      },
    },
    getIndividualDescription: {
      description:
        'Callback that returns a human-readable description for an individual criteria entry.',
      control: false,
      table: {
        type: { summary: '(entry: IndividualCriteriaEntry) => string' },
      },
    },
    onBeforeDelete: {
      description:
        'Intercepts the delete action. Receives `(index, entry, confirmDelete)`. ' +
        'Call `confirmDelete()` to proceed with removal.',
      control: false,
      table: {
        type: {
          summary:
            '(index: number, entry: CriteriaEntry, confirmDelete: () => void) => void',
        },
      },
    },
    slotProps: {
      description:
        'Props forwarded to inner slot components. Supports `title` to customize the Title component ' +
        'and `alert` to render a HuAlert between the title and the criteria content.',
      control: false,
      table: {
        type: {
          summary: '{ title?: Partial<TitleProps>; alert?: AlertProps }',
        },
      },
    },
    sx: {
      description: 'MUI `sx` style overrides applied to the root `Stack`.',
      control: false,
      table: { type: { summary: 'SxProps' } },
    },
  },
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Empty: Story = {
  name: 'No criteria selected',
  render: () => <AudienceStory />,
  parameters: {
    docs: {
      description: {
        story:
          'Initial state with no criteria selected. Shows the three criteria cards ' +
          '(Segmentation, Individual, All) for the user to pick from.',
      },
    },
  },
};

export const WithSegmentation: Story = {
  name: 'With segmentation criteria',
  render: () => (
    <AudienceStory
      defaultCriterias={[
        {
          type: CriteriaType.SEGMENTATION,
          conditions: [emptyCondition],
        },
      ]}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'One segmentation criteria is pre-selected. Shows the summary card with edit/delete ' +
          'actions and the autocomplete to add an individual criteria.',
      },
    },
  },
};

export const WithIndividual: Story = {
  name: 'With individual criteria',
  render: () => (
    <AudienceStory
      defaultCriterias={[
        {
          type: CriteriaType.INDIVIDUAL,
          userIds: new Set(['1', '2', '3']),
        },
      ]}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'One individual criteria is pre-selected with 3 collaborators. Shows the summary card ' +
          'and the autocomplete to add a segmentation criteria.',
      },
    },
  },
};

export const WithAll: Story = {
  name: 'With all community criteria',
  render: () => (
    <AudienceStory defaultCriterias={[{ type: CriteriaType.ALL }]} />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'The "entire community" criteria is selected. The all summary card has no edit action, only delete.',
      },
    },
  },
};

export const WithMultipleCriteria: Story = {
  name: 'With multiple criteria',
  render: () => (
    <AudienceStory
      defaultCriterias={[
        {
          type: CriteriaType.SEGMENTATION,
          conditions: [emptyCondition],
        },
        {
          type: CriteriaType.INDIVIDUAL,
          userIds: new Set(['1', '2', '3', '4', '5']),
        },
      ]}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Both segmentation and individual criteria are selected. The autocomplete is hidden ' +
          'because all non-ALL types are in use.',
      },
    },
  },
};

export const CustomTitle: Story = {
  name: 'Custom title and description',
  render: () => (
    <AudienceStory
      title="Custom title"
      description="Custom audience description"
    />
  ),
  parameters: {
    docs: {
      description: {
        story: 'Demonstrates custom title and description props.',
      },
    },
  },
};

const OnBeforeDeleteExample = () => {
  const [pendingDelete, setPendingDelete] = useState<(() => void) | null>(null);

  return (
    <>
      <AudienceStory
        defaultCriterias={[
          { type: CriteriaType.SEGMENTATION, conditions: [emptyCondition] },
          { type: CriteriaType.INDIVIDUAL, userIds: new Set(['1', '2']) },
        ]}
        onBeforeDelete={(_index, _entry, confirmDelete) => {
          setPendingDelete(() => confirmDelete);
        }}
      />
      {pendingDelete && (
        <div
          style={{
            position: 'fixed',
            inset: 0,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            backgroundColor: 'rgba(0,0,0,0.4)',
            zIndex: 9999,
          }}
        >
          <div
            style={{
              background: '#fff',
              borderRadius: 12,
              padding: 24,
              maxWidth: 400,
              display: 'flex',
              flexDirection: 'column',
              gap: 16,
            }}
          >
            <strong>¿Quieres eliminar el criterio?</strong>
            <span>
              Al eliminarlo, se perderá toda la configuración asociada.
            </span>
            <div
              style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}
            >
              <button
                type="button"
                onClick={() => setPendingDelete(null)}
              >
                Cancelar
              </button>
              <button
                type="button"
                onClick={() => {
                  pendingDelete();
                  setPendingDelete(null);
                }}
              >
                Eliminar
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
};

export const WithOnBeforeDelete: Story = {
  name: 'With onBeforeDelete (confirmation)',
  render: () => <OnBeforeDeleteExample />,
  parameters: {
    docs: {
      description: {
        story:
          'Demonstrates the `onBeforeDelete` prop. Clicking the trash icon opens a confirmation ' +
          'dialog managed by the consumer. The entry is only removed when "Eliminar" is clicked.',
      },
    },
  },
};

export const WithTitleSlotProps: Story = {
  name: 'With slotProps.title (variant L)',
  render: () => (
    <AudienceStory
      title="Colaboradores"
      description="Selecciona los colaboradores que podrán iniciar este servicio."
      slotProps={{ title: { variant: 'L' } }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Uses `slotProps.title` to override the Title variant to `"L"`. ' +
          'Any Title prop (variant, fontWeight, sx, etc.) can be customized this way.',
      },
    },
  },
};

export const WithAlertError: Story = {
  name: 'With slotProps.alert (error)',
  render: () => (
    <AudienceStory
      slotProps={{
        alert: {
          severity: 'error',
          title: 'No se seleccionaron colaboradores',
          description:
            'Debes seleccionar al menos un criterio de audiencia para continuar.',
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Uses `slotProps.alert` to render an error Alert between the title and the criteria cards. ' +
          'Typical use case: validation feedback when the form is submitted without criteria.',
      },
    },
  },
};

export const WithAlertWarning: Story = {
  name: 'With slotProps.alert (warning)',
  render: () => (
    <AudienceStory
      defaultCriterias={[
        {
          type: CriteriaType.SEGMENTATION,
          conditions: [emptyCondition],
        },
      ]}
      slotProps={{
        alert: {
          severity: 'warning',
          title: 'Criterio incompleto',
          description:
            'Algunos campos de segmentación están vacíos. Completalos antes de guardar.',
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Warning alert shown alongside existing criteria. Demonstrates the alert ' +
          'rendering between the title and the summary cards.',
      },
    },
  },
};

export const WithAlertInfo: Story = {
  name: 'With slotProps.alert (info)',
  render: () => (
    <AudienceStory
      slotProps={{
        alert: {
          severity: 'info',
          title: 'Información',
          description:
            'Los criterios de audiencia determinan qué colaboradores podrán acceder a este servicio.',
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story: 'Informational alert used as a contextual hint for the user.',
      },
    },
  },
};

export const WithShowCriteriaInfoFalse: Story = {
  name: 'With showCriteriaInfo false',
  render: () => <AudienceStory showCriteriaInfo={false} />,
  parameters: {
    docs: {
      description: {
        story:
          'When `showCriteriaInfo` is `false`, the criteria cards hide the automatic-update pill ' +
          'and the segmentation drawer description omits the automatic-update sentence.',
      },
    },
  },
};

export const WithAlertAndTitleSlotProps: Story = {
  name: 'With slotProps.alert + slotProps.title',
  render: () => (
    <AudienceStory
      title="Colaboradores"
      description="Selecciona los colaboradores que podrán iniciar este servicio."
      slotProps={{
        title: { variant: 'L' },
        alert: {
          severity: 'error',
          title: 'No se seleccionaron colaboradores',
          description:
            'Debes seleccionar al menos un criterio de audiencia para continuar.',
        },
      }}
    />
  ),
  parameters: {
    docs: {
      description: {
        story:
          'Combines both `slotProps.title` and `slotProps.alert` to show how ' +
          'multiple slot overrides compose together.',
      },
    },
  },
};
