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

import { zodResolver } from '@hookform/resolvers/zod';
import { type TFunction } from 'i18next';
import { isEqual } from 'lodash-es';
import { useQueryState } from 'nuqs';

import {
  type CollaboratorPanelFilters,
  type CoordinatorTaskFilters,
} from 'src/pages/dashboard/serviceManagement/types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { defaultDashboardFilters, defaultTaskFilters } from '../constants';
import { createCoordinatorFiltersSchema } from '../form/schemas';
import {
  collaboratorPanelFiltersSchema,
  coordinatorTaskFiltersSchema,
} from '../types';
import {
  createFilterParser,
  resetFormToDefaults,
  trimFormValues,
} from '../utils';

export const useCoordinatorFilters = () => {
  const { t } = useLokaliseTranslation('service_management');

  const [appliedDashboardFilters, setAppliedDashboardFilters] = useQueryState(
    'dashboardFilters',
    createFilterParser<CollaboratorPanelFilters>(
      collaboratorPanelFiltersSchema,
    ).withDefault(defaultDashboardFilters),
  );

  const [appliedTaskFilters, setAppliedTaskFilters] = useQueryState(
    'taskFilters',
    createFilterParser<CoordinatorTaskFilters>(
      coordinatorTaskFiltersSchema,
    ).withDefault(defaultTaskFilters),
  );

  const dashboardFiltersForm = useForm<CollaboratorPanelFilters>({
    defaultValues: defaultDashboardFilters,
    resolver: zodResolver(createCoordinatorFiltersSchema(t as TFunction)),
    mode: 'onChange',
  });

  const taskFiltersForm = useForm<CoordinatorTaskFilters>({
    defaultValues: defaultTaskFilters,
    resolver: zodResolver(createCoordinatorFiltersSchema(t as TFunction)),
    mode: 'onChange',
  });

  const handleResetTaskFilters = useCallback(() => {
    resetFormToDefaults(taskFiltersForm, defaultTaskFilters);
  }, [taskFiltersForm]);

  const handleResetDashboardFilters = useCallback(() => {
    resetFormToDefaults(dashboardFiltersForm, defaultDashboardFilters);
  }, [dashboardFiltersForm]);

  // Clear all applied filters (URL state) and reset both forms.
  // Used when the selected help desk changes, since previously selected
  // service items, agents, and groups belong to the previous help desk.
  const clearAllAppliedFilters = useCallback(() => {
    dashboardFiltersForm.reset(defaultDashboardFilters);
    taskFiltersForm.reset(defaultTaskFilters);
    setAppliedDashboardFilters(null);
    setAppliedTaskFilters(null);
  }, [
    dashboardFiltersForm,
    taskFiltersForm,
    setAppliedDashboardFilters,
    setAppliedTaskFilters,
  ]);

  useEffect(() => {
    if (!isEqual(appliedTaskFilters, defaultTaskFilters)) {
      taskFiltersForm.reset(appliedTaskFilters);
    } else {
      handleResetTaskFilters();
    }
  }, [appliedTaskFilters, taskFiltersForm, handleResetTaskFilters]);

  useEffect(() => {
    if (!isEqual(appliedDashboardFilters, defaultDashboardFilters)) {
      dashboardFiltersForm.reset(appliedDashboardFilters);
    } else {
      handleResetDashboardFilters();
    }
  }, [
    appliedDashboardFilters,
    dashboardFiltersForm,
    handleResetDashboardFilters,
  ]);

  const minimizeFilters = <T extends CollaboratorPanelFilters>(filters: T): T =>
    ({
      ...filters,
      serviceItemsIn: filters.serviceItemsIn?.map(item => ({
        id: item.id,
        name: item.name,
      })),
      agentsIn: filters.agentsIn?.map(a => ({
        id: a.id,
        firstName: a.firstName,
        lastName: a.lastName,
        profilePicture: a.profilePicture ?? null,
        employeeInternalId: a.employeeInternalId,
      })),
      agentGroupsIn: filters.agentGroupsIn?.map(group => ({
        id: group.id,
        name: group.name,
      })),
    }) as T;

  const handleApplyDashboardFilters = () => {
    const values = dashboardFiltersForm.getValues();
    trimFormValues(values);
    if (isEqual(values, defaultDashboardFilters)) {
      setAppliedDashboardFilters(null);
    } else {
      setAppliedDashboardFilters(minimizeFilters(values));
    }
  };

  const handleApplyTaskFilters = () => {
    const values = taskFiltersForm.getValues();
    trimFormValues(values);
    if (isEqual(values, defaultTaskFilters)) {
      setAppliedTaskFilters(null);
    } else {
      const minimized = {
        ...minimizeFilters(values),
        statesIn: values.statesIn?.map(status => ({
          id: status.id,
          name: status.name,
          terminal: status.terminal,
        })),
        initiatorsIn: values.initiatorsIn?.map(initiator => ({
          id: initiator.id,
          firstName: initiator.firstName,
          lastName: initiator.lastName,
          profilePicture: initiator.profilePicture ?? null,
          employeeInternalId: initiator.employeeInternalId,
        })),
        collaboratorTypesIn: values.collaboratorTypesIn?.map(type => ({
          id: type.id,
          title: type.title,
        })),
      } as CoordinatorTaskFilters;
      setAppliedTaskFilters(minimized);
    }
  };

  const handleCloseTaskFilters = () => {
    taskFiltersForm.reset(appliedTaskFilters);
  };

  const handleCloseDashboardFilters = () => {
    dashboardFiltersForm.reset(appliedDashboardFilters);
  };

  return {
    dashboardFiltersForm,
    taskFiltersForm,
    appliedDashboardFilters,
    appliedTaskFilters,
    handleApplyDashboardFilters,
    handleApplyTaskFilters,
    handleCloseTaskFilters,
    handleCloseDashboardFilters,
    handleResetTaskFilters,
    handleResetDashboardFilters,
    clearAllAppliedFilters,
  };
};
