import { useCallback, useEffect, useMemo, useState } from 'react';
import { Helmet } from 'react-helmet-async';
import { FormProvider, type UseFormReturn } from 'react-hook-form';
import { useInfiniteQuery, useQuery, useQueryClient } from 'react-query';
import { useNavigate } from 'react-router-dom';

import { IconFileCheck, IconFilter } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import BadgeCountButton from '@material-hu/components/composed-components/BadgeCountButton';
import HuAvatar from '@material-hu/components/design-system/Avatar';
import HuBadge from '@material-hu/components/design-system/Badge';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import TaskFocusHeader from '@material-hu/components/design-system/Header/TaskFocus';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuListItem from '@material-hu/components/design-system/List/components/ListItem';
import StateCard from '@material-hu/components/design-system/StateCard';
import HuTabs from '@material-hu/components/design-system/Tabs';
import HuTitle from '@material-hu/components/design-system/Title';

import { logEvent } from 'src/config/logging';
import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import {
  getTasks,
  getTransitionsStates,
} from 'src/pages/dashboard/serviceManagement/services';
import {
  getApprovalPillDescription,
  getApprovalPillType,
  getApprovalStateName,
  getTaskID,
  getUserDisplayName,
  parseHistoryApprovalsFilters,
  parsePendingApprovalsFilters,
} from 'src/pages/dashboard/serviceManagement/utils';
import { EventName } from 'src/types/amplitude';
import { FeatureFlags } from 'src/types/featureFlags';
import { formatLocalizedDate } from 'src/utils/date';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';

import InfiniteList from 'src/components/list/InfiniteList';

import {
  ORDER_BY_DEFAULT_VALUE,
  ORDER_DEFAULT_VALUE,
} from '../../agentWorkspace/constants';
import {
  type HistoryApprovalsFormValues,
  type PendingApprovalsFormValues,
} from '../../agentWorkspace/types';
import {
  type ApprovalTabsType,
  approvalEmptyState,
  approvalNoSearchId,
  approvalTabs,
} from '../../constants';
import ApprovalsCoachmark from '../../general/ApprovalsCoachmark';
import ApprovalsFiltersDrawer from '../../general/ApprovalsFiltersDrawer';
import useApprovalsUrlState from '../../hooks/useApprovalsUrlState';
import useTaskCommentsUpdater from '../../hooks/useTaskCommentsUpdater';
import { serviceManagementKeys } from '../../queries';
import { serviceManagementRoutes } from '../../routes';
import {
  ApprovalScreenSource,
  ServiceItemTypes,
  type Task,
  TasksType,
} from '../../types';
import { ApprovalActions } from '../serviceItems/components/ApprovalActions';
import ApprovalItemSkeleton from '../serviceItems/components/ApprovalItemSkeleton';

const ApprovalsPortal = () => {
  const { t } = useLokaliseTranslation('service_management');
  const HugoThemeProvider = useHuGoTheme();
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { user } = useAuth();
  const socket = useSocket();
  const bubblesEnabled = useFeatureFlag(
    FeatureFlags.SERVICE_MANAGEMENT_BUBBLES_ENABLED,
  );

  const {
    tab,
    setTab,
    isPending,
    search,
    debouncedSearch,
    setSearch,
    appliedFilters,
    appliedFiltersCount,
    filtersForm,
    filterDrawerOpen,
    openFilterDrawer,
    handleApplyFilters,
    handleResetFilters,
    handleCloseFilterDrawer,
  } = useApprovalsUrlState();

  const [searchAnchor, setSearchAnchor] = useState<HTMLDivElement | null>(null);
  const [filterAnchor, setFilterAnchor] = useState<HTMLDivElement | null>(null);
  const searchRefCallback = useCallback((node: HTMLDivElement | null) => {
    setSearchAnchor(node);
  }, []);
  const filterRefCallback = useCallback((node: HTMLDivElement | null) => {
    setFilterAnchor(node);
  }, []);

  const tabsArray = [
    {
      label: t('approvals.pending'),
      value: approvalTabs.pending,
    },
    { label: t('approvals.history'), value: approvalTabs.history },
  ];

  const params = useMemo(
    () => ({
      q: debouncedSearch,
      limit: 10,
      order: ORDER_DEFAULT_VALUE,
      orderBy: ORDER_BY_DEFAULT_VALUE,
      role: TasksType.AGENT,
      closed: tab === approvalTabs.history,
      type: ServiceItemTypes.APPROVAL,
      ...(isPending
        ? parsePendingApprovalsFilters(
            appliedFilters as PendingApprovalsFormValues,
          )
        : parseHistoryApprovalsFilters(
            appliedFilters as HistoryApprovalsFormValues,
          )),
    }),
    [debouncedSearch, tab, isPending, appliedFilters],
  );

  useTaskCommentsUpdater({
    socket,
    params,
    event: EVENTS_SOCKETS.SERVICE_MANAGER_TASK_NEW_COMMENT,
  });

  const {
    data,
    isLoading,
    isError,
    fetchNextPage,
    hasNextPage,
    isFetching,
    isFetchingNextPage,
    isSuccess,
  } = useInfiniteQuery(
    serviceManagementKeys.tasks.list(params),
    ({ pageParam = '' }) => getTasks({ ...params, cursor: pageParam }),
    {
      getNextPageParam: lastPage => lastPage.data.cursor,
      select: response => ({
        ...response,
        pages: response.pages.map(page => page.data),
      }),
      onError: () => {
        // Prevent global error handler
      },
    },
  );
  const invalidateQueries = () => {
    queryClient.invalidateQueries(serviceManagementKeys.tasks.list(params));
  };

  const allTasks =
    data?.pages
      ?.flatMap(page => page.items)
      .filter(task =>
        tab === approvalTabs.history
          ? task.state.terminal
          : !task.state.terminal,
      ) || [];
  const noSearch = !debouncedSearch;

  const configKey = noSearch ? tab : approvalNoSearchId;
  const { emptyTitle, emptyDescription } = approvalEmptyState[configKey];
  const showList = !isLoading && !(isFetching && !isFetchingNextPage);

  const handleRowClick = (task: Task) => {
    if (!user?.isAgent)
      navigate(serviceManagementRoutes.userSide.detail(task.id), {
        state: { navigatedFromServiceMgmt: true },
      });
    else if (task.parentTask) {
      navigate(serviceManagementRoutes.agentSide.detail(task.parentTask.id), {
        state: { navigatedFromPortal: task.id },
      });
    }
  };

  const transitionTask = useMemo(() => allTasks?.[0], [allTasks]);
  const { data: states } = useQuery(
    serviceManagementKeys.states.list(transitionTask?.state.id!),
    () => getTransitionsStates(transitionTask?.state.id!),
    {
      enabled: !!transitionTask && tab === approvalTabs.pending,
      select: response => response.data,
    },
  );

  useEffect(() => {
    if (!isSuccess) return;
    if (tab === approvalTabs.pending) {
      logEvent(EventName.SERVICE_MGMT_APPROVAL_PORTAL_VIEWED, {
        user_id: user?.id,
      });
    } else {
      logEvent(EventName.SERVICE_MGMT_APPROVAL_HISTORY_VIEWED, {
        user_id: user?.id,
      });
    }
  }, [tab, isSuccess, user]);

  return (
    <HugoThemeProvider>
      <Helmet>
        <title>{formatTitle(t('approvals.portal.title'))}</title>
      </Helmet>
      <TaskFocusHeader
        slotProps={{
          root: {
            sx: {
              position: 'sticky',
            },
          },
        }}
        title={t('approvals.portal.title')}
        onBack={() => navigate(serviceManagementRoutes.servicePortal())}
      />
      <Stack
        sx={{
          p: 2,
          maxWidth: '1000px',
          mx: 'auto',
        }}
      >
        <Stack
          sx={{
            flexDirection: 'row',
            alignItems: 'center',
            py: 2,
            gap: 2,
          }}
        >
          <HuAvatar
            Icon={IconFileCheck}
            variant="circular"
            size="large"
            color="primary"
          />
          <HuTitle
            title={t('approvals.portal.title')}
            description={t('approvals.portal.description')}
            variant="L"
          />
        </Stack>
        <HuTabs
          tabs={tabsArray}
          value={tab}
          onTabChange={value => setTab(value as ApprovalTabsType)}
          defaultValue={tabsArray[0].value}
        />
        <Stack
          sx={{ flexDirection: 'row', alignItems: 'center', gap: 2, mt: 2 }}
        >
          <Stack
            ref={searchRefCallback}
            sx={{ flex: 1 }}
          >
            <HuSearch
              fullWidth
              placeholder={t('search_approval')}
              value={search}
              onChange={setSearch}
            />
          </Stack>
          <Stack ref={filterRefCallback}>
            <BadgeCountButton
              count={appliedFiltersCount}
              buttonProps={{
                variant: 'secondary',
                startIcon: <IconFilter />,
                onClick: openFilterDrawer,
              }}
            >
              {appliedFiltersCount > 0 ? t('general:filtered') : t('filter')}
            </BadgeCountButton>
          </Stack>
          <FormProvider
            {...(filtersForm as UseFormReturn<
              PendingApprovalsFormValues | HistoryApprovalsFormValues
            >)}
          >
            <ApprovalsFiltersDrawer
              open={filterDrawerOpen}
              onClose={handleCloseFilterDrawer}
              onApply={handleApplyFilters}
              onReset={handleResetFilters}
              isPending={isPending}
            />
          </FormProvider>
        </Stack>
        <ApprovalsCoachmark
          searchAnchor={searchAnchor}
          filterAnchor={filterAnchor}
          storageKeySuffix="portal"
        />
        <InfiniteList
          isLoading={isLoading}
          isSuccess={!isLoading && !isError}
          isEmpty={!allTasks.length}
          fetchNextPage={fetchNextPage}
          hasNextPage={hasNextPage}
          isFetchingNextPage={isFetchingNextPage || isFetching}
          loadingSkeleton
          sx={{ gap: 2, alignItems: 'center', mt: 2 }}
          noResultsLabel={
            <StateCard
              variant="primary"
              title={t(emptyTitle)}
              description={t(emptyDescription)}
            />
          }
          renderSkeleton={<ApprovalItemSkeleton tab={tab} />}
        >
          {showList &&
            allTasks.map(task => (
              <HuCardContainer
                key={task.id}
                padding={0}
                sx={{ width: '100%', mb: 2 }}
                onClick={() => handleRowClick(task)}
              >
                <HuListItem
                  text={{
                    title: (
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          gap: 1,
                          alignItems: 'center',
                        }}
                      >
                        {!!bubblesEnabled && task.bubbleCount > 0 && (
                          <HuBadge
                            variant="dot"
                            color="primary"
                            aria-hidden
                          />
                        )}
                        <Stack>
                          <Typography
                            variant="globalS"
                            sx={{
                              fontWeight: 'fontWeightSemiBold',
                            }}
                          >
                            {task.name}
                          </Typography>
                          <Typography
                            variant="globalXS"
                            sx={{
                              color: ({ palette }) =>
                                palette.new.text.neutral.lighter,
                            }}
                          >
                            {task.parentTask?.catalogItem.name}
                          </Typography>
                        </Stack>
                      </Stack>
                    ),
                    copetin: getApprovalPillDescription(
                      task.state,
                      getUserDisplayName(
                        task?.parentTask?.initiator!,
                        user!,
                        t,
                      ),
                      formatLocalizedDate(task?.createdAt) || '-',
                      t,
                    ),
                    description: `${getTaskID(task.parentTask!)} • ${t('approvals.requested_by_short')} ${getUserDisplayName(
                      task?.parentTask?.initiator!,
                      user!,
                      t,
                    )}`,
                  }}
                  {...(tab === approvalTabs.pending && {
                    sideContent: (
                      <ApprovalActions
                        task={task}
                        states={states || []}
                        invalidateQueries={invalidateQueries}
                        screenSource={
                          ApprovalScreenSource.APPROVALS_LIST_PORTAL
                        }
                      />
                    ),
                  })}
                  {...(tab === approvalTabs.history && {
                    sidePill: {
                      label: t(
                        `approvals.${getApprovalStateName(task.state.name)}`,
                      ),
                      type: getApprovalPillType(task.state),
                    },
                  })}
                />
              </HuCardContainer>
            ))}
        </InfiniteList>
      </Stack>
    </HugoThemeProvider>
  );
};

export default ApprovalsPortal;
