/**
 * useFormSync Hook
 */

import { useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/router';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import type { RootState } from '../stores/store';
import type { AsyncThunk } from '@reduxjs/toolkit';
import type { BaseEntity } from '../types/entities';
import type { FetchParams } from '../types/api';

interface UseFormSyncOptions<T, TFormValues> {
  entitySelector: (state: RootState) => T | T[] | undefined;
  fetchAction: AsyncThunk<unknown, FetchParams, { rejectValue: unknown }>;
  initialValues: TFormValues;
  transformEntity?: (entity: T) => TFormValues;
}

interface UseFormSyncReturn<TFormValues> {
  formValues: TFormValues;
  setFormValues: (values: TFormValues) => void;
  isLoading: boolean;
  entityId: string | undefined;
  resetForm: () => void;
}

/**
 * Hook for synchronizing form state with Redux entity data
 * Replaces the redundant triple-useEffect pattern in edit pages
 *
 * @param options - Configuration options
 * @returns Form state and management functions
 *
 * @example
 * ```typescript
 * const { formValues, isLoading, entityId } = useFormSync({
 *   entitySelector: (state) => state.users.users,
 *   fetchAction: fetch,
 *   initialValues: { firstName: '', lastName: '', email: '' },
 * })
 * ```
 */
export function useFormSync<
  T extends BaseEntity,
  TFormValues extends Record<string, unknown>,
>(options: UseFormSyncOptions<T, TFormValues>): UseFormSyncReturn<TFormValues> {
  const { entitySelector, fetchAction, initialValues, transformEntity } =
    options;

  const router = useRouter();
  const dispatch = useAppDispatch();
  const [formValues, setFormValues] = useState<TFormValues>(initialValues);
  const [isLoading, setIsLoading] = useState(false);

  // Get entity ID from router
  const entityId = router.query.id as string | undefined;

  // Get entity data from Redux
  const entityData = useAppSelector(entitySelector);

  // Fetch entity data when ID is available
  useEffect(() => {
    if (!entityId) return;

    setIsLoading(true);
    dispatch(fetchAction({ id: entityId })).finally(() => setIsLoading(false));
  }, [entityId, dispatch, fetchAction]);

  // Sync form values with fetched entity data (single useEffect replaces redundant pair)
  useEffect(() => {
    if (!entityData) return;

    // Handle both single entity and array cases
    const entity = Array.isArray(entityData) ? undefined : entityData;

    if (entity && typeof entity === 'object') {
      if (transformEntity) {
        setFormValues(transformEntity(entity));
      } else {
        // Default: merge entity data into initial values
        const newValues = { ...initialValues };
        Object.keys(initialValues).forEach((key) => {
          const entityKey = key as keyof T;
          if (entityKey in entity) {
            (newValues as Record<string, unknown>)[key] = entity[entityKey];
          }
        });
        setFormValues(newValues);
      }
    }
  }, [entityData, initialValues, transformEntity]);

  // Reset form to initial values
  const resetForm = useCallback(() => {
    setFormValues(initialValues);
  }, [initialValues]);

  return {
    formValues,
    setFormValues,
    isLoading,
    entityId,
    resetForm,
  };
}

export default useFormSync;
