package com.za.common.speech

import android.media.MediaPlayer
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.za.common.log.LogUtil
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body
import retrofit2.http.POST
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

interface SpeechApiService {
    @POST("v1/audio/speech")
    fun textToSpeech(@Body request: JsonObject): Call<ResponseBody>
}

object CustomerSpeechManager {

    private const val BASE_URL = "http://192.168.3.129:8880/"

    private val gson: Gson by lazy {
        Gson().newBuilder()
            .setLenient()
            .create()
    }

    private val retrofit: Retrofit by lazy {
        val loggingInterceptor = HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }

        val client = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .build()

        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
            .build()
    }

    private val speechApiService: SpeechApiService by lazy {
        retrofit.create(SpeechApiService::class.java)
    }

    fun textToSpeech(input: String, destinationFile: File): Boolean {
        val requestBody = JsonObject().apply {
            addProperty("input", input)
            addProperty("voice", "zf_xiaoxiao")
            addProperty("response_format", "mp3")
            addProperty("stream", true)
            addProperty("speed", 1)
            addProperty("return_download_link", false) // Set to false to get the stream directly
            addProperty("lang_code", "z")
        }

        val call = speechApiService.textToSpeech(requestBody)
        try {
            val response = call.execute()
            LogUtil.print("CustomerSpeechManager", "response: $response")
            if (response.isSuccessful) {
                val responseBody = response.body()
                if (responseBody != null) {
                    saveToFile(responseBody, destinationFile)
                    playAudio(destinationFile)
                    return true
                }
            } else {
                LogUtil.print("CustomerSpeechManager", "Request failed: ${response.code()}")
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return false
    }

    private fun saveToFile(body: ResponseBody, destinationFile: File) {
        body.byteStream().use {
            FileOutputStream(destinationFile).buffered().use { outputStream ->
                val buffer = ByteArray(4096)
                var bytesRead: Int
                while (it.read(buffer).also { bytesRead = it } != -1) {
                    outputStream.write(buffer, 0, bytesRead)
                }
            }
        }
    }

    private fun playAudio(file: File) {
        val mediaPlayer = MediaPlayer().apply {
            try {
                setDataSource(file.absolutePath)
                prepare()
                start()
            } catch (e: IOException) {
                e.printStackTrace()
                release()
            }
        }

        mediaPlayer.setOnCompletionListener {
            it.release()
        }

        mediaPlayer.setOnErrorListener { mp, what, extra ->
            mp.release()
            false
        }
    }
}


