import { type FC, useCallback, useMemo, useRef, useState } from 'react';
import { FormProvider, type UseFormReturn } from 'react-hook-form';
import { useInfiniteQuery, useQuery, useQueryClient } from 'react-query';
import { useNavigate } from 'react-router';

import { 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 HuBadge from '@material-hu/components/design-system/Badge';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuPills from '@material-hu/components/design-system/Pills';
import HuSkeleton from '@material-hu/components/design-system/Skeleton';
import StateCard from '@material-hu/components/design-system/StateCard';
import HuTable from '@material-hu/components/design-system/Table';
import HuTableBody from '@material-hu/components/design-system/Table/components/TableBody';
import HuTableCell from '@material-hu/components/design-system/Table/components/TableCell';
import HuTableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import HuTableHead from '@material-hu/components/design-system/Table/components/TableHead';
import HuTableLoader from '@material-hu/components/design-system/Table/components/TableLoader';
import HuTableRow from '@material-hu/components/design-system/Table/components/TableRow';
import HuTabs from '@material-hu/components/design-system/Tabs';
import HuTitle from '@material-hu/components/design-system/Title';

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 ApprovalsCoachmark from 'src/pages/dashboard/serviceManagement/general/ApprovalsCoachmark';
import { serviceManagementKeys } from 'src/pages/dashboard/serviceManagement/queries';
import { serviceManagementRoutes } from 'src/pages/dashboard/serviceManagement/routes';
import {
  getTasks,
  getTransitionsStates,
} from 'src/pages/dashboard/serviceManagement/services';
import {
  ApprovalScreenSource,
  ServiceItemTypes,
  type Task,
  TasksType,
} from 'src/pages/dashboard/serviceManagement/types';
import {
  getApprovalPillType,
  getApprovalStateName,
  getTaskID,
  getUserDisplayName,
  parseHistoryApprovalsFilters,
  parsePendingApprovalsFilters,
} from 'src/pages/dashboard/serviceManagement/utils';
import { FeatureFlags } from 'src/types/featureFlags';
import { formatLocalizedDate } from 'src/utils/date';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  type ApprovalTabsType,
  approvalEmptyState,
  approvalNoSearchId,
  approvalTabs,
} from '../constants';
import ApprovalsFiltersDrawer from '../general/ApprovalsFiltersDrawer';
import useApprovalsUrlState from '../hooks/useApprovalsUrlState';
import useTaskCommentsUpdater from '../hooks/useTaskCommentsUpdater';
import useTaskStateListUpdater from '../hooks/useTaskStateListUpdater';
import { ApprovalActions } from '../servicePortal/serviceItems/components/ApprovalActions';

import { ORDER_BY_DEFAULT_VALUE, ORDER_DEFAULT_VALUE } from './constants';
import {
  type HistoryApprovalsFormValues,
  type PendingApprovalsFormValues,
} from './types';

const ApprovalsSkeleton = ({ isPending }: { isPending: boolean }) =>
  Array.from({ length: 5 }, (_, index) => (
    <HuTableRow key={index}>
      <HuTableCell colSpan={3}>
        <Stack sx={{ gap: 1 }}>
          <HuSkeleton
            width={140}
            height={20}
          />
          <HuSkeleton
            width={80}
            height={12}
          />
        </Stack>
      </HuTableCell>
      <HuTableCell colSpan={2}>
        <HuSkeleton
          width={120}
          height={32}
        />
      </HuTableCell>
      <HuTableCell colSpan={2}>
        <HuSkeleton
          width={120}
          height={20}
        />
      </HuTableCell>
      <HuTableCell colSpan={2}>
        <HuSkeleton
          width={100}
          height={20}
        />
      </HuTableCell>
      <HuTableCell colSpan={3}>
        <Stack sx={{ flexDirection: 'row', gap: 1.5 }}>
          <HuSkeleton
            width={135}
            height={32}
          />
          {isPending && (
            <HuSkeleton
              width={135}
              height={32}
            />
          )}
        </Stack>
      </HuTableCell>
    </HuTableRow>
  ));

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

  const pageRef = useRef<HTMLDivElement>(null);

  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 {
    tab,
    setTab,
    isPending,
    search,
    debouncedSearch,
    setSearch,
    appliedFilters,
    appliedFiltersCount,
    filtersForm,
    filterDrawerOpen,
    openFilterDrawer,
    handleApplyFilters,
    handleResetFilters,
    handleCloseFilterDrawer,
  } = useApprovalsUrlState();

  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,
          )),
    }),
    [tab, isPending, debouncedSearch, appliedFilters],
  );

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

  const handleScrollToTop = () => {
    pageRef.current?.scrollTo({ top: 0, behavior: 'smooth' });
  };

  const { data, isLoading, fetchNextPage, isFetching, isFetchingNextPage } =
    useInfiniteQuery(
      serviceManagementKeys.tasks.list(params),
      ({ pageParam = 1 }) =>
        getTasks({ ...params, page: pageParam, usePage: true }),
      {
        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
        },
      },
    );

  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 totalCount = data?.pages?.[0]?.count ?? 0;

  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: { navigatedFromAgent: task.id },
      });
    }
  };

  const noSearch = !debouncedSearch;
  const configKey = noSearch ? tab : approvalNoSearchId;
  const { emptyTitle, emptyDescription } = approvalEmptyState[configKey];
  const showEmpty =
    !allTasks.length && !isLoading && !isFetching && !isFetchingNextPage;

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

  return (
    <HugoThemeProvider>
      <Stack
        ref={pageRef}
        sx={{
          overflow: 'auto',
          height: '100%',
          width: '100%',
          backgroundColor: ({ palette }) =>
            palette.new.background.layout.default,
          flex: 1,
        }}
      >
        <Stack
          sx={{
            position: 'sticky',
            top: 0,
            zIndex: 10,
            backgroundColor: ({ palette }) =>
              palette.new.background.layout.default,
            pt: 5,
            px: {
              xs: 8,
              md: 10,
              lg: 12,
            },
            pb: 3,
          }}
        >
          <Typography
            variant="globalL"
            fontWeight="semiBold"
          >
            {t('approvals.title')}
          </Typography>
          <HuTabs
            tabs={tabsArray}
            value={tab}
            onTabChange={value => setTab(value as ApprovalTabsType)}
            defaultValue={tabsArray[0].value}
          />
        </Stack>
        <Stack
          sx={{
            flex: 1,
            px: {
              xs: 8,
              md: 10,
              lg: 12,
            },
            pb: 5,
            gap: 2,
          }}
        >
          <Stack sx={{ flexDirection: 'row', alignItems: 'center', gap: 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="agent-workspace"
          />
          <HuTableContainer>
            <HuTable
              sx={{
                tableLayout: 'fixed',
              }}
            >
              <HuTableHead>
                <HuTableRow headerRow>
                  <HuTableCell
                    colSpan={3}
                    headerCell
                  >
                    {t('service')}
                  </HuTableCell>
                  <HuTableCell
                    colSpan={2}
                    headerCell
                  >
                    {t('approvals.step')}
                  </HuTableCell>
                  <HuTableCell
                    colSpan={2}
                    headerCell
                  >
                    {t('requester')}
                  </HuTableCell>
                  <HuTableCell
                    colSpan={isPending ? 2 : 3}
                    headerCell
                  >
                    {t(
                      isPending
                        ? 'approvals.requested'
                        : 'approvals.resolution_date',
                    )}
                  </HuTableCell>
                  {isPending && (
                    <HuTableCell
                      colSpan={3}
                      headerCell
                    />
                  )}
                  {!isPending && (
                    <HuTableCell
                      colSpan={2}
                      headerCell
                    >
                      {t('status')}
                    </HuTableCell>
                  )}
                </HuTableRow>
              </HuTableHead>
              <HuTableBody sx={{ opacity: isFetchingNextPage ? 0.5 : 1 }}>
                {isLoading && <ApprovalsSkeleton isPending={isPending} />}
                {showEmpty && (
                  <HuTableRow>
                    <HuTableCell colSpan={12}>
                      <StateCard
                        variant="primary"
                        title={t(emptyTitle)}
                        description={t(emptyDescription)}
                      />
                    </HuTableCell>
                  </HuTableRow>
                )}
                {!isLoading &&
                  !!allTasks.length &&
                  allTasks.map(task => (
                    <HuTableRow
                      key={task.id}
                      onClick={() => handleRowClick(task)}
                    >
                      <HuTableCell colSpan={3}>
                        <Stack
                          sx={{
                            flexDirection: 'row',
                            alignItems: 'center',
                            gap: 1,
                          }}
                        >
                          {!!bubblesEnabled && task.bubbleCount > 0 && (
                            <HuBadge
                              variant="dot"
                              color="primary"
                            />
                          )}
                          <HuTitle
                            variant="S"
                            withEllipsis
                            overflow="tooltip"
                            title={task.parentTask?.catalogItem.name}
                            description={getTaskID(task.parentTask!)}
                          />
                        </Stack>
                      </HuTableCell>
                      <HuTableCell colSpan={2}>
                        <HuTitle
                          description={task.name}
                          variant="M"
                          withEllipsis
                          overflow="tooltip"
                        />
                      </HuTableCell>
                      <HuTableCell colSpan={2}>
                        <Typography
                          variant="globalS"
                          sx={{
                            display: '-webkit-box',
                            WebkitBoxOrient: 'vertical',
                            WebkitLineClamp: 1,
                            overflow: 'hidden',
                          }}
                        >
                          {getUserDisplayName(
                            task.parentTask?.initiator!,
                            user!,
                            t,
                          )}
                        </Typography>
                      </HuTableCell>
                      <HuTableCell colSpan={isPending ? 2 : 3}>
                        <Typography variant="globalS">
                          {formatLocalizedDate(
                            isPending ? task.createdAt : task.updatedAt,
                          ) || '-'}
                        </Typography>
                      </HuTableCell>
                      <HuTableCell colSpan={isPending ? 3 : 2}>
                        {isPending && (
                          <ApprovalActions
                            task={task}
                            states={states || []}
                            invalidateQueries={invalidateQueries}
                            screenSource={
                              ApprovalScreenSource.APPROVALS_LIST_AGENT_WORKSPACE
                            }
                          />
                        )}
                        {!isPending && (
                          <HuPills
                            label={t(
                              `approvals.${getApprovalStateName(
                                task.state.name,
                              )}`,
                            )}
                            type={getApprovalPillType(task.state)}
                            hasIcon={false}
                          />
                        )}
                      </HuTableCell>
                    </HuTableRow>
                  ))}
              </HuTableBody>
            </HuTable>
          </HuTableContainer>
          {allTasks.length > 0 && (
            <HuTableLoader
              loadedCount={allTasks.length}
              totalCount={totalCount}
              onLoadMore={fetchNextPage}
              onScrollToTop={handleScrollToTop}
            />
          )}
        </Stack>
      </Stack>
    </HugoThemeProvider>
  );
};

export default Approvals;
