package com.bytelyst.platform

import android.content.Context
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone

/**
 * Local rotating JSON audit log.
 *
 * Writes audit entries to a JSON lines file in the app's files directory.
 * Rotates when the file exceeds [maxFileSizeBytes]. Keeps [maxFiles] rotated files.
 *
 * Mirrors the Swift BLAuditLogger API.
 */
class BLAuditLogger(
    context: Context,
    private val config: BLPlatformConfig,
    private val maxFileSizeBytes: Long = 1_000_000L,
    private val maxFiles: Int = 5,
) {
    @Serializable
    data class AuditEntry(
        val timestamp: String,
        val productId: String,
        val action: String,
        val module: String,
        val detail: String? = null,
        val userId: String? = null,
    )

    private val json = Json { encodeDefaults = true }
    private val logDir = File(context.filesDir, "audit_logs")
    private val currentFile: File
        get() = File(logDir, "${config.productId}_audit.jsonl")

    private val isoFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US).apply {
        timeZone = TimeZone.getTimeZone("UTC")
    }

    /** Thread-safe ISO timestamp — SimpleDateFormat is NOT thread-safe. */
    @Synchronized
    private fun isoNow(): String = isoFormat.format(Date())

    init {
        logDir.mkdirs()
    }

    /**
     * Log an audit event.
     */
    fun log(action: String, module: String, detail: String? = null, userId: String? = null) {
        val entry = AuditEntry(
            timestamp = isoNow(),
            productId = config.productId,
            action = action,
            module = module,
            detail = detail,
            userId = userId,
        )

        try {
            rotateIfNeeded()
            currentFile.appendText(json.encodeToString(entry) + "\n")
        } catch (_: Exception) {
            // Audit logging should never crash the app
        }
    }

    /**
     * Read all entries from the current log file.
     */
    fun readEntries(): List<AuditEntry> {
        return try {
            if (!currentFile.exists()) return emptyList()
            currentFile.readLines()
                .filter { it.isNotBlank() }
                .mapNotNull {
                    try { json.decodeFromString<AuditEntry>(it) } catch (_: Exception) { null }
                }
        } catch (_: Exception) {
            emptyList()
        }
    }

    /**
     * Clear all audit log files.
     */
    fun clear() {
        try {
            logDir.listFiles()?.forEach { it.delete() }
        } catch (_: Exception) {
            // Ignore
        }
    }

    private fun rotateIfNeeded() {
        if (!currentFile.exists() || currentFile.length() < maxFileSizeBytes) return

        // Rotate: current → .1, .1 → .2, etc.
        for (i in maxFiles downTo 1) {
            val from = if (i == 1) currentFile else File(logDir, "${config.productId}_audit.${i - 1}.jsonl")
            val to = File(logDir, "${config.productId}_audit.$i.jsonl")
            if (from.exists()) {
                to.delete()
                from.renameTo(to)
            }
        }
    }
}
