@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.utils

import eu.gaudian.translator.model.SubtitleLine
import eu.gaudian.translator.model.jsonParser
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import okhttp3.OkHttpClient
import okhttp3.Request
import java.util.concurrent.TimeUnit


@Serializable
data class LanguageInfo(
    @Suppress("HardCodedStringLiteral") @SerialName("language_code")
    val languageCode: String
)

@Serializable
data class TranscriptListResponse(
    @SerialName("available_languages")
    val availableLanguages: List<LanguageInfo> = emptyList()
)

@Serializable
data class FullTranscriptResponse(
    @Suppress("HardCodedStringLiteral") @SerialName("transcript")
    val transcript: List<SubtitleLine> = emptyList()
)

/**
 * Service that talks to the external transcript backend provided in the issue description.
 * Base URL: http://23.88.48.47:5151
 */
object YouTubeExerciseService {
    private const val BASE_URL = "http://23.88.48.47:5151"

    private val client: OkHttpClient by lazy {
        OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS) // Time to establish a connection
            .readTimeout(30, TimeUnit.SECONDS)    // Time waiting for data after connection
            .writeTimeout(30, TimeUnit.SECONDS)   // Time to write data
            .build()
    }

    suspend fun listTranscripts(videoId: String): List<String> = withContext(Dispatchers.IO) {
        val url = "$BASE_URL/api/list_transcripts/$videoId"
        Log.d("url: $url")
        try {
            val request = Request.Builder().url(url).build()
            val response = client.newCall(request).execute()
            val jsonResponse = response.body.string()

            if (response.isSuccessful && jsonResponse.isNotBlank()) {
                // Parse the full object
                val transcriptListResponse = jsonParser.decodeFromString<TranscriptListResponse>(jsonResponse)
                // Extract just the language codes and return them as a List<String>
                val languageCodes = transcriptListResponse.availableLanguages.map { it.languageCode }
                Log.d("YouTubeExerciseService", "Found language codes for $videoId: $languageCodes")
                return@withContext languageCodes
            } else {
                Log.w("YouTubeExerciseService", "Failed to list transcripts for $videoId. Code: ${response.code}")
                return@withContext emptyList()
            }
        } catch (e: Exception) {
            Log.e("YouTubeExerciseService", "Error listing transcripts for $videoId", e)
            return@withContext emptyList()
        }
    }
    suspend fun getTranscript(videoId: String, languageCode: String): List<SubtitleLine> = withContext(Dispatchers.IO) {
        val url = "$BASE_URL/api/get_transcript/$videoId/$languageCode"
        Log.d("YouTubeExerciseService", "getTranscript url: $url")
        try {
            val request = Request.Builder().url(url).build()
            val response = client.newCall(request).execute()
            val jsonResponse = response.body.string()

            if (response.isSuccessful && jsonResponse.isNotBlank()) {
                Log.d("YouTubeExerciseService", "getTranscript jsonResponse: ${jsonResponse.take(2000)}")


                val fullResponse = jsonParser.decodeFromString<FullTranscriptResponse>(jsonResponse)
                val subtitles = fullResponse.transcript // Then extract the list of subtitles

                Log.d("YouTubeExerciseService", "Fetched ${subtitles.size} subtitle lines for $videoId")
                return@withContext subtitles
            } else {
                Log.w("YouTubeExerciseService", "Failed to get transcript for $videoId ($languageCode). Code: ${response.code}")
                return@withContext emptyList()
            }
        } catch (e: Exception) {
            Log.e("YouTubeExerciseService", "Error getting transcript for $videoId ($languageCode)", e)
            return@withContext emptyList()
        }
    }
}