import { useEffect, useState } from 'react';

import { apiErrorMessage } from '@/utils/api';

import { notify } from '../../common/notify';
import { useAppDispatch } from '../store';
import { fetchModuleInput, saveModuleInput } from '../store/modulesSlice/thunks';
import { type InputItem } from './ModuleInputForm';
import { ModuleInputSection } from './ModuleInputSection';

interface Props {
  encodedName?: boolean;
  moduleAdded: boolean;
  moduleName: string;
  onSaved: () => void;
  projectId: number | string;
}

export const ModuleInputData = ({ encodedName, moduleAdded, moduleName, onSaved, projectId }: Props) => {
  const dispatch = useAppDispatch();

  const [spec, setSpec] = useState<InputItem[] | null>(null);
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    let cancelled = false;
    // Reset per-module state so data from a previously viewed module never leaks
    // into a module that has no input spec of its own.
    setLoaded(false);
    setSpec(null);
    dispatch(fetchModuleInput({ projectId, name: moduleName, encodedName }))
      .unwrap()
      .then(data => {
        if (cancelled) return;
        const loadedSpec = (data as { input_spec?: InputItem[] })?.input_spec;
        setSpec(loadedSpec?.length ? loadedSpec : null);
        setLoaded(true);
      })
      .catch(() => {
        if (cancelled) return;
        setLoaded(true);
        notify.error('Unable to load input data for this module.');
      });
    return () => {
      cancelled = true;
    };
  }, [projectId, moduleName, encodedName, dispatch]);

  const onSave = (input: InputItem[]) =>
    dispatch(saveModuleInput({ projectId, name: moduleName, input, encodedName }))
      .unwrap()
      .then(() => {
        notify.success('Input data successfully saved.');
        onSaved();
      })
      .catch(err => {
        notify.error(apiErrorMessage(err, 'Unable to save input data.'));
        throw err;
      });

  return <ModuleInputSection spec={spec} loaded={loaded} moduleAdded={moduleAdded} onSave={onSave} />;
};
