package com.optix.android.ai.providers

import com.optix.android.ai.MockBrain
import com.optix.android.domain.model.AiMessage
import com.optix.android.domain.model.MessageRole
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

/**
 * Wraps [MockBrain] to satisfy the [LlmProvider] interface.
 *
 * When MockBrain returns a toolCall, this provider emits a ProviderEvent.ToolCall
 * so AiBridge actually executes the tool and returns real results inline.
 */
class OfflineProvider(val mockBrain: MockBrain) : LlmProvider {

    override suspend fun generate(messages: List<AiMessage>, schemas: List<ToolSchema>): String {
        val lastUser = messages.lastOrNull { it.role == MessageRole.USER }?.content ?: ""
        return mockBrain.respond(lastUser).text
    }

    override fun stream(messages: List<AiMessage>, schemas: List<ToolSchema>): Flow<ProviderEvent> = flow {
        val lastUser = messages.lastOrNull { it.role == MessageRole.USER }?.content ?: ""
        val response = mockBrain.respond(lastUser)

        // Emit the preamble text as streaming tokens
        if (response.text.isNotEmpty()) {
            response.text.chunked(20).forEach { chunk ->
                emit(ProviderEvent.Token(chunk))
                delay(25)
            }
        }

        // If MockBrain matched a tool, emit a ToolCall so AiBridge runs it
        response.toolCall?.let { (toolName, args) ->
            emit(ProviderEvent.Token("\n\n"))
            delay(50)
            emit(ProviderEvent.ToolCall(
                id = "offline_${toolName}_${System.currentTimeMillis()}",
                toolName = toolName,
                arguments = args,
            ))
        }

        // If MockBrain produced a chain, emit a ToolChain so AiBridge can parse+validate it
        response.chain?.let { raw ->
            emit(ProviderEvent.Token("\n\n"))
            delay(50)
            emit(ProviderEvent.ToolChain(raw = raw))
        }

        emit(ProviderEvent.Done)
    }
}
