import { FormProvider, useForm, useWatch } from 'react-hook-form';
import { useMutation, useQuery } from 'react-query';
import { useLocation } from 'react-router-dom';

import { useServerPagination } from '@material-hu/hooks/useServerPagination';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuPagination from '@material-hu/components/design-system/Inputs/Pagination';
import HuSearch from '@material-hu/components/design-system/Inputs/Search';
import HuList from '@material-hu/components/design-system/List';
import HuListItemSkeleton from '@material-hu/components/design-system/List/components/ListItemSkeleton';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { queryClient } from 'src/config/react-query';
import useGeneralError from 'src/hooks/useGeneralError';
import CycleSelector from 'src/pages/dashboard/goals/components/CycleSelector';
import GoalCard from 'src/pages/dashboard/goals/components/GoalCard';
import { GoalCardVariant } from 'src/pages/dashboard/goals/constants';
import { GoalFeaturesConfigProvider } from 'src/pages/dashboard/goals/components/GoalFeaturesConfigContext';
import GoalsEmptyState from 'src/pages/dashboard/goals/components/GoalsEmptyState';
import { useGoalFeaturesConfig } from 'src/pages/dashboard/goals/hooks/useGoalFeaturesConfig';
import { goalsKeys } from 'src/pages/dashboard/goals/queries';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  CycleValues,
  EXCLUDED_GOAL_CYCLE_IDS,
  GOALS_GOAL_CARD_LIST_ITEM_SKELETON_GENERAL_SX,
  GOALS_LIST_STACK_SX,
  SortField,
  SortOrder,
} from '../constants';
import { deleteGoal, getGoals } from '../services';

const General = () => {
  const { t } = useLokaliseTranslation('goals');
  const { enqueueSnackbar } = useHuSnackbar();
  const { isApprovalFlowEnabled, isBossCanEditPublishedObjectives } =
    useGoalFeaturesConfig();
  const showGeneralError = useGeneralError();
  const location = useLocation();
  const { state } = location;
  const goalCycleIdFromState = (state as { goalCycleId?: number })?.goalCycleId;

  const form = useForm({
    defaultValues: {
      goalCycleId: goalCycleIdFromState || CycleValues.ALL_CYCLES,
      query: '',
    },
  });
  const goalCycleId = useWatch({ control: form.control, name: 'goalCycleId' });
  const query = useWatch({ control: form.control, name: 'query' });

  const { order, orderBy, pagination, setPage } = useServerPagination({
    labelRowsPerPage: t('general:rows_per_page'),
    defaultOrderBy: SortField.ID,
    defaultOrder: SortOrder.DESC_NULLS_LAST,
  });

  const formatPagination = {
    order,
    orderBy,
    ...(query && { q: query }),
    ...pagination,
  };

  const {
    data: allGoals,
    isLoading: isLoadingAllGoals,
    isFetching: isFetchingAllGoals,
  } = useQuery(
    goalsKeys.generalList(goalCycleId, formatPagination),
    () =>
      getGoals(
        EXCLUDED_GOAL_CYCLE_IDS.has(goalCycleId) ? undefined : goalCycleId,
        formatPagination,
      ),
    {
      select: r => r.data,
      keepPreviousData: true,
      enabled: !!goalCycleId,
    },
  );

  const deleteMutation = useMutation(
    ({ id }: { id: number }) => deleteGoal(id),
    {
      onSuccess: () => {
        queryClient.invalidateQueries(
          goalsKeys.generalList(goalCycleId, formatPagination),
        );
        enqueueSnackbar({ title: t('delete.success'), variant: 'success' });
      },
      onError: err => {
        showGeneralError(err, t('delete.error'));
      },
    },
  );

  const goals = allGoals?.items || [];
  const totalPages = allGoals?.totalPages ?? 0;

  const loading = isLoadingAllGoals || isFetchingAllGoals;

  return (
    <FormProvider {...form}>
      <Stack
        sx={{
          gap: 2,
          width: '100%',
          alignContent: 'center',
          flexDirection: 'row',
        }}
      >
        <HuSearch
          label={t('general:searching')}
          placeholder={t('list.search')}
          value={query}
          onChange={value => {
            form.setValue('query', value);
            setPage(0);
          }}
        />
        <CycleSelector
          showAllAndUnassignedOptions
          onChange={() => setPage(0)}
        />
      </Stack>
      <Stack sx={{ gap: 2 }}>
        <Stack>
          <Typography
            variant="globalM"
            fontWeight="fontWeightSemiBold"
          >
            {t('general:list')}
          </Typography>
        </Stack>
        {loading && (
          <HuList sx={GOALS_LIST_STACK_SX}>
            <HuCardContainer fullWidth>
              <HuListItemSkeleton
                sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_GENERAL_SX}
              />
            </HuCardContainer>
            <HuCardContainer fullWidth>
              <HuListItemSkeleton
                sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_GENERAL_SX}
              />
            </HuCardContainer>
            <HuCardContainer fullWidth>
              <HuListItemSkeleton
                sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_GENERAL_SX}
              />
            </HuCardContainer>
          </HuList>
        )}
        {!loading && (
          <Stack
            sx={{
              pb: 2,
              gap: 2,
            }}
          >
            {goals.length > 0 && (
              <GoalFeaturesConfigProvider
                isApprovalFlowEnabled={isApprovalFlowEnabled}
                isBossCanEditPublishedObjectives={
                  isBossCanEditPublishedObjectives
                }
              >
                <HuList sx={GOALS_LIST_STACK_SX}>
                  {goals?.map(goal => (
                    <GoalCard
                      key={goal.id}
                      goal={goal}
                      deleteGoal={deleteMutation}
                      variant={GoalCardVariant.GENERAL}
                    />
                  ))}
                </HuList>
              </GoalFeaturesConfigProvider>
            )}
            {!goals.length && <GoalsEmptyState />}
            {totalPages > 1 && (
              <HuPagination
                type="basic"
                limit={pagination.limit}
                page={pagination.page + 1}
                totalPages={totalPages}
                loading={loading}
                onChangePage={newPage => setPage(newPage - 1)}
              />
            )}
          </Stack>
        )}
      </Stack>
    </FormProvider>
  );
};

export default General;
