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

import { useDebounce } from '@material-hu/hooks/useDebounce';
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 { useAuth } from 'src/contexts/JWTContext';
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 GoalWeightsDrawer from 'src/pages/dashboard/goals/components/GoalWeightsDrawer';
import { useDefaultCycleId } from 'src/pages/dashboard/goals/hooks/useDefaultCycleId';
import { useGoalFeaturesConfig } from 'src/pages/dashboard/goals/hooks/useGoalFeaturesConfig';
import { goalsKeys } from 'src/pages/dashboard/goals/queries';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  GOALS_GOAL_CARD_LIST_ITEM_SKELETON_INDIVIDUAL_SX,
  GOALS_LIST_STACK_SX,
  MY_GOALS_PAGE_SIZE,
} from '../constants';
import { goalsRoutes } from '../routes';
import { deleteGoal, getMyGoals } from '../services';

import MyGoalsSummary from './components/MyGoalsSummary';

type MyGoalsFormValues = {
  goalCycleId: number | null;
  ownerId: number;
  fromMyGoalsPage: boolean;
  query: string;
};

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

  const form = useForm<MyGoalsFormValues>({
    defaultValues: {
      goalCycleId: goalCycleIdFromState ?? defaultCycleId ?? null,
      ownerId: user?.id || 0,
      fromMyGoalsPage: true,
      query: '',
    },
  });

  const goalCycleId = useWatch({ control: form.control, name: 'goalCycleId' });
  const query = useWatch({ control: form.control, name: 'query' });
  const debouncedQuery = useDebounce(query);

  const { pagination, setPage } = useServerPagination({
    labelRowsPerPage: t('general:rows_per_page'),
    defaultLimit: MY_GOALS_PAGE_SIZE,
    limitOptions: [MY_GOALS_PAGE_SIZE],
  });

  const {
    data: myGoalsData,
    isLoading: isAllMyGoalsLoading,
    isFetching: isAllMyGoalsFetching,
  } = useQuery(
    goalsKeys.myGoalsList(Number(goalCycleId), debouncedQuery, pagination),
    () =>
      getMyGoals(Number(goalCycleId), {
        ...pagination,
        ...(debouncedQuery ? { q: debouncedQuery } : {}),
      }),
    {
      select: r => r.data,
      enabled: !!goalCycleId,
      keepPreviousData: true,
    },
  );

  const goals = myGoalsData?.items ?? [];
  const weightedProgress = myGoalsData?.weightedProgress ?? 0;
  const totalPages = myGoalsData?.totalPages ?? 0;

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

  const loading = isAllMyGoalsLoading || isAllMyGoalsFetching;
  const shouldShowEmptyState = !loading && goals.length === 0;

  return (
    <Stack sx={{ height: '100%', gap: 3 }}>
      <FormProvider {...form}>
        <MyGoalsSummary
          loading={isAllMyGoalsLoading}
          weightedProgress={weightedProgress}
          goalsCount={goals?.length}
          isSearching={!!query}
        />
        <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 onChange={() => setPage(0)} />
        </Stack>
        <Stack sx={{ gap: 2 }}>
          <Stack
            sx={{
              flexDirection: 'row',
              justifyContent: 'space-between',
              alignItems: 'center',
            }}
          >
            <Typography
              variant="globalM"
              fontWeight="fontWeightSemiBold"
            >
              {t('general:list')}
            </Typography>
            <GoalWeightsDrawer
              goals={goals}
              goalCycleId={goalCycleId}
              ownerId={user?.id ?? 0}
              query={debouncedQuery}
              fromMyGoalsPage={true}
            />
          </Stack>
          {loading && (
            <HuList sx={GOALS_LIST_STACK_SX}>
              <HuCardContainer fullWidth>
                <HuListItemSkeleton
                  sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_INDIVIDUAL_SX}
                />
              </HuCardContainer>
              <HuCardContainer fullWidth>
                <HuListItemSkeleton
                  sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_INDIVIDUAL_SX}
                />
              </HuCardContainer>
              <HuCardContainer fullWidth>
                <HuListItemSkeleton
                  sx={GOALS_GOAL_CARD_LIST_ITEM_SKELETON_INDIVIDUAL_SX}
                />
              </HuCardContainer>
            </HuList>
          )}
          {!loading && (
            <Stack
              sx={{
                pb: 2,
                gap: 2,
              }}
            >
              {goals.length > 0 && (
                <HuList
                  sx={{
                    ...GOALS_LIST_STACK_SX,
                    pb: 2,
                  }}
                >
                  <GoalFeaturesConfigProvider
                    isApprovalFlowEnabled={isApprovalFlowEnabled}
                    isBossCanEditPublishedObjectives={
                      isBossCanEditPublishedObjectives
                    }
                  >
                    {goals.map(goal => (
                      <GoalCard
                        key={goal.id}
                        goal={goal}
                        deleteGoal={deleteMutation}
                        variant={GoalCardVariant.INDIVIDUAL}
                        customBackLink={goalsRoutes.goals()}
                        goalCycleId={goalCycleId ?? undefined}
                      />
                    ))}
                  </GoalFeaturesConfigProvider>
                </HuList>
              )}
              {shouldShowEmptyState && <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>
    </Stack>
  );
};

export default MyGoals;
