import { type FC, useCallback, useMemo } from 'react';
import { useInfiniteQuery } from 'react-query';

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

import { type PillsProps } from '@material-hu/components/design-system/Pills';
import StateCard from '@material-hu/components/design-system/StateCard';
import { useDrawerLayer } from '@material-hu/components/layers/Drawers';

import useFeatureFlag from 'src/hooks/useFeatureFlag';
import { getApprovalTasks } from 'src/pages/dashboard/serviceManagement/services';
import {
  ServiceItemTypes,
  type Task,
  type TaskChild,
  TasksType,
} from 'src/pages/dashboard/serviceManagement/types';
import {
  getStateName,
  ServiceManagementTaskStateName,
} from 'src/pages/dashboard/serviceManagement/utils';
import { FeatureFlags } from 'src/types/featureFlags';
import { useLokaliseTranslation } from 'src/utils/i18n';

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

import useVisitTask from '../../../hooks/useVisitTask';
import { serviceManagementKeys } from '../../../queries';

import ApprovalGroupSkeleton from './Skeletons/ApprovalGroupSkeleton';
import SubtaskDrawer from './SubtaskDetailDrawer';
import TaskChildItem from './TaskChildItem';

type TasksTabProps = {
  taskData: Task;
};

export const getTaskPillType = (type: string): PillsProps['type'] => {
  const stateName = getStateName(type);
  switch (stateName) {
    case ServiceManagementTaskStateName.ASSIGNED:
      return 'highlight';
    case ServiceManagementTaskStateName.IN_PROGRESS:
      return 'info';
    case ServiceManagementTaskStateName.ON_HOLD:
      return 'warning';
    case ServiceManagementTaskStateName.CLOSED:
      return 'success';
    case ServiceManagementTaskStateName.UNASSIGNED:
      return 'neutral';
    case ServiceManagementTaskStateName.CANCELLED:
      return 'error';
    default:
      return 'neutral';
  }
};

const TasksTab: FC<TasksTabProps> = ({ taskData }) => {
  const { t } = useLokaliseTranslation('service_management');
  const { mutate: visitTaskMutate } = useVisitTask();
  const bubblesEnabled = useFeatureFlag(
    FeatureFlags.SERVICE_MANAGEMENT_BUBBLES_ENABLED,
  );

  const params = useMemo<
    Omit<
      { page: number; limit: number; role: TasksType; type: ServiceItemTypes },
      'page'
    >
  >(
    () => ({
      limit: 10,
      role: TasksType.AGENT,
      type: ServiceItemTypes.SUBTASK,
    }),
    [],
  );

  const { openDrawer, closeDrawer } = useDrawerLayer();

  const showDrawer = useCallback(
    ({ task }: { task: Task }) => {
      openDrawer({
        children: (
          <SubtaskDrawer
            parentData={{ parentTask: taskData, params }}
            taskData={task}
            onClose={closeDrawer}
          />
        ),
        title: task?.name || '',
        hasBackButton: false,
        onClose: closeDrawer,
      });
    },
    [openDrawer, closeDrawer, taskData, params],
  );

  const {
    data,
    isLoading,
    isSuccess,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(
    serviceManagementKeys.tasks.children(taskData?.id, params),
    ({ pageParam = 1 }) =>
      getApprovalTasks(taskData?.id, { ...params, page: pageParam }),
    {
      getNextPageParam: lastPage => {
        const { page, totalPages } = lastPage.data;
        return page < totalPages ? page + 1 : undefined;
      },
      select: response => ({
        ...response,
        pages: response.pages.map(page => page.data),
      }),
      onError: () => {
        // Prevent global error handler
      },
      enabled: !!taskData?.id,
      keepPreviousData: false,
    },
  );

  const taskChildren: TaskChild[] =
    data?.pages?.flatMap(page => page.items) || [];

  const handleOpen = useCallback(
    (taskChild: TaskChild) => {
      showDrawer({ task: taskChild as unknown as Task });
      // Intentionally NOT called when the flag is OFF: the `visit` endpoint
      // exists exclusively for the red-bubbles lifecycle (no analytics, audit
      // or read-state side effects beyond it). With the flag ON, the subtask
      // drawer doesn't render Comments, so we can't know `lastReadCommentId`
      // here: send `commentsViewed: true` when there are no unreads, otherwise
      // no body (backend keeps the bubble until comments are read elsewhere).
      if (!bubblesEnabled) return;
      const hasUnreads = (taskChild.unreadCommentsCount ?? 0) > 0;
      visitTaskMutate({
        taskId: taskChild.id,
        body: hasUnreads ? undefined : { commentsViewed: true },
      });
    },
    [showDrawer, visitTaskMutate, bubblesEnabled],
  );

  return (
    <Stack
      sx={{
        width: '100%',
        height: '100%',
        overflow: 'auto',
        p: 3,
        gap: 2,
        backgroundColor: theme => theme.palette.new.background.layout.default,
      }}
    >
      <Stack>
        <Typography
          variant="globalM"
          fontWeight="fontWeightSemiBold"
        >
          {t('subtasks.title')}
        </Typography>
      </Stack>
      <InfiniteList
        isLoading={isLoading}
        isSuccess={isSuccess}
        isEmpty={isSuccess && !taskChildren.length}
        fetchNextPage={fetchNextPage}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
        loadingSkeleton
        noResultsLabel={
          <StateCard
            variant="primary"
            title={t('subtasks.empty.title')}
            description={t('subtasks.empty.description')}
          />
        }
        renderSkeleton={<ApprovalGroupSkeleton />}
      >
        {taskChildren.map(taskChild => (
          <TaskChildItem
            key={taskChild.id}
            taskChild={taskChild}
            onOpen={handleOpen}
          />
        ))}
      </InfiniteList>
    </Stack>
  );
};

export default TasksTab;
