/**
 * Detection utilities + model catalog for Lotus ML noise suppression
 * (DeepFilterNet 3 / DTLN / RNNoise / Speex). The catalog is ordered by
 * quality (and, correspondingly, CPU cost) — highest first — and drives the
 * order of the model dropdown in settings.
 */

import { DenoiseModelId } from '../state/settings';

export type DenoiseModel = {
  id: DenoiseModelId;
  name: string;
  description: string;
  cpuUsage: string;
  binarySize: string;
  transients: 'Poor' | 'Good' | 'Excellent';
  voiceQuality: 'Moderate' | 'High' | 'Very High';
};

// Ordered best-quality (highest CPU) first — this is the dropdown order.
export const DENOISE_MODELS: DenoiseModel[] = [
  {
    id: 'deepfilternet',
    name: 'DeepFilterNet 3 (beta)',
    description:
      'Studio-grade deep-learning model (48 kHz fullband, ONNX). Best quality; highest CPU and a larger one-time download.',
    cpuUsage: '25-50%',
    binarySize: '~18 MB',
    transients: 'Excellent',
    voiceQuality: 'Very High',
  },
  {
    id: 'dtln',
    name: 'DTLN (beta)',
    description:
      'Dual-signal deep-learning model (16 kHz). Strong on transient noise; moderate CPU.',
    cpuUsage: '10-20%',
    binarySize: '~4 MB',
    transients: 'Excellent',
    voiceQuality: 'High',
  },
  {
    id: 'rnnoise',
    name: 'RNNoise',
    description:
      'Lightweight hybrid model (48 kHz). Very low CPU; good for steady noise like fans, but can sound processed at full strength.',
    cpuUsage: '< 5%',
    binarySize: '< 1 MB',
    transients: 'Good',
    voiceQuality: 'Moderate',
  },
  {
    id: 'speex',
    name: 'Speex (Legacy)',
    description:
      'Classic DSP noise suppressor. Minimal CPU, gentlest on voice; weakest suppression.',
    cpuUsage: '< 2%',
    binarySize: '< 1 MB',
    transients: 'Poor',
    voiceQuality: 'Moderate',
  },
];

export const isMLDenoiseSupported = (): boolean => {
  if (typeof window === 'undefined') return false;

  // Requirements:
  // 1. AudioContext/webkitAudioContext (Web Audio API)
  // 2. AudioWorklet (Real-time processing in a background thread)
  // 3. getUserMedia (Microphone access)
  const hasAudioContext = !!(window.AudioContext || (window as any).webkitAudioContext);
  // Use `typeof` rather than `!!AudioWorkletNode`: on a browser that has
  // AudioContext but no AudioWorkletNode binding (older Safari/Edge), a bare
  // reference throws ReferenceError, making this feature-detection helper throw
  // instead of returning false.
  const hasAudioWorklet = hasAudioContext && typeof AudioWorkletNode !== 'undefined';
  const hasGetUserMedia = !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
  // Every ML model compiles WebAssembly (and DFN/DTLN load worklets via blob
  // URLs). Under a strict CSP without `wasm-unsafe-eval` (e.g. some desktop/Tauri
  // shells) WASM is unavailable, so gate on it — otherwise we'd offer ML and then
  // silently fall back to the raw mic in-call.
  const hasWasm =
    typeof WebAssembly !== 'undefined' && typeof WebAssembly.instantiate === 'function';

  return hasAudioWorklet && hasGetUserMedia && hasWasm;
};

/**
 * EXACT requirements for ML Denoise (for UI display).
 */
export const ML_DENOISE_REQUIREMENTS = [
  'Modern browser with Web Audio API support',
  'AudioWorklet support (Chrome 66+, Firefox 76+, Safari 14.1+)',
  'WebAssembly (WASM) support',
  'Microphone access',
];
