make this async

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.IO;
using System.Text;
using TMPro;
using Michsky.UI.Reach;
using UnityEngine.UI;

// Response data model matching JSON output: { "text": "some transcription" }
[System.Serializable]
public class TranscriptionResponse
{
    public string text;
}

public class FastAPIAudioTranscriber : MonoBehaviour
{
    public TMP_InputField inputField;
    public string XOut;
    public bool AgentTalkMode = false;
    public Michsky.UI.Reach.Dropdown SelectedAgent;

    // URL of the FastAPI transcription endpoint
    [Tooltip("Set this to your FastAPI server's /transcribe endpoint")]
    public string apiUrl = "http://yourserver.com/transcribe";

    // Path to the audio file on the device
    [Tooltip("Local path to the audio file to transcribe")]
    public string audioFilePath;

    // Use this to start the transcription process
    public void StartTranscription()
    {
        if (string.IsNullOrEmpty(audioFilePath))
        {
            Debug.LogError("Audio file path is empty.");
            return;
        }

        if (!File.Exists(audioFilePath))
        {
            Debug.LogError("Audio file does not exist at path: " + audioFilePath);
            return;
        }

        StartCoroutine(UploadAndTranscribeCoroutine(audioFilePath));
    }

    /// <summary>
    /// New method to transcribe an audio file path and get the transcription string via callback.
    /// Does not modify existing inputField or other internal state.
    /// Usage example:
    /// StartCoroutine(TranscribeAudioFile("path/to/audio.wav", result => {
    ///     Debug.Log("Transcription result: " + result);
    /// }));
    /// </summary>
    /// <param name="path">Local file path to audio file</param>
    /// <param name="onResult">Callback to receive transcription string or null on failure</param>
    public IEnumerator TranscribeAudioFile(string path, System.Action<string> onResult)
    {
        if (string.IsNullOrEmpty(path))
        {
            Debug.LogError("Provided audio file path is empty.");
            onResult?.Invoke(null);
            yield break;
        }

        if (!File.Exists(path))
        {
            Debug.LogError("Audio file does not exist at path: " + path);
            onResult?.Invoke(null);
            yield break;
        }

        byte[] audioData = File.ReadAllBytes(path);
        if (audioData == null || audioData.Length == 0)
        {
            Debug.LogError("Failed to read audio data from file.");
            onResult?.Invoke(null);
            yield break;
        }

        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();

        formData.Add(new MultipartFormFileSection(
            "audio_file",
            audioData,
            Path.GetFileName(path),
            "audio/wav"
        ));

        formData.Add(new MultipartFormDataSection("task", "transcribe"));

        using (UnityWebRequest www = UnityWebRequest.Post(apiUrl, formData))
        {
            www.timeout = 60;
            yield return www.SendWebRequest();

#if UNITY_2020_1_OR_NEWER
            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
#else
            if (www.isNetworkError || www.isHttpError)
#endif
            {
                Debug.LogError($"Error uploading audio: {www.error}");
                Debug.LogError($"Response: {www.downloadHandler.text}");
                onResult?.Invoke(null);
            }
            else
            {
                try
                {
                    TranscriptionResponse response = JsonUtility.FromJson<TranscriptionResponse>(www.downloadHandler.text);
                    if (response != null)
                    {
                        onResult?.Invoke(response.text);
                    }
                    else
                    {
                        Debug.LogWarning("Failed to parse transcription response JSON.");
                        onResult?.Invoke(null);
                    }
                }
                catch (System.Exception ex)
                {
                    Debug.LogError("Exception parsing JSON response: " + ex.Message);
                    onResult?.Invoke(null);
                }
            }
        }
    }

    private IEnumerator UploadAndTranscribeCoroutine(string path)
    {
        // Read audio file bytes
        byte[] audioData = File.ReadAllBytes(path);
        if (audioData == null || audioData.Length == 0)
        {
            Debug.LogError("Failed to read audio data from file.");
            yield break;
        }

        // Construct multipart form data request
        List<IMultipartFormSection> formData = new List<IMultipartFormSection>();

        // Add audio_file (as UploadFile)
        formData.Add(new MultipartFormFileSection(
            "audio_file",        // field name must match FastAPI parameter
            audioData,
            Path.GetFileName(path),
            "audio/wav"          // mime type (adjust if mp3, etc.)
        ));

        // Add form field "task" with value "transcribe"
        formData.Add(new MultipartFormDataSection("task", "transcribe"));

        using (UnityWebRequest www = UnityWebRequest.Post(apiUrl, formData))
        {
            // Set a timeout if needed (seconds)
            www.timeout = 777;

            // Send request and wait for response
            yield return www.SendWebRequest();

#if UNITY_2020_1_OR_NEWER
            if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError)
#else
            if (www.isNetworkError || www.isHttpError)
#endif
            {
                Debug.LogError($"Error uploading audio: {www.error}");
                Debug.LogError($"Response: {www.downloadHandler.text}");
            }
            else
            {
                // Debug.Log("Upload complete! Response: " + www.downloadHandler.text);

                try
                {
                    // Parse JSON response
                    TranscriptionResponse response = JsonUtility.FromJson<TranscriptionResponse>(www.downloadHandler.text);
                    if (response != null)
                    {
                        if (AgentTalkMode)
                        {
                            string selectedItemName = SelectedAgent.items[SelectedAgent.selectedItemIndex].itemName;
                            XOut = "$female @" + selectedItemName + " {calm, cute, sexy, funny} " + response.text;
                            AgentTalkMode = false;
                        }
                        else
                        {
                            inputField.text = response.text; 
                        } 
                    }
                    else
                    {
                        Debug.LogWarning("Failed to parse transcription response JSON.");
                    }
                }
                catch (System.Exception ex)
                {
                    Debug.LogError("Exception parsing JSON response: " + ex.Message);
                }
            }
        }
    }
}