import json
import math
from pathlib import Path

import numpy as np
import soundfile as sf

root = Path.cwd()
manifest = json.loads((root / 'logs/evidence/SFX-BATCH-20261004-01/batch.json').read_text())
records = []
for request in manifest['requests']:
    for relative in request['expectedPaths']:
        audio, rate = sf.read(root / relative, dtype='float64', always_2d=True)
        mono = audio.mean(axis=1)
        rms = float(np.sqrt(np.mean(mono * mono)))
        peak = float(np.max(np.abs(mono)))
        win_size = min(8192, len(mono))
        window = np.hanning(win_size)
        spectrum = np.abs(np.fft.rfft(mono[:win_size] * window)) ** 2
        frequencies = np.fft.rfftfreq(win_size, 1 / rate)
        total = float(spectrum.sum()) or 1e-20
        centroid = float(np.sum(frequencies * spectrum) / total)
        band_energy = {
            'low_20_150_hz': float(spectrum[(frequencies >= 20) & (frequencies < 150)].sum() / total),
            'mid_150_1000_hz': float(spectrum[(frequencies >= 150) & (frequencies < 1000)].sum() / total),
            'high_1000_plus_hz': float(spectrum[frequencies >= 1000].sum() / total),
        }
        frames = mono[: len(mono) - len(mono) % 441].reshape(-1, 441)
        frame_rms = np.sqrt(np.mean(frames * frames, axis=1))
        active = np.flatnonzero(frame_rms >= max(peak * 0.01, 10 ** (-60 / 20)))
        attack_n = max(1, round(rate * 0.05))
        tail_n = max(1, round(rate * 0.1))
        records.append({
            'id': request['id'], 'path': relative, 'duration_s': len(mono) / rate,
            'rms_dbfs': 20 * math.log10(max(rms, 1e-20)),
            'peak_dbfs_mono': 20 * math.log10(max(peak, 1e-20)),
            'spectral_centroid_hz_first_0_186ms': centroid,
            **band_energy,
            'first_50ms_rms_dbfs': 20 * math.log10(max(float(np.sqrt(np.mean(mono[:attack_n] ** 2))), 1e-20)),
            'last_100ms_rms_dbfs': 20 * math.log10(max(float(np.sqrt(np.mean(mono[-tail_n:] ** 2))), 1e-20)),
            'active_span_ms_at_minus40db': (int(active[-1] - active[0] + 1) if len(active) else 0) * 10,
        })
summary = []
for request in manifest['requests']:
    takes = [x for x in records if x['id'] == request['id']]
    keys = ['rms_dbfs', 'spectral_centroid_hz_first_0_186ms', 'low_20_150_hz', 'mid_150_1000_hz', 'high_1000_plus_hz', 'active_span_ms_at_minus40db']
    summary.append({'id': request['id'], 'takes': len(takes), **{k: round(float(np.median([x[k] for x in takes])), 3) for k in keys}})
out = {'method': 'signal-feature summary only; does not assess perceived semantic match', 'takes': records, 'median_by_request': summary}
(root / 'logs/evidence/SFX-AUDIT-20261004-01/features.json').write_text(json.dumps(out, indent=2) + '\n')
print(json.dumps({'median_by_request': summary}, indent=2))
