import { useCallback, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useQuery } from 'react-query';
import { useNavigate } from 'react-router';

import { isNil } from 'lodash-es';
import { useDebounce } from '@material-hu/hooks/useDebounce';
import { useServerPagination } from '@material-hu/hooks/useServerPagination';

import { getReviewsCycles } from 'src/pages/dashboard/performance/services';
import {
  type ReviewCycle,
  ReviewCycleStatus,
} from 'src/pages/dashboard/performance/types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { PerformanceCycleActions } from '../../constants';
import { performanceKeys } from '../../queries';
import { performanceRoutes } from '../../routes';

const CYCLES_PAGE_SIZE = 10;

export type PerformanceCycleRow = ReviewCycle & {
  hasPendingReviews?: boolean;
};

type SearchForm = {
  query: string;
};

export const usePerformanceCyclesList = () => {
  const navigate = useNavigate();
  const { t } = useLokaliseTranslation(['performance', 'apps']);

  const form = useForm<SearchForm>({
    defaultValues: { query: '' },
  });
  const searchQuery = form.watch('query');
  const debouncedQuery = useDebounce(searchQuery);

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

  // biome-ignore lint/correctness/useExhaustiveDependencies: reset to first page when debounced search changes
  useEffect(() => {
    setPage(0);
  }, [debouncedQuery, setPage]);

  const q = debouncedQuery.trim() || undefined;

  const { data, isLoading } = useQuery(
    performanceKeys.list(pagination.page, pagination.limit, debouncedQuery),
    () =>
      getReviewsCycles({
        page: pagination.page + 1,
        limit: pagination.limit,
        ...(q && { q }),
      }),
    { keepPreviousData: true },
  );

  const results: PerformanceCycleRow[] = data?.data?.items || [];
  const count = data?.data?.count;

  const getReviewCycleAction = useCallback(
    (row: PerformanceCycleRow) => {
      if (row.status === ReviewCycleStatus.SELECTION) {
        return {
          onClick: () => navigate(performanceRoutes.review.peer(row.id)),
          context: PerformanceCycleActions.SELECT_REVIEWERS,
        };
      }
      if (row.status === ReviewCycleStatus.FINISHED) {
        return {
          onClick: () => navigate(performanceRoutes.review.detail(row.id)),
          context: PerformanceCycleActions.FINISHED,
        };
      }
      if (!row.hasPendingReviews) {
        return {
          onClick: () => navigate(performanceRoutes.review.detail(row.id)),
          context: PerformanceCycleActions.SEE_REVIEWS,
        };
      }
      return {
        onClick: () => navigate(performanceRoutes.review.detail(row.id)),
        context: PerformanceCycleActions.IN_PROGRESS,
      };
    },
    [navigate],
  );

  const labelDisplayedRows = useCallback(
    ({
      from,
      to,
      count: tableCount,
    }: {
      from: number;
      to: number;
      count: number;
    }) =>
      `${from}–${to} ${t('pagination.of')} ${tableCount !== -1 ? tableCount : `${t('pagination.more_than')} ${to}`}`,
    [t],
  );

  const totalPages = !isNil(count) ? Math.ceil(count / pagination.limit) : 0;

  const hasActiveSearch = debouncedQuery.trim().length > 0;

  return {
    pagination,
    setPage,
    totalPages,
    results,
    count,
    isLoading,
    getReviewCycleAction,
    labelDisplayedRows,
    searchQuery,
    setSearchQuery: (value: string) => form.setValue('query', value),
    hasActiveSearch,
  };
};
