/*
 * Copyright 2025 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { useCallback, useState } from "react";
import { cellValuesEqual } from "../utils/editableUtils.js";
export function useEditableTable({
  editMode = "manual",
  onCellValueChanged,
  onSubmitEdits
}) {
  const [isActive, setActive] = useState(editMode === "always");
  const [cellEdits, setCellEdits] = useState({});
  const [validationErrors, setValidationErrors] = useState(new Map());
  const clearCellValidationError = useCallback(cellId => {
    setValidationErrors(prev => {
      const newErrors = new Map(prev);
      newErrors.delete(cellId);
      return newErrors;
    });
  }, []);
  const handleCellEdit = useCallback((cellId, info) => {
    // If value is changed back to original, remove it from edits. null
    // and undefined are treated as the same empty state so clearing a
    // never-set cell doesn't leave a phantom "edited" indicator. "" stays
    // a distinct value.
    if (cellValuesEqual(info.newValue, info.oldValue)) {
      setCellEdits(prev => {
        const {
          [cellId]: _,
          ...rest
        } = prev;
        return rest;
      });
    } else {
      setCellEdits(prev => ({
        ...prev,
        [cellId]: info
      }));
    }
    onCellValueChanged?.(info);
  }, [onCellValueChanged]);
  const clearEdits = useCallback(() => {
    setCellEdits({});
    setValidationErrors(new Map());
  }, []);

  // TODO(oxc type-aware): the type-aware typescript/require-await rule does not flag this (it returns a Promise); remove this disable once type-aware linting is enabled.
  // oxlint-disable-next-line require-await -- intentionally async: returns a Promise to satisfy its declared/contract type; no await needed
  const handleSubmitEdits = useCallback(async () => {
    const edits = Object.values(cellEdits);
    return onSubmitEdits ? onSubmitEdits(edits) : false;
  }, [cellEdits, onSubmitEdits]);
  const onCellValidationError = useCallback((cellId, error) => {
    setValidationErrors(prev => {
      const newErrors = new Map(prev);
      newErrors.set(cellId, error);
      return newErrors;
    });
  }, []);
  const editModeState = editMode === "always" ? {
    type: "always",
    isActive: true
  } : {
    type: "manual",
    isActive,
    setActive
  };
  return {
    cellEdits,
    onCellEdit: handleCellEdit,
    onSubmitEdits: onSubmitEdits ? handleSubmitEdits : undefined,
    clearEdits,
    editModeState,
    onCellValidationError,
    validationErrors,
    clearCellValidationError
  };
}
//# sourceMappingURL=useEditableTable.js.map