#!/usr/bin/env python3
"""
Test semantic encoding on a single audio file.

This script encodes a single audio file to verify the pipeline works correctly.
"""

import numpy as np
import os
import torchaudio

# Import encoding functions
from suno_utils.tasks.mert_25 import (
    preload_models as preload_semantic_models_,
    encode as encode_semantic,
)

# Import Audio class
from suno_utils.audio import Audio


def main():
    import argparse

    parser = argparse.ArgumentParser(
        description="Test semantic encoding on a single file"
    )
    parser.add_argument(
        "--n_codebooks",
        type=int,
        default=None,
        help="Number of codebooks to use (default: use all available)",
    )
    args = parser.parse_args()

    print("=" * 80)
    print("SINGLE FILE SEMANTIC ENCODING TEST")
    print("=" * 80)
    print()

    # Test file
    test_file = "/app2/suno/data/raw_audio_opus_v0/muFDKWH1aaY.opus"
    test_id = "muFDKWH1aaY"
    output_dir = "/home/tony/Work/tony/RealGen/test_output"
    output_file = os.path.join(output_dir, f"{test_id}.npz")

    print(f"Test file:   {test_file}")
    print(f"Output:      {output_file}")
    print(f"N codebooks: {args.n_codebooks if args.n_codebooks else 'all available'}")
    print()

    # Create output directory
    os.makedirs(output_dir, exist_ok=True)

    # Load semantic model
    print("Loading MERT-25 semantic model...")

    # IMPORTANT: Clear any cached models first to ensure we load with correct centroids
    # (suno_utils caches models by device only, not by centroids filepath)
    from suno_utils.tasks.mert_25 import clean_models

    clean_models()

    preload_semantic_models_(
        checkpoint_filepath="/app/suno/data/dpo/models/mert_25.pt",
        centroids_filepath="/app/suno/data/dpo/models/mert_25_2x4k.npy",
        # centroids_filepath="/home/minz/temp/mert_768d_centroids_4000_50.npy",
        device="cuda:0",
    )
    print("Model loaded!\n")

    # Load audio
    print("Loading audio file...")
    if not os.path.exists(test_file):
        print(f"Error: File not found: {test_file}")
        return

    # Load with torchaudio
    waveform, sample_rate = torchaudio.load(test_file)
    print(
        f"  Original: {sample_rate}Hz, {waveform.shape[0]} channels, {waveform.shape[1]/sample_rate:.2f}s"
    )

    # Convert to mono by averaging channels
    if waveform.shape[0] > 1:
        waveform = waveform.mean(dim=0, keepdim=True)

    # Resample to 24kHz
    if sample_rate != 24000:
        waveform = torchaudio.functional.resample(waveform, sample_rate, 24000)

    # Convert to Audio object (mono, 24kHz)
    audio = Audio.from_array_float(
        waveform.numpy().squeeze(), sample_rate=24000, max_allowed_val=100
    )
    print(f"  Converted: 24000Hz, 1 channel, {audio.duration_s:.2f}s")
    print()

    # Encode semantic codes
    print("Encoding semantic codes...")
    codes = encode_semantic(audio, device="cuda:0", n_codebooks=args.n_codebooks)
    print(f"  Encoded shape: {codes.shape}")
    print(f"  Data type: {codes.dtype}")
    print(f"  Value range: [{codes.min()}, {codes.max()}]")
    if codes.ndim == 2:
        print(f"  N codebooks used: {codes.shape[1]}")
    print()

    # Convert to int64 and save
    codes = codes.astype(np.int64)
    np.savez(output_file, codes=codes)
    print(f"Saved to: {output_file}")
    print()

    # Verify saved file
    print("Verifying saved file...")
    loaded = np.load(output_file)
    loaded_codes = loaded["codes"]
    print(f"  Loaded shape: {loaded_codes.shape}")
    print(f"  Loaded dtype: {loaded_codes.dtype}")
    print(f"  Values match: {np.array_equal(codes, loaded_codes)}")
    print()

    # Show sample codes
    print("Sample codes (first 20):")
    print(loaded_codes[:20])
    print()

    print("Sample codes (last 20):")
    print(loaded_codes[-20:])
    print()

    print("=" * 80)
    print("✓ Test completed successfully!")
    print("=" * 80)


if __name__ == "__main__":
    main()
