/*
 * Copyright (c) 2025 Element Creations Ltd.
 * Copyright 2023-2025 New Vector Ltd.
 *
 * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
 * Please see LICENSE files in the repository root for full details.
 */

package io.element.android.libraries.matrix.impl.tracing

import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.core.data.ByteUnit
import io.element.android.libraries.core.data.megaBytes
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.tracing.LogLevel
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
import io.element.android.libraries.matrix.api.tracing.TracingService
import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
import org.matrix.rustcomponents.sdk.SentryConfig
import org.matrix.rustcomponents.sdk.TracingFileConfiguration
import org.matrix.rustcomponents.sdk.reloadTracingFileWriter
import timber.log.Timber

@ContributesBinding(AppScope::class)
class RustTracingService(private val buildMeta: BuildMeta) : TracingService {
    override fun createTimberTree(target: String): Timber.Tree {
        return RustTracingTree(target = target, retrieveFromStackTrace = buildMeta.isDebuggable)
    }

    override fun updateWriteToFilesConfiguration(config: WriteToFilesConfiguration) {
        config.toTracingFileConfiguration()?.let {
            reloadTracingFileWriter(it)
        }
    }
}

private fun LogLevel.toRustLogLevel(): org.matrix.rustcomponents.sdk.LogLevel {
    return when (this) {
        LogLevel.ERROR -> org.matrix.rustcomponents.sdk.LogLevel.ERROR
        LogLevel.WARN -> org.matrix.rustcomponents.sdk.LogLevel.WARN
        LogLevel.INFO -> org.matrix.rustcomponents.sdk.LogLevel.INFO
        LogLevel.DEBUG -> org.matrix.rustcomponents.sdk.LogLevel.DEBUG
        LogLevel.TRACE -> org.matrix.rustcomponents.sdk.LogLevel.TRACE
    }
}

private fun WriteToFilesConfiguration.toTracingFileConfiguration(): TracingFileConfiguration? {
    return when (this) {
        is WriteToFilesConfiguration.Disabled -> null
        is WriteToFilesConfiguration.Enabled -> TracingFileConfiguration(
            path = directory,
            filePrefix = filenamePrefix,
            fileSuffix = filenameSuffix,
            // Have at max 100MB of logs in disk
            maxTotalSizeBytes = 100.megaBytes.into(ByteUnit.BYTES).toULong(),
            // Store up to 7 days of logs
            maxAgeSeconds = (7 * 24 * 60 * 60).toULong(),
        )
    }
}

fun TracingConfiguration.map(buildMeta: BuildMeta): org.matrix.rustcomponents.sdk.TracingConfiguration = org.matrix.rustcomponents.sdk.TracingConfiguration(
    writeToStdoutOrSystem = writesToLogcat,
    logLevel = logLevel.toRustLogLevel(),
    extraTargets = extraTargets,
    traceLogPacks = traceLogPacks.map(),
    writeToFiles = writesToFilesConfiguration.toTracingFileConfiguration(),
    sentryConfig = sdkSentryDsn?.let {
        SentryConfig(
            dsn = it,
            appVersion = buildMeta.versionName,
            appPlatform = "Android",
        )
    }
)
