import {
  type ComponentProps,
  type FC,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from 'react';
import { type FieldValues, useFormContext } from 'react-hook-form';
import { type UseInfiniteQueryOptions } from 'react-query';

import { type AxiosResponse } from 'axios';
import Stack from '@material-hu/mui/Stack';

import CollapsibleAutocompleteSelector from '@material-hu/components/composed-components/CollapsibleAutocompleteSelector';
import DatePickerWithOptions from '@material-hu/components/composed-components/DatePickerWithOptions';
import HuAccordion from '@material-hu/components/design-system/Accordion';
import HuDrawer from '@material-hu/components/design-system/Drawer';

import { useAuth } from 'src/contexts/JWTContext';
import UserCollapsibleAutocompleteSelector from 'src/pages/dashboard/serviceManagement/general/UserCollapsibleAutocompleteSelector';
import {
  type OxxoCollaboratorType,
  ServiceItemTypes,
  type State,
} from 'src/pages/dashboard/serviceManagement/types';
import {
  getCreationDateFilterDescription,
  getStateName,
} from 'src/pages/dashboard/serviceManagement/utils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { type PaginatedResponse } from 'src/utils/pagination';

import {
  OXXO_COLLABORATOR_TYPE_IDS,
  OXXO_SEGMENTATION_OPTIONS,
} from '../../constants';
import useInfiniteAgentGroups from '../../hooks/useInfiniteAgentGroups';
import useInfiniteServiceItems from '../../hooks/useInfiniteServiceItems';
import useInfiniteUsersAndAgents from '../../hooks/useInfiniteUsersAndAgents';
import useTaskStates from '../../hooks/useTaskStates';
import { createStaticOptionsQuery } from '../../utils';
import { type FilterFieldConfig } from '../form/form';

type InfiniteQueryParams = { limit: number; name: string };
type InfiniteQueryHookOptions = UseInfiniteQueryOptions<
  AxiosResponse<PaginatedResponse<unknown>>
>;

// Stable module-scope hook: binds `isAgent: true` without recreating per render.
const useInfiniteAgents = (
  params: InfiniteQueryParams,
  options: InfiniteQueryHookOptions,
) => useInfiniteUsersAndAgents({ ...params, isAgent: true }, options);

type CollapsibleSelectorProps = ComponentProps<
  typeof CollapsibleAutocompleteSelector
>;
type BoundCollapsibleSelectorProps = Omit<
  CollapsibleSelectorProps,
  'infiniteQuery'
> & {
  helpDeskId?: string;
};

// Dedicated wrappers that own the helpDeskId binding for each query.
// Stabilizing the hook reference with useCallback ensures the function identity
// only changes when helpDeskId changes (instead of every parent render), keeping
// CollapsibleAutocompleteSelector's internal hook call site consistent.
const ServiceItemsCollapsibleSelector: FC<BoundCollapsibleSelectorProps> = ({
  helpDeskId,
  ...rest
}) => {
  const infiniteQuery = useCallback(
    (params: InfiniteQueryParams, options: InfiniteQueryHookOptions) =>
      // biome-ignore lint/correctness/useHookAtTopLevel: invoked at the top level of CollapsibleAutocompleteSelector
      useInfiniteServiceItems({ ...params, helpDeskId }, options),
    [helpDeskId],
  );

  return (
    <CollapsibleAutocompleteSelector
      {...(rest as CollapsibleSelectorProps)}
      infiniteQuery={infiniteQuery as CollapsibleSelectorProps['infiniteQuery']}
    />
  );
};

const AgentGroupsCollapsibleSelector: FC<BoundCollapsibleSelectorProps> = ({
  helpDeskId,
  ...rest
}) => {
  const infiniteQuery = useCallback(
    (params: InfiniteQueryParams, options: InfiniteQueryHookOptions) =>
      // biome-ignore lint/correctness/useHookAtTopLevel: invoked at the top level of CollapsibleAutocompleteSelector
      useInfiniteAgentGroups({ ...params, helpDeskId }, options),
    [helpDeskId],
  );

  return (
    <CollapsibleAutocompleteSelector
      {...(rest as CollapsibleSelectorProps)}
      infiniteQuery={infiniteQuery as CollapsibleSelectorProps['infiniteQuery']}
    />
  );
};

type Props = {
  open: boolean;
  onClose: () => void;
  onApply: () => void;
  onReset: () => void;
  helpDeskId?: string;
  filterConfig: FilterFieldConfig;
  // Optional filter visibility
  showStatuses?: boolean;
  showRequesters?: boolean;
  showCollaboratorTypes?: boolean;
  showBack?: boolean;
};

type ExpandedState = {
  serviceItemsIn: boolean;
  agentGroupsIn: boolean;
  taskStatusesIn: boolean;
  initiatorsIn: boolean;
  creationDate: boolean;
  agentsIn: boolean;
  collaboratorTypesIn: boolean;
};

const defaultExpanded: ExpandedState = {
  serviceItemsIn: false,
  agentGroupsIn: false,
  taskStatusesIn: false,
  initiatorsIn: false,
  creationDate: false,
  agentsIn: false,
  collaboratorTypesIn: false,
};

const CollaboratorPanelFilterDrawer: FC<Props> = ({
  open,
  onClose,
  onApply,
  onReset,
  helpDeskId,
  filterConfig,
  showStatuses = false,
  showRequesters = false,
  showCollaboratorTypes = false,
  showBack = false,
}) => {
  const { t, i18n } = useLokaliseTranslation(['service_management', 'general']);
  const {
    watch,
    handleSubmit,
    formState: { errors },
    clearErrors,
    setValue,
  } = useFormContext<FieldValues>();
  const { instance } = useAuth();

  const [expanded, setExpanded] = useState<ExpandedState>(defaultExpanded);

  const formValues = watch();
  const dateRangeValue = Boolean(watch(filterConfig.dateOptions.dateRange()));

  const handleExpand = (field: keyof ExpandedState, newExpanded: boolean) => {
    setExpanded(prev => ({ ...prev, [field]: newExpanded }));
  };

  const applyDisabled = useMemo(
    () =>
      (dateRangeValue &&
        !formValues[filterConfig.creationDateFrom()] &&
        !formValues[filterConfig.creationDateTo()]) ||
      Object.keys(errors || {}).length > 0,
    [formValues, errors, dateRangeValue, filterConfig],
  );

  useEffect(() => {
    if (!dateRangeValue) {
      clearErrors([
        filterConfig.creationDateFrom(),
        filterConfig.creationDateTo(),
      ]);
      setValue(filterConfig.creationDateFrom(), null);
      setValue(filterConfig.creationDateTo(), null);
    }
  }, [dateRangeValue, clearErrors, setValue, filterConfig]);

  const { data: taskStates = [] } = useTaskStates(ServiceItemTypes.INCIDENT, {
    enabled: showStatuses,
  });

  const taskStaticQueryOptions = useMemo(
    () =>
      createStaticOptionsQuery(taskStates, {
        getSearchText: item => t(getStateName(item.name)),
      }),
    [taskStates, t],
  );

  const oxxoStaticQueryOptions = useMemo(
    () => createStaticOptionsQuery(OXXO_SEGMENTATION_OPTIONS.items),
    [],
  );

  const autocompleteLabelProps = useMemo(() => {
    return {
      selectAllLabel: t('select_all'),
      noResultsLabel: t('empty_results'),
      lackingOptionsMessage: t('empty_results'),
      formatAndMore: (count: number) => t('and_n_items_more', { count }),
      virtualized: true,
      maxHeight: 300,
    };
  }, [t]);

  // Show OXXO collaborator types for OXXO or testing instances
  const isOxxo = OXXO_COLLABORATOR_TYPE_IDS.includes(instance?.id!);
  const shouldShowCollaboratorTypes = showCollaboratorTypes && isOxxo;

  return (
    <HuDrawer
      open={open}
      onClose={onClose}
      hasBackButton={showBack}
      title={t('filter_by')}
      primaryButtonProps={{
        onClick: handleSubmit(onApply),
        children: t('general:apply'),
        fullWidth: true,
        disabled: applyDisabled,
      }}
      secondaryButtonProps={{
        onClick: onReset,
        children: t('reset'),
        fullWidth: true,
      }}
    >
      <Stack sx={{ gap: 2 }}>
        <ServiceItemsCollapsibleSelector
          sectionTitle={t('request_types')}
          fieldName={filterConfig.serviceItemsIn()}
          helpDeskId={helpDeskId}
          isExpanded={expanded.serviceItemsIn}
          setExpanded={newExpanded =>
            handleExpand('serviceItemsIn', newExpanded)
          }
          {...autocompleteLabelProps}
        />
        {showStatuses && filterConfig.statesIn && (
          <CollapsibleAutocompleteSelector<State>
            fieldName={filterConfig.statesIn()}
            sectionTitle={t('statuses')}
            customMapper={item => ({
              value: item.id,
              name: t(getStateName(item.name)),
            })}
            infiniteQuery={taskStaticQueryOptions}
            isExpanded={expanded.taskStatusesIn}
            setExpanded={newExpanded =>
              handleExpand('taskStatusesIn', newExpanded)
            }
            {...autocompleteLabelProps}
          />
        )}
        {showRequesters && filterConfig.initiatorsIn && (
          <UserCollapsibleAutocompleteSelector
            fieldName={filterConfig.initiatorsIn()}
            sectionTitle={t('requesters')}
            infiniteQuery={useInfiniteUsersAndAgents}
            isExpanded={expanded.initiatorsIn}
            setExpanded={newExpanded =>
              handleExpand('initiatorsIn', newExpanded)
            }
            {...autocompleteLabelProps}
          />
        )}
        <UserCollapsibleAutocompleteSelector
          fieldName={filterConfig.agentsIn()}
          sectionTitle={t('agents')}
          infiniteQuery={useInfiniteAgents as any}
          isExpanded={expanded.agentsIn}
          setExpanded={newExpanded => handleExpand('agentsIn', newExpanded)}
          showOnlyOnSearch
          {...autocompleteLabelProps}
        />
        <AgentGroupsCollapsibleSelector
          fieldName={filterConfig.agentGroupsIn()}
          sectionTitle={t('groups')}
          helpDeskId={helpDeskId}
          isExpanded={expanded.agentGroupsIn}
          setExpanded={newExpanded =>
            handleExpand('agentGroupsIn', newExpanded)
          }
          {...autocompleteLabelProps}
        />
        {shouldShowCollaboratorTypes && filterConfig.collaboratorTypesIn && (
          <CollapsibleAutocompleteSelector<OxxoCollaboratorType>
            fieldName={filterConfig.collaboratorTypesIn()}
            sectionTitle={t('collaborator_type')}
            isExpanded={expanded.collaboratorTypesIn}
            setExpanded={newExpanded =>
              handleExpand('collaboratorTypesIn', newExpanded)
            }
            infiniteQuery={oxxoStaticQueryOptions as any}
            customMapper={item => ({ value: item.id, name: item.title })}
            getItemId={item => item.id}
            {...autocompleteLabelProps}
          />
        )}
        <HuAccordion
          title={t('creation_date')}
          description={getCreationDateFilterDescription({
            dateRangeValueSelected: !!dateRangeValue,
            lastSevenDays: Boolean(
              watch(filterConfig.dateOptions.lastSevenDays()),
            ),
            lastFourteenDays: Boolean(
              watch(filterConfig.dateOptions.lastFourteenDays()),
            ),
            lastThirtyDays: Boolean(
              watch(filterConfig.dateOptions.lastThirtyDays()),
            ),
            fromDate: watch(filterConfig.creationDateFrom()),
            toDate: watch(filterConfig.creationDateTo()),
            language: i18n.language || 'en',
            t,
          })}
          expanded={expanded.creationDate}
          onChange={(_, newExpanded) => {
            handleExpand('creationDate', newExpanded);
          }}
          elevation={0}
          sx={{
            borderRadius: ({ spacing }) => spacing(1),
            mb: 2,
            backgroundColor: ({ palette }) =>
              palette.new.background.elements.grey,
            '&:before': {
              backgroundColor: 'transparent',
            },
          }}
          disableGutters
          customDetail={
            <DatePickerWithOptions
              showDatePickers
              options={[
                {
                  name: filterConfig.dateOptions.lastSevenDays(),
                  label: t('last_n_days', { days: 7 }),
                },
                {
                  name: filterConfig.dateOptions.lastFourteenDays(),
                  label: t('last_n_days', { days: 14 }),
                },
                {
                  name: filterConfig.dateOptions.lastThirtyDays(),
                  label: t('last_n_days', { days: 30 }),
                },
                {
                  name: filterConfig.dateOptions.dateRange(),
                  label: t('choose_date_range'),
                },
              ]}
              startDatePicker={{
                name: filterConfig.creationDateFrom(),
                label: t('from'),
                disabled: !dateRangeValue,
                inputProps: { disableFuture: true },
              }}
              endDatePicker={{
                name: filterConfig.creationDateTo(),
                label: t('general:until'),
                disabled: !dateRangeValue,
                inputProps: { disableFuture: true },
              }}
            />
          }
        />
      </Stack>
    </HuDrawer>
  );
};

export default CollaboratorPanelFilterDrawer;
