package com.omixlab.lckcontrol.p2p.channels

import android.content.Context
import android.os.BatteryManager
import android.util.Log
import com.omixlab.lckcontrol.p2p.webrtc.WebRtcPeerManager
import com.squareup.moshi.Moshi
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ControlChannelHandler @Inject constructor(
    @ApplicationContext private val context: Context,
    private val peerManager: WebRtcPeerManager,
    private val moshi: Moshi,
) {
    companion object {
        private const val TAG = "ControlHandler"
    }

    fun handleMessage(json: String) {
        try {
            val msg = moshi.adapter(ControlMessage::class.java).fromJson(json)
            if (msg?.type != "request") return

            when (msg.method) {
                "getDeviceStatus" -> handleGetDeviceStatus(msg.id)
                "getStreamingStats" -> handleGetStreamingStats(msg.id)
                "getCortexState" -> handleGetCortexState(msg.id)
                "listFiles" -> handleListFiles(msg.id)
                "startVideoStream" -> handleStartVideoStream(msg.id)
                "stopVideoStream" -> handleStopVideoStream(msg.id)
                else -> sendError(msg.id, "Unknown method: ${msg.method}")
            }
        } catch (e: Exception) {
            Log.e(TAG, "Failed to handle message", e)
        }
    }

    private fun handleGetDeviceStatus(requestId: String) {
        val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
        val batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)

        val runtime = Runtime.getRuntime()
        val memoryUsed = runtime.totalMemory() - runtime.freeMemory()
        val memoryTotal = runtime.maxMemory()

        sendResponse(requestId, "getDeviceStatus", mapOf(
            "batteryLevel" to batteryLevel,
            "memoryUsed" to memoryUsed,
            "memoryTotal" to memoryTotal,
            "runningGame" to null,
            "streamingState" to null,
            "cortexRecording" to false,
        ))
    }

    private fun handleGetStreamingStats(requestId: String) {
        sendResponse(requestId, "getStreamingStats", mapOf(
            "bitrate" to 0,
            "fps" to 0,
            "droppedFrames" to 0,
            "duration" to 0,
        ))
    }

    private fun handleGetCortexState(requestId: String) {
        sendResponse(requestId, "getCortexState", mapOf(
            "recording" to false,
            "storageUsed" to 0,
        ))
    }

    private fun handleListFiles(requestId: String) {
        // List available clips and cortex files
        val files = mutableListOf<Map<String, Any?>>()

        val clipsDir = context.getExternalFilesDir("clips")
        clipsDir?.listFiles()?.forEach { file ->
            files.add(mapOf(
                "path" to file.absolutePath,
                "name" to file.name,
                "size" to file.length(),
                "isDirectory" to file.isDirectory,
            ))
        }

        val cortexDir = context.getExternalFilesDir("cortex")
        cortexDir?.listFiles()?.forEach { file ->
            files.add(mapOf(
                "path" to file.absolutePath,
                "name" to file.name,
                "size" to file.length(),
                "isDirectory" to file.isDirectory,
            ))
        }

        sendResponse(requestId, "listFiles", mapOf("files" to files))
    }

    private fun handleStartVideoStream(requestId: String) {
        // TODO: Connect to EncodedVideoSource and add track to peer connection
        sendResponse(requestId, "startVideoStream", mapOf("started" to true))
    }

    private fun handleStopVideoStream(requestId: String) {
        // TODO: Stop video stream
        sendResponse(requestId, "stopVideoStream", mapOf("stopped" to true))
    }

    fun sendEvent(method: String, payload: Map<String, Any?>) {
        val msg = ControlMessage(
            id = System.currentTimeMillis().toString(),
            type = "event",
            method = method,
            payload = payload,
        )
        val json = moshi.adapter(ControlMessage::class.java).toJson(msg)
        peerManager.sendControlMessage(json)
    }

    private fun sendResponse(requestId: String, method: String, payload: Map<String, Any?>) {
        val msg = ControlMessage(
            id = requestId,
            type = "response",
            method = method,
            payload = payload,
        )
        val json = moshi.adapter(ControlMessage::class.java).toJson(msg)
        peerManager.sendControlMessage(json)
    }

    private fun sendError(requestId: String, error: String) {
        val msg = ControlMessage(
            id = requestId,
            type = "response",
            error = error,
        )
        val json = moshi.adapter(ControlMessage::class.java).toJson(msg)
        peerManager.sendControlMessage(json)
    }
}
