import 'dart:math';
import 'dart:typed_data';

/// Utility for trimming leading/trailing silence from PCM audio.
///
/// The heavy-lifting noise reduction is handled by [SpeechEnhancer] (GTCRN).
/// This class provides a lightweight silence trimmer to reduce data sent
/// to the backend STT.
class NoiseReducer {
  /// Trim leading and trailing silence from PCM audio.
  ///
  /// Keeps a [marginMs] buffer around detected speech boundaries.
  static Uint8List trimSilence(
    Uint8List pcm16Data, {
    int sampleRate = 16000,
    double silenceThresholdDb = -40,
    int marginMs = 200,
  }) {
    if (pcm16Data.length < 4) return pcm16Data;

    final sampleCount = pcm16Data.length ~/ 2;
    final byteData = ByteData.sublistView(pcm16Data);
    final frameSize = (sampleRate * 0.020).round();
    final marginSamples = (sampleRate * marginMs / 1000).round();

    // Convert dB threshold to amplitude
    final threshold = 32768 * pow(10, silenceThresholdDb / 20);

    // Find first non-silent frame
    int startSample = 0;
    bool foundStart = false;
    for (int i = 0; i < sampleCount - frameSize; i += frameSize) {
      double rms = 0;
      final end = min(i + frameSize, sampleCount);
      for (int j = i; j < end; j++) {
        final s = byteData.getInt16(j * 2, Endian.little).toDouble();
        rms += s * s;
      }
      rms = sqrt(rms / (end - i));
      if (rms > threshold) {
        startSample = max(0, i - marginSamples);
        foundStart = true;
        break;
      }
    }
    if (!foundStart) return Uint8List(0);

    // Find last non-silent frame
    int endSample = sampleCount;
    for (int i = sampleCount - frameSize; i >= 0; i -= frameSize) {
      double rms = 0;
      final end = min(i + frameSize, sampleCount);
      for (int j = i; j < end; j++) {
        final s = byteData.getInt16(j * 2, Endian.little).toDouble();
        rms += s * s;
      }
      rms = sqrt(rms / (end - i));
      if (rms > threshold) {
        endSample = min(sampleCount, i + frameSize + marginSamples);
        break;
      }
    }

    if (startSample >= endSample) return Uint8List(0);
    return Uint8List.sublistView(pcm16Data, startSample * 2, endSample * 2);
  }
}
