import sys
import queue
import threading
import time

import numpy as np
import sounddevice as sd

from .model import SAMPLE_RATE, transcribe_audio
from .vad import DEFAULT_SILENCE_FRAMES, FRAME_SIZE, VADStateMachine, calibrate_silence


def stream_transcribe(processor, model, language, silence_frames=DEFAULT_SILENCE_FRAMES):
    threshold = calibrate_silence()
    vad = VADStateMachine(threshold, silence_frames=silence_frames)
    seg_queue = queue.Queue()
    stop_event = threading.Event()
    start_time = time.monotonic()

    def transcription_worker():
        while not stop_event.is_set() or not seg_queue.empty():
            try:
                seg_start, audio = seg_queue.get(timeout=0.5)
            except queue.Empty:
                continue
            minutes = int(seg_start) // 60
            seconds = int(seg_start) % 60
            text = transcribe_audio(processor, model, audio, language)
            if text.strip():
                print(f"[{minutes:02d}:{seconds:02d}] {text.strip()}")

    worker = threading.Thread(target=transcription_worker, daemon=True)
    worker.start()

    def audio_callback(indata, frames, time_info, status):
        if stop_event.is_set():
            return
        elapsed = time.monotonic() - start_time
        result = vad.process_frame(indata[:, 0].copy(), elapsed)
        if result is not None:
            seg_queue.put(result)

    print("Listening... (Ctrl+C to stop)")
    stream = sd.InputStream(
        samplerate=SAMPLE_RATE, channels=1, dtype="float32",
        callback=audio_callback, blocksize=FRAME_SIZE,
    )

    try:
        with stream:
            while True:
                time.sleep(0.1)
    except KeyboardInterrupt:
        pass

    stop_event.set()

    if vad.speaking and vad.segment:
        seg_queue.put((vad.segment_start_time, np.concatenate(vad.segment)))

    worker.join(timeout=30)
    if worker.is_alive():
        print("Warning: transcription worker did not finish in time.", file=sys.stderr)
    print("\nDone.")
