import { useEffect, useMemo, useState } from 'react';
import { useFormContext } from 'react-hook-form';

import Stack from '@material-hu/mui/Stack';

import HuAvatar from '@material-hu/components/design-system/Avatar';
import HuFormAutocomplete from '@material-hu/components/design-system/Inputs/Autocomplete/form';
import HuMenuItem from '@material-hu/components/design-system/Menu/components/MenuItem';
import HuSkeleton from '@material-hu/components/design-system/Skeleton';
import HuTitle from '@material-hu/components/design-system/Title';

import { type HydratedUser } from 'src/pages/dashboard/ServiceManagement/types';
import { transformUsersToOptions } from 'src/pages/dashboard/Workflows/utils';
import { useInfiniteUsersPublicSearch } from 'src/services/usersQueries';
import { type User } from 'src/types/user';
import { getFullname } from 'src/utils/userUtils';

import { InfiniteListAutocomplete } from './InfiniteListAutocomplete';

const agentSkeleton = (
  <Stack sx={{ flexDirection: 'row', gap: 2, alignItems: 'center', mx: 2 }}>
    <HuSkeleton
      variant="rectangular"
      height={20}
      width={25}
      sx={{
        borderRadius: 0.5,
      }}
    />
    <HuSkeleton
      variant="circular"
      width={45}
      height={35}
    />
    <HuSkeleton
      variant="text"
      height={40}
      sx={{
        borderRadius: 1,
        width: '100%',
      }}
    />
  </Stack>
);

type Props = {
  name: string;
  agentGroupsFieldName: string;
  autocompleteProps?: any;
};

const LIMIT = 20;

function AgentsByGroupAutocomplete({
  name,
  agentGroupsFieldName,
  autocompleteProps,
}: Props) {
  const [search, setSearch] = useState('');
  const { watch, setValue } = useFormContext();

  const selectedAgentGroup = watch(agentGroupsFieldName);
  const selectedAgent = watch(name);

  const groupIsHydrating = typeof selectedAgentGroup === 'string';

  const agentIds = useMemo(() => {
    if (!selectedAgentGroup || groupIsHydrating) {
      return [];
    }

    const agents = selectedAgentGroup.agents;
    if (!Array.isArray(agents) || agents.length === 0) {
      return [];
    }

    return [
      ...new Set(
        agents
          .map((agent: HydratedUser) =>
            typeof agent === 'object' ? agent.id : agent,
          )
          .filter(Boolean),
      ),
    ];
  }, [selectedAgentGroup]);

  const selectedAgentId =
    typeof selectedAgent === 'number' ? selectedAgent : selectedAgent?.id;
  const needsHydration = selectedAgentId && typeof selectedAgent === 'number';

  const queryIds = useMemo(() => {
    if (needsHydration) {
      return [selectedAgentId];
    }

    if (agentIds.length > 0) {
      return agentIds;
    }

    return null;
  }, [needsHydration, selectedAgentId, agentIds]);

  // Fetch when needed or if there is no agent and the group is not hydrated
  const shouldFetch = needsHydration || (!groupIsHydrating && !selectedAgent);

  const usersInfiniteQuery = useInfiniteUsersPublicSearch(
    {
      search,
      limit: LIMIT,
      ids: queryIds,
      isAgent: true,
    },
    {
      enabled: shouldFetch,
      refetchOnWindowFocus: false,
    },
  );

  const options = useMemo(
    () => transformUsersToOptions(usersInfiniteQuery?.data?.pages),
    [usersInfiniteQuery?.data?.pages],
  );

  useEffect(() => {
    if (needsHydration && options.length > 0) {
      const hydratedAgent = options.find(opt => opt.id === selectedAgentId);
      if (hydratedAgent && typeof selectedAgent === 'number') {
        setValue(name, hydratedAgent);
      }
    }
  }, [needsHydration, options, selectedAgentId, selectedAgent, name, setValue]);

  const isLoading = usersInfiniteQuery.isFetching;
  const isDisabled = groupIsHydrating;

  return (
    <HuFormAutocomplete
      name={name}
      options={options}
      autocompleteProps={{
        disabled: isDisabled,
        getOptionLabel: (option: User) => getFullname(option) || '',
        isOptionEqualToValue: (option: User, value: User) =>
          option?.id === value?.id,
        ...(isLoading && {
          renderTags: () => (
            <HuSkeleton
              variant="rounded"
              width={140}
              height={26}
              sx={{ ml: 0.5, my: 1 }}
            />
          ),
        }),
        renderOption: (props, option: User, { selected, index }) => {
          const { key, ...rest } = props;
          if (option.status === 'DEACTIVATED') {
            return null;
          }
          return (
            <>
              <HuMenuItem
                selected={selected}
                key={key}
                {...rest}
                sx={{ gap: 2, padding: '8px !important' }}
              >
                <HuAvatar
                  src={option.profilePicture || undefined}
                  size="medium"
                  sx={{ my: 1 }}
                />
                <HuTitle
                  variant="S"
                  title={getFullname(option)}
                  description={option.employeeInternalId}
                />
              </HuMenuItem>
              {index === options.length - 1 && (
                <InfiniteListAutocomplete
                  infiniteQuery={usersInfiniteQuery}
                  options={options}
                  renderSkeleton={agentSkeleton}
                />
              )}
            </>
          );
        },
        onInputChange: (_, value) => setSearch(value),
        loading: usersInfiniteQuery.isFetchingNextPage || isLoading,
        isServerFiltered: true,
        ...autocompleteProps,
        placeholder: selectedAgent ? undefined : autocompleteProps?.placeholder,
      }}
    />
  );
}

export default AgentsByGroupAutocomplete;
