import type { MeshLabWebScript } from './scriptTypes';
import { applyFilter, MeshLoadResult } from '../wasm/meshlab-core';

export interface ScriptRunResult {
  success: boolean;
  executed: number;
  skipped: string[];
  errors: string[];
  duration: number;
}

const KNOWN_FILTERS = new Set([
  'laplacian_smooth', 'taubin_smooth', 'simplification', 'subdivision',
  'remove_duplicate_vertices', 'remove_unreferenced_vertices', 'compute_normals',
  'scale', 'translate', 'rotate', 'invert_faces',
  'colorize_gaussian_curvature', 'colorize_mean_curvature', 'color_from_quality',
  'fill_holes', 'remove_small_components', 'fix_non_manifold_edges',
  'remove_degenerate_faces', 'remove_flipped_faces', 'auto_repair',
  'parametrize_trivial', 'freeze_transform', 'reset_transform', 'estimate_normals',
]);

export async function runScript(
  script: MeshLabWebScript,
  meshHandle: number,
  onProgress?: (step: number, total: number, filterName: string) => void
): Promise<{ result: ScriptRunResult; lastMeshResult?: MeshLoadResult }> {
  const start = performance.now();
  let executed = 0;
  const skipped: string[] = [];
  const errors: string[] = [];
  let lastResult: MeshLoadResult | undefined;

  for (let i = 0; i < script.filters.length; i++) {
    const f = script.filters[i];
    onProgress?.(i + 1, script.filters.length, f.id);

    if (!KNOWN_FILTERS.has(f.id)) {
      skipped.push(f.id);
      continue;
    }

    try {
      lastResult = await applyFilter(meshHandle, f.id, f.params as Record<string, number | boolean | string>);
      executed++;
    } catch (e) {
      errors.push(`${f.id}: ${e}`);
    }
  }

  return {
    result: {
      success: errors.length === 0,
      executed,
      skipped,
      errors,
      duration: performance.now() - start,
    },
    lastMeshResult: lastResult,
  };
}
