package com.optix.android.data.repository

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.optix.android.data.local.AuditLogDao
import com.optix.android.data.local.entities.AuditLogEntity
import com.optix.android.domain.model.AuditLogEntry
import com.optix.android.domain.repository.AuditLogRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class AuditLogRepositoryImpl @Inject constructor(
    private val dao: AuditLogDao,
    private val gson: Gson,
) : AuditLogRepository {

    override suspend fun insert(entry: AuditLogEntry): Long =
        dao.insert(entry.toEntity())

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

    override suspend fun clear() = dao.clear()

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

    private fun AuditLogEntry.toEntity() = AuditLogEntity(
        id = id,
        toolName = toolName,
        toolDisplayName = toolDisplayName,
        paramsJson = gson.toJson(params),
        target = target,
        userId = userId,
        timestamp = timestamp,
        success = success,
        errorMessage = errorMessage,
        durationMs = durationMs,
    )

    private fun AuditLogEntity.toDomain() = AuditLogEntry(
        id = id,
        toolName = toolName,
        toolDisplayName = toolDisplayName,
        params = gson.fromJson(paramsJson, mapType) ?: emptyMap(),
        target = target,
        userId = userId,
        timestamp = timestamp,
        success = success,
        errorMessage = errorMessage,
        durationMs = durationMs,
    )
}
