# fonada_asr/concurrency.py
import asyncio
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Iterable, Optional, Callable, Any, List, cast

from .client import ASRClient
from .models import BatchResult, FailedTranscription, TranscribeResult

# ----------------------------------------------------------------------
# Generic Thread-based concurrency (for sync code)
# ----------------------------------------------------------------------

def run_concurrently(func: Callable[[Any], Any], items: Iterable[Any], max_workers: int = 10) -> BatchResult:
    """
    Run a synchronous function concurrently using ThreadPoolExecutor and collect successes/failures.
    """
    successes: List[Any] = []
    failures: List[FailedTranscription] = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_to_item = {executor.submit(func, item): item for item in items}
        for future in as_completed(future_to_item):
            item = future_to_item[future]
            try:
                successes.append(future.result())
            except Exception as exc:
                failures.append(FailedTranscription(file_path=str(item), error=str(exc)))
    return BatchResult(
        results=cast(List[TranscribeResult], successes),
        failed=failures,
    )

# ----------------------------------------------------------------------
# Async concurrency (for ASRClient async SDK)
# ----------------------------------------------------------------------

async def _abatch(client: ASRClient, files: Iterable[str], language_id: str, concurrency: int) -> BatchResult:
    """
    Run asynchronous batch transcription jobs concurrently.
    """
    return await client.abatch_transcribe(files, language_id, concurrency)

def send_concurrent(
    files: Iterable[str],
    language_id: str = "hi",
    concurrency: Optional[int] = None,
) -> BatchResult:
    """
    High-level convenience wrapper that automatically runs
    multiple transcriptions concurrently using the async ASRClient.
    """
    client = ASRClient()
    try:
        conc = concurrency or client.max_concurrency
        # asyncio.run handles event loop automatically
        return asyncio.run(_abatch(client, files, language_id, conc))
    finally:
        client.close()
