package com.bytelyst.platform.diagnostics

import okhttp3.*
import okhttp3.Interceptor.Chain
import okio.Buffer
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

/**
 * Network interceptor for OkHttp to capture HTTP requests/responses
 */
class NetworkInterceptor(
    private val onRequest: (DiagnosticsNetworkRequest) -> Unit
) : Interceptor {
    private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
        timeZone = TimeZone.getTimeZone("UTC")
    }

    private var isActive = false
    private lateinit var httpClient: OkHttpClient

    fun start(client: OkHttpClient) {
        this.httpClient = client
        isActive = true
    }

    fun stop() {
        isActive = false
    }

    override fun intercept(chain: Chain): Response {
        if (!isActive) {
            return chain.proceed(chain.request())
        }

        val request = chain.request()
        val requestId = generateId()
        val startTime = System.currentTimeMillis()

        // Capture request details
        val requestHeaders = mutableMapOf<String, String>()
        for (i in 0 until request.headers.size) {
            val name = request.headers.name(i)
            val value = request.headers.value(i)
            requestHeaders[name] = sanitizeHeader(value, name)
        }

        val requestBody = request.body?.let { body ->
            val buffer = Buffer()
            try {
                body.writeTo(buffer)
                buffer.readUtf8()
            } catch (e: Exception) {
                null
            }
        }

        // Proceed with request
        val response: Response
        try {
            response = chain.proceed(request)
        } catch (e: Exception) {
            // Capture failed request
            val networkRequest = DiagnosticsNetworkRequest(
                id = requestId,
                url = request.url.toString().take(2048),
                method = request.method,
                requestHeaders = requestHeaders,
                requestBody = requestBody?.take(100 * 1024), // Limit to 100KB
                startTime = dateFormat.format(Date(startTime)),
                endTime = dateFormat.format(Date()),
                durationMs = (System.currentTimeMillis() - startTime).toDouble(),
                error = e.message
            )
            onRequest(networkRequest)
            throw e
        }

        // Capture response
        val endTime = System.currentTimeMillis()
        val responseHeaders = mutableMapOf<String, String>()
        for (i in 0 until response.headers.size) {
            val name = response.headers.name(i)
            val value = response.headers.value(i)
            responseHeaders[name] = sanitizeHeader(value, name)
        }

        val networkRequest = DiagnosticsNetworkRequest(
            id = requestId,
            url = request.url.toString().take(2048),
            method = request.method,
            requestHeaders = requestHeaders,
            requestBody = requestBody?.take(100 * 1024),
            status = response.code,
            responseHeaders = responseHeaders,
            responseBody = null, // Don't capture response body (too large)
            startTime = dateFormat.format(Date(startTime)),
            endTime = dateFormat.format(Date(endTime)),
            durationMs = (endTime - startTime).toDouble(),
            error = null
        )

        onRequest(networkRequest)

        return response
    }

    private fun sanitizeHeader(value: String, key: String): String {
        val sensitivePatterns = listOf("authorization", "cookie", "token", "api-key")
        val lowerKey = key.lowercase()

        for (pattern in sensitivePatterns) {
            if (lowerKey.contains(pattern)) {
                return "[REDACTED]"
            }
        }
        return value
    }

    private fun generateId(): String {
        return "${System.currentTimeMillis()}_${UUID.randomUUID().toString().take(7)}"
    }
}
