import * as React from "react";
import { FieldValues, Path, UseFormReturn, useFieldArray } from "react-hook-form";

interface UseItemsTableNavigationOptions<TFieldValues extends FieldValues> {
  /** Nombre del array de líneas en el formulario (tipo-safe) */
  name: Path<TFieldValues>;
  /** Creador de una línea vacía */
  createEmpty: () => unknown; // ajusta el tipo del item si lo conoces
  /** Primer campo editable de la fila */
  firstEditableField?: string;
}

export function useItemsTableNavigation<TFieldValues extends FieldValues = FieldValues>(
  form: UseFormReturn<TFieldValues>,
  {
    name,
    createEmpty,
    firstEditableField = "description",
  }: UseItemsTableNavigationOptions<TFieldValues>
) {
  const { control, getValues, setFocus } = form;
  const fa = useFieldArray<TFieldValues>({ control, name });

  // Desestructurar para evitar recreaciones
  const { append, insert, remove: faRemove, move } = fa;

  // Ref estable para getValues
  const getValuesRef = React.useRef(getValues);
  getValuesRef.current = getValues;

  const length = React.useCallback(() => {
    const arr = getValuesRef.current(name) as unknown[];
    return Array.isArray(arr) ? arr.length : 0;
  }, [name]);

  const focusRowFirstField = React.useCallback(
    (rowIndex: number) => {
      queueMicrotask(() => {
        try {
          setFocus(`${name}.${rowIndex}.${firstEditableField}` as any, {
            shouldSelect: true,
          });
        } catch {
          // el campo aún no está montado
        }
      });
    },
    [name, firstEditableField, setFocus]
  );

  const addEmpty = React.useCallback(
    (atEnd = true, index?: number, initial?: Record<string, unknown>) => {
      const row = { ...createEmpty(), ...(initial ?? {}) };
      if (!atEnd && typeof index === "number") insert(index, row);
      else append(row);
    },
    [append, insert, createEmpty]
  );

  const duplicate = React.useCallback(
    (i: number) => {
      const curr = getValuesRef.current(`${name}.${i}`) as Record<string, unknown> | undefined;
      if (!curr) return;
      const clone =
        typeof structuredClone === "function"
          ? structuredClone(curr)
          : JSON.parse(JSON.stringify(curr));
      const { id: _id, ...sanitized } = clone;
      insert(i + 1, sanitized);
    },
    [insert, name]
  );

  const remove = React.useCallback(
    (i: number) => {
      if (i < 0 || i >= length()) return;
      faRemove(i);
    },
    [faRemove, length]
  );

  const moveUp = React.useCallback(
    (i: number) => {
      if (i <= 0) return;
      move(i, i - 1);
    },
    [move]
  );

  const moveDown = React.useCallback(
    (i: number) => {
      const len = length();
      if (i < 0 || i >= len - 1) return;
      move(i, i + 1);
    },
    [move, length]
  );

  const onTabFromLastCell = React.useCallback(
    (rowIndex: number) => {
      const len = length();
      if (rowIndex === len - 1) {
        addEmpty(true);
        focusRowFirstField(len);
      } else {
        focusRowFirstField(rowIndex + 1);
      }
    },
    [length, addEmpty, focusRowFirstField]
  );

  const onShiftTabFromFirstCell = React.useCallback(
    (rowIndex: number) => {
      if (rowIndex <= 0) return;
      focusRowFirstField(rowIndex - 1);
    },
    [focusRowFirstField]
  );

  return {
    fieldArray: fa, // { fields, append, remove, insert, move, ... }
    addEmpty,
    duplicate,
    remove,
    moveUp,
    moveDown,
    onTabFromLastCell,
    onShiftTabFromFirstCell,
    focusRowFirstField,
  };
}
