package com.ponzischeme89.memby.data.analytics

import com.ponzischeme89.memby.data.model.GatewayJourneyEvent
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.UUID

/**
 * Builds one ordered, user-scoped foreground journey. Callers provide controlled labels;
 * this collector has no field for titles, queries, setting values or arbitrary metadata.
 */
class JourneyAnalytics(
    private val userId: String,
    private val now: () -> Long = System::currentTimeMillis,
    private val journeyId: String = UUID.randomUUID().toString(),
) {
    private val lock = Any()
    private val buffer = ArrayList<GatewayJourneyEvent>()
    private var sequence = 0
    private var ended = false

    init { track("session", "journey_start", screen = "home", feature = "app") }

    fun track(
        category: String,
        action: String,
        screen: String = "",
        feature: String = "",
        source: String = "",
        target: String = "",
        itemId: String = "",
        itemType: String = "",
        outcome: String = "",
    ) = synchronized(lock) {
        if (ended) return@synchronized
        buffer += GatewayJourneyEvent(
            userId = userId,
            journeyId = journeyId,
            sequence = sequence++,
            category = category,
            action = action,
            screen = clean(screen),
            feature = clean(feature),
            source = clean(source),
            target = clean(target),
            itemId = clean(itemId),
            itemType = clean(itemType),
            outcome = clean(outcome),
            occurredAt = timestamp(),
        )
        if (buffer.size > 200) buffer.removeAt(0)
    }

    fun end(screen: String) = synchronized(lock) {
        if (!ended) {
            track("session", "journey_end", screen = screen, feature = "app")
            ended = true
        }
    }

    fun drain(): List<GatewayJourneyEvent> = synchronized(lock) {
        val copy = buffer.toList(); buffer.clear(); copy
    }

    private fun clean(value: String): String = value.take(100).filter {
        it.isLetterOrDigit() || it == '-' || it == '_' || it == '.' || it == ':'
    }

    private fun timestamp(): String = iso8601.get()!!.format(Date(now()))

    companion object {
        private val iso8601 = object : ThreadLocal<SimpleDateFormat>() {
            override fun initialValue() = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
                timeZone = TimeZone.getTimeZone("UTC")
            }
        }
    }
}
