/**
 * Drag & drop local-file path (PLAN P2-1, P2-2).
 *
 * Captures HTML5 DnD events + click-to-browse on the #dropzone element,
 * validates the picked file is a supported model, and forwards valid files to
 * viewer-core's loadLocalFile. createObjectURL/revoke lifecycle is owned by
 * the viewer (per the locked Blob URL pattern in SKILL.md); this module only
 * validates + hands the File off.
 */

import { extOf } from '../viewer/modelLoader';

/** Viewer surface this module depends on (viewer-core implements loadLocalFile). */
export interface ViewerHandle {
  loadLocalFile: (file: File, sidecars?: File[]) => void;
}

/** Options for initDropzone. */
export interface DropzoneOpts {
  viewer: ViewerHandle;
  dropzone: HTMLElement;
  fileInput: HTMLInputElement;
  /** Optional error sink; defaults to console.warn. */
  onError?: (msg: string) => void;
}

/** Accept any supported model extension by name (case-insensitive). */
function isValidModel(file: File): boolean {
  return extOf(file.name) !== null;
}

/**
 * Wire up drag/drop + click-to-browse on the given dropzone.
 * Idempotent-ish: attaches listeners; caller should call once per element.
 */
export function initDropzone(opts: DropzoneOpts): void {
  const { dropzone, fileInput, viewer } = opts;
  const onError = opts.onError ?? ((msg: string) => console.warn(msg));

  // Accept multiple files at once: the first supported model is the primary,
  // the rest (e.g. a .mtl beside an .obj) ride along as sidecars.
  const handleFiles = (files: File[]): void => {
    if (!files.length) return;
    const model = files.find(isValidModel);
    if (!model) {
      onError("Unsupported file (use .glb .gltf .obj .fbx .dae .ifc)");
      return;
    }
    viewer.loadLocalFile(model, files.filter((f) => f !== model));
  };

  // --- Drag & drop ---
  // preventDefault on dragover is MANDATORY or the browser navigates to the file.
  dropzone.addEventListener("dragover", (e: DragEvent) => {
    e.preventDefault();
    dropzone.classList.add("drag");
  });

  dropzone.addEventListener("dragenter", (e: DragEvent) => {
    e.preventDefault();
    dropzone.classList.add("drag");
  });

  dropzone.addEventListener("dragleave", () => {
    dropzone.classList.remove("drag");
  });

  dropzone.addEventListener("drop", (e: DragEvent) => {
    e.preventDefault();
    dropzone.classList.remove("drag");
    handleFiles(Array.from(e.dataTransfer?.files ?? []));
  });

  // --- Click to browse (accessibility) ---
  dropzone.addEventListener("click", () => {
    fileInput.click();
  });

  fileInput.addEventListener("change", () => {
    handleFiles(Array.from(fileInput.files ?? []));
    // reset so picking the same file twice fires `change` again
    fileInput.value = "";
  });
}
