package com.example.m20_gamepad.video

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import androidx.media3.common.MediaItem
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.exoplayer.DefaultLoadControl
import androidx.media3.exoplayer.DefaultRenderersFactory
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.mediacodec.MediaCodecInfo
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
import com.example.m20_gamepad.data.VideoResizeMode

/**
 * 视频解码器选择策略。
 */
enum class VideoCodec {
    /** 自动选择（优先硬件解码） */
    AUTO,
    /** 强制硬件解码（最快，延迟优先，接受丢帧） */
    FORCE_HW,
    /** 强制软件 H.264 解码 */
    FORCE_SW_H264,
    /** 强制软件 H.265 解码 */
    FORCE_SW_H265
}

/** RTSP 播放状态 */
sealed class RtspState {
    /** 连接中 */
    object Connecting : RtspState()
    /** 播放中 */
    object Playing : RtspState()
    /** 连接失败 */
    data class Error(val message: String) : RtspState()
}

/**
 * RTSP 视频流播放 Composable。
 *
 * 使用 Media3 ExoPlayer + RTSP 扩展拉取 RTSP 流，作为全屏背景层。
 * [codec] 变化时重建播放器并应用新的解码器策略。
 * 连接失败时显示错误提示。
 *
 * @param url RTSP 流地址，如 `rtsp://10.21.31.103:554/stream`
 * @param codec 解码器选择策略
 * @param resizeMode 视频缩放模式，默认 ZOOM（等比填充全屏）
 * @param modifier 布局修饰符
 */
@Composable
fun RtspVideoPlayer(
    url: String,
    codec: VideoCodec = VideoCodec.AUTO,
    resizeMode: VideoResizeMode = VideoResizeMode.ZOOM,
    modifier: Modifier = Modifier
) {
    val context = LocalContext.current

    var state by remember { mutableStateOf<RtspState>(RtspState.Connecting) }

    // codec 变化时重建 ExoPlayer，新的 selector 在 RenderersFactory 中注入，
    // 同时使用最小缓冲策略降低延迟
    val player: ExoPlayer = remember(codec) {
        val selector = codec.toMediaCodecSelector()
        val renderersFactory = DefaultRenderersFactory(context)
        renderersFactory.setMediaCodecSelector(selector)
        val loadControl = DefaultLoadControl.Builder()
            .setBufferDurationsMs(
                200,   // minBufferMs — 必须 >= bufferForPlaybackAfterRebufferMs
                500,   // maxBufferMs
                100,   // bufferForPlaybackMs — 起播所需缓冲
                200    // bufferForPlaybackAfterRebufferMs — 重缓冲后所需缓冲
            )
            .setBackBuffer(0, false)
            .setPrioritizeTimeOverSizeThresholds(true)
            .build()
        ExoPlayer.Builder(context, renderersFactory)
            .setLoadControl(loadControl)
            .build()
            .apply {
                repeatMode = Player.REPEAT_MODE_OFF
                playWhenReady = true
                addListener(object : Player.Listener {
                    override fun onPlaybackStateChanged(playbackState: Int) {
                        state = when (playbackState) {
                            Player.STATE_BUFFERING -> RtspState.Connecting
                            Player.STATE_READY -> RtspState.Playing
                            Player.STATE_IDLE -> RtspState.Connecting
                            else -> state
                        }
                    }

                    override fun onPlayerError(error: PlaybackException) {
                        state = RtspState.Error(error.message ?: "连接失败")
                    }
                })
            }
    }

    // URL 或 codec 变化时重新加载媒体源
    LaunchedEffect(url, codec) {
        if (url.isNotBlank()) {
            state = RtspState.Connecting
            val mediaItem = MediaItem.fromUri(url)
            player.setMediaItem(mediaItem)
            player.prepare()
        }
    }

    // codec 变化时释放旧播放器
    DisposableEffect(codec) {
        onDispose {
            player.release()
        }
    }

    Box(modifier = modifier) {
        // 仅在视频播放中时渲染 PlayerView，否则透出底层背景
        if (state is RtspState.Playing) {
            AndroidView(
                modifier = Modifier.fillMaxSize(),
                factory = { ctx ->
                    PlayerView(ctx).apply {
                        useController = false
                        this.resizeMode = resizeMode.toMedia3ResizeMode()
                        this.player = player
                        setShutterBackgroundColor(android.graphics.Color.TRANSPARENT)
                    }
                },
                update = { view ->
                    view.player = player
                    view.resizeMode = resizeMode.toMedia3ResizeMode()
                }
            )
        }

        // 连接中 / 错误时的提示覆盖层
        when (val s = state) {
            is RtspState.Connecting -> StatusOverlay("连接 RTSP 流中...")
            is RtspState.Error -> StatusOverlay("RTSP 连接失败: ${s.message}")
            is RtspState.Playing -> { /* 正常播放，不显示覆盖层 */ }
        }
    }
}

@Composable
private fun StatusOverlay(text: String) {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = text,
            color = Color.White
        )
    }
}

// ==================== 解码器选择器 ====================

/** MIME 类型常量 */
private const val MIME_H264 = "video/avc"
private const val MIME_HEVC = "video/hevc"

/**
 * 将 [VideoCodec] 枚举映射为 [MediaCodecSelector]。
 *
 * - AUTO: 默认选择器（优先硬件解码）
 * - FORCE_HW: 强制硬件解码，所有 MIME 类型仅保留硬件加速解码器
 * - FORCE_SW_H264: 针对 H.264 仅保留软件解码器，其余 MIME 走默认
 * - FORCE_SW_H265: 针对 H.265/HEVC 仅保留软件解码器，其余 MIME 走默认
 */
private fun VideoCodec.toMediaCodecSelector(): MediaCodecSelector = when (this) {
    VideoCodec.AUTO -> MediaCodecSelector.DEFAULT

    VideoCodec.FORCE_HW -> forceHardware()
    VideoCodec.FORCE_SW_H264 -> forceSoftwareForMime(MIME_H264)
    VideoCodec.FORCE_SW_H265 -> forceSoftwareForMime(MIME_HEVC)
}

/**
 * 创建一个 [MediaCodecSelector]，仅对指定 [mimeType] 强制软件解码。
 * 其余 MIME 类型使用默认行为。
 */
private fun forceSoftwareForMime(targetMime: String): MediaCodecSelector = object : MediaCodecSelector {
    override fun getDecoderInfos(
        mimeType: String,
        requiresSecureDecoder: Boolean,
        requiresTunnelingDecoder: Boolean
    ): List<MediaCodecInfo> {
        val all = MediaCodecSelector.DEFAULT.getDecoderInfos(
            mimeType, requiresSecureDecoder, requiresTunnelingDecoder
        )
        // 只对目标 MIME 类型过滤，其余保持默认
        return if (mimeType == targetMime) {
            all.filter { !it.hardwareAccelerated }
        } else {
            all
        }
    }
}

/**
 * 创建一个 [MediaCodecSelector]，所有 MIME 类型仅保留硬件加速解码器。
 * 用于强制硬件解码模式（延迟优先）。
 */
private fun forceHardware(): MediaCodecSelector = object : MediaCodecSelector {
    override fun getDecoderInfos(
        mimeType: String,
        requiresSecureDecoder: Boolean,
        requiresTunnelingDecoder: Boolean
    ): List<MediaCodecInfo> {
        return MediaCodecSelector.DEFAULT.getDecoderInfos(
            mimeType, requiresSecureDecoder, requiresTunnelingDecoder
        ).filter { it.hardwareAccelerated }
    }
}

// ==================== 缩放模式映射 ====================

/** 将 [VideoResizeMode] 映射为 [AspectRatioFrameLayout] 的 resizeMode 常量。 */
private fun VideoResizeMode.toMedia3ResizeMode(): Int = when (this) {
    VideoResizeMode.FIT -> AspectRatioFrameLayout.RESIZE_MODE_FIT
    VideoResizeMode.ZOOM -> AspectRatioFrameLayout.RESIZE_MODE_ZOOM
    VideoResizeMode.FILL -> AspectRatioFrameLayout.RESIZE_MODE_FILL
}