import { useCallback, useEffect, useMemo } from 'react';
import { useForm } from 'react-hook-form';

import {
  parseAsInteger,
  parseAsString,
  parseAsStringLiteral,
  useQueryStates,
} from 'nuqs';
import useHuServerTableSorting from '@material-hu/hooks/TableSorting/useHuServerTableSorting';
import { useDebounce } from '@material-hu/hooks/useDebounce';
import { type FormValues } from '@material-hu/hooks/useHuPagination';

import useSearchPaginationControllers from './useSearchPaginationControllers';

const FIRST_PAGE = 1;

type SortOrder = 'ASC' | 'DESC';

type Options = {
  defaultPage?: number;
  defaultLimit?: number;
  defaultOrder?: SortOrder;
  defaultOrderBy?: string;
  defaultSearch?: string;
};

// Slim, nuqs-based replacement for useHuPagination. Manages only page / limit
// / order / orderBy / search via the URL using partial updates so other
// nuqs-managed query params (e.g. tab, hd, dashboardFilters, taskFilters)
// are preserved across pagination, search and sort interactions.
const useTableSearchParams = ({
  defaultPage = FIRST_PAGE,
  defaultLimit = 10,
  defaultOrder = 'DESC',
  defaultOrderBy = 'CREATED_AT',
  defaultSearch = '',
}: Options = {}) => {
  const orderParser = useMemo(
    () =>
      parseAsStringLiteral<SortOrder>(['ASC', 'DESC']).withDefault(
        defaultOrder,
      ),
    [defaultOrder],
  );

  const [urlState, setUrlState] = useQueryStates({
    page: parseAsInteger.withDefault(defaultPage),
    limit: parseAsInteger.withDefault(defaultLimit),
    order: orderParser,
    orderBy: parseAsString.withDefault(defaultOrderBy),
    search: parseAsString.withDefault(defaultSearch),
  });

  const { page, limit, order, orderBy, search } = urlState;

  const debouncedQuery = useDebounce(search);

  // Local form purely to drive useHuPagination's UI components (FormSearch,
  // FormPagination, useHuServerTableSorting). It does NOT write the URL —
  // the URL is the source of truth, managed by nuqs.
  const paginationForm = useForm<FormValues>({
    defaultValues: {
      params: {
        search,
        pagination: { page, limit },
        order,
        orderBy,
      },
    },
  });
  const { setValue: setPaginationFormValue } = paginationForm;

  useEffect(() => {
    setPaginationFormValue('params', {
      search,
      pagination: { page, limit },
      order,
      orderBy,
    });
  }, [search, page, limit, order, orderBy, setPaginationFormValue]);

  const handleChangePage = useCallback(
    (newPage: number) => {
      setUrlState({ page: newPage });
    },
    [setUrlState],
  );

  const handleChangeLimit = useCallback(
    (newLimit: number) => {
      setUrlState({ limit: newLimit, page: FIRST_PAGE });
    },
    [setUrlState],
  );

  const handleChangeSearch = useCallback(
    (newSearch: string) => {
      setUrlState({ search: newSearch, page: FIRST_PAGE });
    },
    [setUrlState],
  );

  // Two-state sort cycle (ASC <-> DESC), matching SmSortDirection.
  const handleChangeSort = useCallback(
    (newOrderBy: string) => {
      const isAsc = orderBy === newOrderBy && order === 'ASC';
      setUrlState({
        orderBy: newOrderBy,
        order: isAsc ? 'DESC' : 'ASC',
        page: FIRST_PAGE,
      });
    },
    [setUrlState, order, orderBy],
  );

  const HuTableSortingHeader = useHuServerTableSorting({
    form: paginationForm,
    handleChangeSort,
  });

  const { Search, Pagination } = useSearchPaginationControllers({
    onChangeSearch: handleChangeSearch,
    onChangePage: handleChangePage,
    onChangeLimit: handleChangeLimit,
  });

  return {
    query: debouncedQuery,
    pagination: { page, limit },
    order,
    orderBy,
    Search,
    Pagination,
    HuTableSortingHeader,
    paginationForm,
  };
};

export default useTableSearchParams;
