import {
  type Dispatch,
  type SetStateAction,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from 'react';
import { type UseFormReturn, useForm } from 'react-hook-form';

import { isEqual } from 'lodash-es';
import {
  parseAsInteger,
  parseAsString,
  parseAsStringLiteral,
  useQueryStates,
} from 'nuqs';
import useHuServerTableSorting from '@material-hu/hooks/TableSorting/useHuServerTableSorting';
import { useDebounce } from '@material-hu/hooks/useDebounce';

import { normalizeViewFilters } from 'src/pages/dashboard/serviceManagement/utils';
import {
  type FilterFormValues,
  type View,
} from 'src/pages/dashboard/serviceManagement/types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import {
  FILTERS_DEFAULT_VALUES,
  LIMIT_DEFAULT_VALUE,
  ORDER_BY_DEFAULT_VALUE,
  ORDER_DEFAULT_VALUE,
  PAGE_DEFAULT_VALUE,
} from '../agentWorkspace/constants';
import { filterFormValuesSchema } from '../agentWorkspace/types';
import {
  createFilterParser,
  parseToValidURLDate,
} from '../agentWorkspace/utils';

import useSearchPaginationControllers from './useSearchPaginationControllers';

const FIRST_PAGE = PAGE_DEFAULT_VALUE;

type SortOrder = 'ASC' | 'DESC' | 'DESC_NULLS_LAST' | '';

type PaginationFormValues = {
  params: {
    search: string;
    pagination: { page: number; limit: number };
    order: string;
    orderBy: string;
  };
};

const orderParser = parseAsStringLiteral<SortOrder>([
  'ASC',
  'DESC',
  'DESC_NULLS_LAST',
  '',
]).withDefault(ORDER_DEFAULT_VALUE as SortOrder);

const filtersParser = createFilterParser<FilterFormValues>(
  filterFormValuesSchema,
).withDefault(FILTERS_DEFAULT_VALUES);

// Strip passthrough fields from filter entities to keep the encoded URL blob
// small. Mirrors the `minimizeFilters` helper used in CoordinatorPanel.
const minimizeFilters = (filters: FilterFormValues): FilterFormValues => ({
  ...filters,
  serviceItemsIn: filters.serviceItemsIn?.map(item => ({
    id: item.id,
    name: item.name,
  })),
  statesIn: filters.statesIn?.map(state => ({
    id: state.id,
    name: state.name,
    terminal: state.terminal,
    title: state.title,
  })),
  initiatorsIn: filters.initiatorsIn?.map(initiator => ({
    id: initiator.id,
    firstName: initiator.firstName,
    lastName: initiator.lastName,
    profilePicture: initiator.profilePicture ?? null,
    employeeInternalId: initiator.employeeInternalId,
  })),
  agentsIn: filters.agentsIn?.map(agent => ({
    id: agent.id,
    firstName: agent.firstName,
    lastName: agent.lastName,
    profilePicture: agent.profilePicture ?? null,
    employeeInternalId: agent.employeeInternalId,
  })),
  initiatorCollaboratorTypesIn: filters.initiatorCollaboratorTypesIn?.map(
    type => ({
      id: type.id,
      title: type.title,
    }),
  ),
  creationDateFrom: filters.creationDateFrom
    ? parseToValidURLDate(filters.creationDateFrom)
    : null,
  creationDateTo: filters.creationDateTo
    ? parseToValidURLDate(filters.creationDateTo)
    : null,
});

const useServiceItemSearchParams = (
  setAppliedFilters: Dispatch<SetStateAction<FilterFormValues | null>>,
  form: UseFormReturn<FilterFormValues>,
  currentView?: View,
) => {
  const { t } = useLokaliseTranslation('service_management');
  const [paramsRead, setParamsRead] = useState(false);

  const [urlState, setUrlState] = useQueryStates({
    page: parseAsInteger.withDefault(FIRST_PAGE),
    limit: parseAsInteger.withDefault(LIMIT_DEFAULT_VALUE),
    order: orderParser,
    orderBy: parseAsString.withDefault(ORDER_BY_DEFAULT_VALUE),
    search: parseAsString.withDefault(''),
    filters: filtersParser,
  });

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

  const debouncedQuery = useDebounce(search);

  // Local form purely to drive useHuPagination's UI components (FormSearch,
  // FormPagination, useHuServerTableSorting). It does NOT write the URL -> all managed internally by nuqs
  const paginationForm = useForm<PaginationFormValues>({
    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 normalizedCurrentViewFilters = useMemo(() => {
    if (!currentView?.filters) return null;
    return normalizeViewFilters(currentView.filters, t);
  }, [currentView, t]);

  useEffect(() => {
    if (currentView?.filters) {
      setAppliedFilters(normalizedCurrentViewFilters);
    }
  }, [currentView, normalizedCurrentViewFilters, setAppliedFilters]);

  // Hydrate applied filters and the filter form once from the URL on mount.
  useEffect(() => {
    if (paramsRead) {
      return;
    }

    const hasNonDefaultFilters = !isEqual(filtersParam, FILTERS_DEFAULT_VALUES);
    if (hasNonDefaultFilters) {
      setAppliedFilters(filtersParam);
      form.reset({
        ...form.getValues(),
        ...filtersParam,
      });
    }

    setParamsRead(true);
  }, [paramsRead, filtersParam, form, setAppliedFilters]);

  const resetFilterParams = useCallback(() => {
    setUrlState({
      page: FIRST_PAGE,
      filters: null,
    });
  }, [setUrlState]);

  const setFilterParams = useCallback(
    (filters: FilterFormValues | null) => {
      if (!filters || isEqual(filters, FILTERS_DEFAULT_VALUES)) {
        resetFilterParams();
        return;
      }

      setUrlState({
        page: FIRST_PAGE,
        filters: minimizeFilters(filters),
      });
    },
    [setUrlState, resetFilterParams],
  );

  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],
  );

  // Three-state sort cycle, matching the original useHuPagination behaviour:
  // ASC -> DESC_NULLS_LAST -> cleared (no sort) -> ASC ...
  const handleChangeSort = useCallback(
    (newOrderBy: string) => {
      const isAsc = orderBy === newOrderBy && order === 'ASC';
      const isDesc = orderBy === newOrderBy && order === 'DESC_NULLS_LAST';
      let newOrder: SortOrder = 'ASC';
      if (isAsc) newOrder = 'DESC_NULLS_LAST';
      else if (isDesc) newOrder = '';
      setUrlState({
        orderBy: isDesc ? '' : newOrderBy,
        order: newOrder,
        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 },
    Pagination,
    HuTableSortingHeader,
    paginationForm,
    Search,
    order,
    orderBy,
    normalizedCurrentViewFilters,
    setFilterParams,
    resetFilterParams,
  };
};

export default useServiceItemSearchParams;
