// Data-import PRESENTATION — the React bridge for Direct Upload. Wires useReducer(directReducer)
// to the application use-case + the infrastructure gateway, exposing a small action API + a live
// §5 task preview. This is the only place the machine, the use-case, and the gateway meet.

import { useCallback, useMemo, useReducer } from 'react';
import {
  directReducer,
  initialDirectMachine,
  mapFilesToTasks,
  type DataType,
  type DirectMachine,
  type StagedFile,
  type TaskPlan,
} from '../../domain';
import { runDirectUpload } from '../../application/runDirectUpload';
import { httpDirectUploadGateway } from '../../infrastructure/httpDirectUploadGateway';

/** Map a browser File to the domain StagedFile, preserving folder structure via webkitRelativePath. */
function toStagedFile(file: File): StagedFile {
  const rel = (file as File & { webkitRelativePath?: string }).webkitRelativePath || file.name;
  return { name: file.name, relativePath: rel, size: file.size, file };
}

export interface UseDirectUpload {
  machine: DirectMachine;
  /** Live §5 mapping preview of the staged files (drives the "N files → M tasks" UI). */
  taskPreview: TaskPlan[];
  selectType: (t: DataType) => void;
  toggleGroupByStudy: () => void;
  addFiles: (files: File[]) => void;
  clearFiles: () => void;
  /** Begin (from Staging) or retry (from an error state) the upload. */
  start: () => Promise<void>;
}

export function useDirectUpload(datasetId: string): UseDirectUpload {
  const [machine, dispatch] = useReducer(directReducer, initialDirectMachine);

  const selectType = useCallback((t: DataType) => dispatch({ type: 'SELECT_TYPE', dataType: t }), []);
  const toggleGroupByStudy = useCallback(() => dispatch({ type: 'TOGGLE_GROUP_BY_STUDY' }), []);
  const addFiles = useCallback((files: File[]) => dispatch({ type: 'ADD_FILES', files: files.map(toStagedFile) }), []);
  const clearFiles = useCallback(() => dispatch({ type: 'CLEAR_FILES' }), []);

  const start = useCallback(async () => {
    const s = machine.state;
    if (s === 'Staging') dispatch({ type: 'START_UPLOAD' });
    else if (s === 'UploadError' || s === 'PartialFailure') dispatch({ type: 'RETRY' });
    else return;
    await runDirectUpload({
      gateway: httpDirectUploadGateway,
      datasetId,
      context: machine.context,
      files: machine.context.files.map((f) => f.file).filter((f): f is File => Boolean(f)),
      dispatch,
    });
  }, [datasetId, machine.state, machine.context]);

  const taskPreview = useMemo(
    () =>
      machine.context.dataType
        ? mapFilesToTasks(machine.context.dataType, machine.context.groupByStudy, machine.context.files)
        : [],
    [machine.context.dataType, machine.context.groupByStudy, machine.context.files],
  );

  return { machine, taskPreview, selectType, toggleGroupByStudy, addFiles, clearFiles, start };
}
