package com.optix.android.data.repository

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.optix.android.data.local.SessionDao
import com.optix.android.data.local.entities.SessionEntity
import com.optix.android.domain.model.Session
import com.optix.android.domain.repository.SessionRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class SessionRepositoryImpl @Inject constructor(
    private val dao: SessionDao,
    private val gson: Gson,
) : SessionRepository {

    override suspend fun saveSession(session: Session): Long =
        dao.insert(session.toEntity())

    override suspend fun getSession(id: Long): Session? =
        dao.getById(id)?.toDomain()

    override fun getAllSessions(): Flow<List<Session>> =
        dao.observeAll().map { list -> list.map { it.toDomain() } }

    override fun getSessionsByTool(toolSlug: String): Flow<List<Session>> =
        dao.observeByTool(toolSlug).map { list -> list.map { it.toDomain() } }

    override suspend fun deleteSession(id: Long) = dao.deleteById(id)

    override fun exportToJson(session: Session): String = gson.toJson(session)

    override fun importFromJson(json: String): Session? = runCatching {
        gson.fromJson(json, Session::class.java)
    }.getOrNull()

    // ------------------------------------------------------------------
    // Mapping helpers
    // ------------------------------------------------------------------

    private val mapType = object : TypeToken<Map<String, String>>() {}.type
    private val listType = object : TypeToken<List<String>>() {}.type

    private fun Session.toEntity() = SessionEntity(
        id = id,
        toolName = toolName,
        toolSlug = toolSlug,
        timestamp = createdAt,
        paramsJson = gson.toJson(params),
        resultsJson = gson.toJson(results),
        logsJson = gson.toJson(logs),
        durationMs = durationMs,
    )

    private fun SessionEntity.toDomain() = Session(
        id = id,
        toolName = toolName,
        toolSlug = toolSlug,
        params = gson.fromJson(paramsJson, mapType) ?: emptyMap(),
        results = gson.fromJson(resultsJson, listType) ?: emptyList(),
        logs = gson.fromJson(logsJson, listType) ?: emptyList(),
        createdAt = timestamp,
        durationMs = durationMs,
    )
}
