package dev.zxq5.chatapp.android.api

import dev.zxq5.chatapp.android.core.BASE_URL
import dev.zxq5.chatapp.android.api.model.Message
import dev.zxq5.chatapp.android.api.model.SendMessage
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import io.ktor.client.plugins.auth.Auth
import io.ktor.client.plugins.auth.providers.BearerTokens
import io.ktor.client.plugins.auth.providers.bearer
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.post
import io.ktor.client.request.prepareGet
import io.ktor.client.request.setBody
import io.ktor.client.statement.bodyAsChannel
import io.ktor.http.ContentType
import io.ktor.http.contentType
import io.ktor.serialization.kotlinx.json.json
import io.ktor.utils.io.readUTF8Line
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.json.Json

class ChatClient(private val token: String) {
    private val http = HttpClient(Android) {
        install(ContentNegotiation) {
            json(Json { ignoreUnknownKeys = true })
        }
        install(Auth) {
            bearer {
                loadTokens { BearerTokens(token, "") }
            }
        }
    }

    suspend fun sendMessage(channelId: Int, userId: Int, text: String) {
        http.post("${BASE_URL}/api/chat/$channelId") {
            contentType(ContentType.Application.Json)
            setBody(SendMessage(user_id = userId, text = text, timestamp = System.currentTimeMillis()))
        }
    }

    fun messageStream(channelId: Int): Flow<Message> = flow {
        http.prepareGet("${BASE_URL}/api/events/$channelId").execute { response ->
            val channel = response.bodyAsChannel()
            while (!channel.isClosedForRead) {
                val line = channel.readUTF8Line(256) ?: break
                if (line.startsWith("data:")) {
                    val json = line.removePrefix("data:").trim()
                    runCatching { Json.decodeFromString<Message>(json) }
                        .onSuccess { emit(it) }
                }
            }
        }
    }
}

