"""Single-stream example: process a WAV file through the Sanas SDK.

Demonstrates the core flow:
  1. create_sdk -> activate_api_key (inline, returns SdkResult)
  2. create_audio_processor with an audio_pipeline_state_notify callback
  3. wait for PipelineState.RUNNING before feeding frames
  4. feed 20 ms frames at real time, then drain the buffered tail with silence
  5. save the processed audio

Environment variables
---------------------
SANAS_API_KEY      (required) licence key
SANAS_STORAGE_DIR  SDK storage directory (data + logs)     (default: ./storage)

The model, input and output WAV are command-line arguments
(--model / --input / --output).

Usage::

    python sdk_example.py --model VI_G_SE --input test_input.wav --output output.wav
"""

import argparse
import os
import sys

# wav_utils / helpers live in the same directory as this script.
_HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, _HERE)

import sanas  # noqa: E402
from helpers import PipelineWaiter, feed_and_drain, load_samples  # noqa: E402
from wav_utils import save_wav  # noqa: E402


def _run():
    parser = argparse.ArgumentParser(
        description="Process a WAV file through the Sanas SDK (single stream)."
    )
    parser.add_argument(
        "--model", default="VI_G_SE", help="ml model key (default: %(default)s)"
    )
    parser.add_argument(
        "--input",
        default="test_input.wav",
        help="input WAV path (default: %(default)s)",
    )
    parser.add_argument(
        "--output",
        default="output.wav",
        help="output WAV path (default: %(default)s)",
    )
    parser.add_argument(
        "--pcm16",
        action="store_true",
        help="negotiate L16 (raw 16-bit PCM) instead of the rate-default codec; "
        "cloud inference only (ignored for local)",
    )
    args = parser.parse_args()

    api_key = os.environ.get("SANAS_API_KEY")
    if not api_key:
        sys.exit("SANAS_API_KEY is not set.")

    storage_dir = os.environ.get("SANAS_STORAGE_DIR", "./storage")

    # --- Create + activate
    sdk = sanas.create_sdk(sanas.InitParams(storage_dir=storage_dir))
    res = sdk.activate_api_key(api_key)  # inline: blocks, returns SdkResult
    if not res.success:
        sys.exit(f"Activation failed: {res.message}")
    print(f"[activation] OK (SDK {sdk.version})")

    # --- Read input audio ---
    samples, sample_rate, channels = load_samples(args.input)
    print(f"[input] {sample_rate} Hz, {channels} ch, {len(samples) // channels} frames")

    # --- Build processor (with pipeline-state callback) ---
    waiter = PipelineWaiter(on_state=lambda s: print(f"[pipeline] {s}"))
    cloud_params = sanas.CloudInferencingParams()
    cloud_params.use_pcm16 = args.pcm16
    attrs = sanas.ProcessorAttributes(
        audio_attributes=sanas.AudioAttributes(
            sampling_rate=sample_rate,
            channels=channels,
            model_name=args.model,
            cloud_inferencing_params=cloud_params,
            audio_pipeline_state_notify=waiter.callback,
        )
    )

    with sdk.create_audio_processor(attrs) as proc:
        # The pipeline initializes asynchronously; wait for RUNNING before feeding.
        print("[pipeline] waiting for RUNNING ...")
        waiter.wait_until_running(timeout=30.0)

        def _progress(pushed, total):
            pct = 100.0 * pushed / total if total else 100.0
            print(f"\r[feed] {pct:5.1f}%", end="", flush=True)

        result = feed_and_drain(
            proc, samples, sample_rate, channels, progress=_progress
        )
        print()

    combined = result["output"]
    if combined:
        save_wav(args.output, combined, sample_rate, channels)
        print(f"[output] {len(combined) // 4} samples -> {args.output}")
    else:
        print("[output] no processed frames received.")


if __name__ == "__main__":
    _run()
