export const DETAILED_WAVEFORM_POINTS_PER_SECOND = 400;
export const DETAILED_WAVEFORM_MIN_POINTS = 12000;
export const DETAILED_WAVEFORM_MAX_POINTS = 250000;

export function detailedWaveformSampleCount(duration, {
  pointsPerSecond = DETAILED_WAVEFORM_POINTS_PER_SECOND,
  minimum = DETAILED_WAVEFORM_MIN_POINTS,
  maximum = DETAILED_WAVEFORM_MAX_POINTS,
} = {}) {
  const seconds = Math.max(0, Number(duration) || 0);
  return Math.min(maximum, Math.max(minimum, Math.ceil(seconds * pointsPerSecond)));
}

export function detailedWaveformSources(tracks = []) {
  const sources = new Map();
  for (const track of tracks) {
    if (track?.type !== 'audio') continue;
    for (const segment of track.segments || []) {
      const audioFile = String(segment?.audioFile || '').trim();
      if (!audioFile) continue;
      const sourceDuration = Math.max(0, Number(segment.sourceDuration) || 0);
      const existing = sources.get(audioFile);
      if (!existing) {
        sources.set(audioFile, { audioFile, sourceDuration, segment });
      } else if (sourceDuration > existing.sourceDuration) {
        existing.sourceDuration = sourceDuration;
        existing.segment = segment;
      }
    }
  }
  return [...sources.values()];
}

export function detailedWaveformResponseMeetsRequest(waveform, requestedSampleCount) {
  const requested = Math.max(1, Math.floor(Number(requestedSampleCount) || 0));
  const sampleCount = Math.max(0, Math.floor(Number(waveform?.sampleCount) || 0));
  return Boolean(
    waveform?.detailed === true
    && waveform?.peaks?.length >= requested
    && sampleCount >= requested
  );
}

export function buildWaveformData(audioBuffer, bins = 12000) {
  const channel = audioBuffer.getChannelData(0);
  const samples = new Float32Array(channel);
  const sampleRate = audioBuffer.sampleRate;
  const binSize = Math.max(1, Math.floor(channel.length / bins));
  const peaks = new Float32Array(bins);

  for (let bin = 0; bin < bins; bin++) {
    let max = 0;
    const start = bin * binSize;
    const end = Math.min(channel.length, start + binSize);
    for (let index = start; index < end; index++) {
      max = Math.max(max, Math.abs(channel[index]));
    }
    peaks[bin] = max;
  }
  return { peaks, samples, sampleRate, duration: audioBuffer.duration };
}

export function normalizeWaveformResponse(data) {
  if (!Array.isArray(data?.waveform) || data.waveform.length === 0) return null;
  return {
    peaks: new Float32Array(data.waveform),
    waveform: data.waveform,
    bpm: data.bpm || null,
    detailed: data.detailed === true,
    sampleCount: Number(data.sample_count || data.waveform.length),
  };
}
