package com.joe.camera.webcam.ui

import android.annotation.SuppressLint
import android.graphics.Color as AndroidColor
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.view.WindowManager
import androidx.activity.compose.BackHandler
import androidx.camera.core.CameraSelector
import androidx.camera.view.PreviewView
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.joe.camera.webcam.MainUiState
import com.joe.camera.webcam.MainViewModel
import com.joe.camera.webcam.model.CameraState
import kotlin.math.roundToInt

private const val DARK_CSS = """
body,.kr-mobile-layout,.home-tab-bar-item{background:#212121!important}
.logo-container,.item-wrapper:has(.home-ad-flow-information),.interact-area,.float-app-button-wrp,.float-home-button-wrp,.article-praise,.may-like-art-wrp{display:none!important}
.show-login{padding-top:1rem!important}.home-tab-bar-wrap .home-tab-bar-item.active{color:#206cff!important}
.home-fixed-area-item-title,.item-title,.body-title,#body-content,#body-content blockquote{color:white!important}
.home-tab-bar-item,.item-bar,.author-name,.time{color:grey!important}
"""

@SuppressLint("SetJavaScriptEnabled")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(viewModel: MainViewModel, state: MainUiState, onMedia: () -> Unit) {
    val lifecycleOwner = LocalLifecycleOwner.current
    val context = LocalContext.current
    val positionPreferences = remember(context) { context.getSharedPreferences("floating_controls", Context.MODE_PRIVATE) }
    var webView by remember { mutableStateOf<WebView?>(null) }
    var progress by remember { mutableFloatStateOf(0f) }
    var menuExpanded by remember { mutableStateOf(false) }
    var settingsOpen by remember { mutableStateOf(false) }
    var previewOpacity by remember { mutableFloatStateOf(0.02f) }
    var previewWidth by remember { mutableFloatStateOf(80f) }
    var cameraZoom by remember { mutableFloatStateOf(0f) }
    var previewX by remember { mutableFloatStateOf(-1f) }
    var previewBottom by remember { mutableFloatStateOf(-1f) }
    var buttonX by remember { mutableFloatStateOf(positionPreferences.getFloat("menu_x", -1f)) }
    var buttonY by remember { mutableFloatStateOf(positionPreferences.getFloat("menu_y", -1f)) }
    val density = LocalDensity.current
    val activity = LocalContext.current.findActivity()

    LaunchedEffect(state.blackScreen) {
        activity?.window?.let { window ->
            window.attributes = window.attributes.apply { screenBrightness = if (state.blackScreen) 0f else WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE }
            WindowInsetsControllerCompat(window, window.decorView).apply {
                if (state.blackScreen) hide(WindowInsetsCompat.Type.systemBars()) else show(WindowInsetsCompat.Type.systemBars())
            }
        }
    }

    BackHandler {
        val view = webView
        if (view?.canGoBack() == true) view.goBack() else view?.reload()
    }

    BoxWithConstraints(Modifier.fillMaxSize().background(Color(0xFF17171A))) {
        val maxWidthPx = with(density) { maxWidth.toPx() }
        val maxHeightPx = with(density) { maxHeight.toPx() }
        val buttonSizePx = with(density) { 42.dp.toPx() }
        val previewWidthPx = with(density) { previewWidth.dp.toPx() }
        val previewHeightPx = previewWidthPx * 16f / 9f
        val previewTop = maxHeightPx - previewBottom - previewHeightPx
        LaunchedEffect(maxWidthPx, maxHeightPx) {
            if (previewX < 0f) previewX = with(density) { 100.dp.toPx() }
            if (previewBottom < 0f) previewBottom = with(density) { 150.dp.toPx() }
            if (buttonX < 0f) buttonX = maxWidthPx - buttonSizePx
            if (buttonY < 0f) buttonY = maxHeightPx * 0.7f
            buttonX = buttonX.coerceIn(0f, maxWidthPx - buttonSizePx)
            buttonY = buttonY.coerceIn(0f, maxHeightPx - buttonSizePx)
        }
        AndroidView(
            modifier = Modifier.fillMaxSize(),
            factory = { context ->
                WebView(context).apply {
                    setBackgroundColor(AndroidColor.rgb(33, 33, 33))
                    settings.javaScriptEnabled = true
                    settings.domStorageEnabled = true
                    webChromeClient = object : WebChromeClient() { override fun onProgressChanged(view: WebView?, newProgress: Int) { progress = newProgress / 100f } }
                    webViewClient = object : WebViewClient() {
                        override fun onPageFinished(view: WebView, url: String?) {
                            val escaped = DARK_CSS.replace("`", "\\`")
                            view.evaluateJavascript("document.getElementById('webcam-style')?.remove();const s=document.createElement('style');s.id='webcam-style';s.textContent=`$escaped`;document.head.appendChild(s);", null)
                        }
                    }
                    loadUrl("https://www.36kr.com/")
                    webView = this
                }
            },
        )
        if (progress in 0.001f..0.999f) LinearProgressIndicator(progress = { progress }, modifier = Modifier.fillMaxWidth().height(2.dp))

        if (!state.remoteMode) {
            AndroidView(
                modifier = Modifier
                    .offset { IntOffset(previewX.roundToInt(), previewTop.roundToInt()) }
                    .width(previewWidth.dp)
                    .aspectRatio(9f / 16f)
                    .alpha(previewOpacity)
                    .clip(RoundedCornerShape((previewWidth / 9f).dp))
                    .pointerInput(maxWidthPx, maxHeightPx, previewWidthPx, previewHeightPx) {
                        detectDragGestures { change, drag ->
                            change.consume()
                            previewX = (previewX + drag.x).coerceIn(0f, (maxWidthPx - previewWidthPx).coerceAtLeast(0f))
                            previewBottom = (previewBottom - drag.y).coerceIn(0f, (maxHeightPx - previewHeightPx).coerceAtLeast(0f))
                        }
                    },
                factory = { context ->
                    PreviewView(context).apply {
                        implementationMode = PreviewView.ImplementationMode.COMPATIBLE
                        scaleType = PreviewView.ScaleType.FILL_CENTER
                        viewModel.bindCamera(lifecycleOwner, this)
                    }
                },
            )
        }

        Box(Modifier.offset { IntOffset(buttonX.roundToInt(), buttonY.roundToInt()) }) {
            Surface(
                modifier = Modifier.size(42.dp)
                    .pointerInput(Unit) { detectTapGestures(onTap = { viewModel.toggleRecording() }, onDoubleTap = { menuExpanded = !menuExpanded }, onLongPress = { settingsOpen = true }) }
                    .pointerInput(maxWidthPx, maxHeightPx) {
                        detectDragGestures(
                            onDragEnd = {
                                buttonX = if (buttonX + buttonSizePx / 2f < maxWidthPx / 2f) 0f else maxWidthPx - buttonSizePx
                                positionPreferences.edit().putFloat("menu_x", buttonX).putFloat("menu_y", buttonY).apply()
                            },
                            onDragCancel = {
                                buttonX = if (buttonX + buttonSizePx / 2f < maxWidthPx / 2f) 0f else maxWidthPx - buttonSizePx
                                positionPreferences.edit().putFloat("menu_x", buttonX).putFloat("menu_y", buttonY).apply()
                            },
                        ) { change, drag ->
                            change.consume()
                            buttonX = (buttonX + drag.x).coerceIn(0f, maxWidthPx - buttonSizePx)
                            buttonY = (buttonY + drag.y).coerceIn(0f, maxHeightPx - buttonSizePx)
                        }
                    },
                shape = CircleShape,
                color = Color.White,
                shadowElevation = 8.dp,
            ) { Icon(Icons.Default.Menu, "控制菜单", modifier = Modifier.padding(9.dp), tint = if (state.cameraState == CameraState.RECORDING || state.cameraState == CameraState.WORKING) Color(0xFF03A9F4) else Color.Black) }
            DropdownMenu(expanded = menuExpanded, onDismissRequest = { menuExpanded = false }) {
                DropdownMenuItem(text = { Text("录像") }, leadingIcon = { Icon(Icons.Default.Videocam, null) }, onClick = { menuExpanded = false; viewModel.toggleRecording() })
                DropdownMenuItem(text = { Text("拍照") }, leadingIcon = { Icon(Icons.Default.PhotoCamera, null) }, enabled = !state.remoteMode, onClick = { menuExpanded = false; viewModel.takePicture() })
                DropdownMenuItem(text = { Text(if (state.previewPaused) "恢复预览" else "暂停预览") }, leadingIcon = { Icon(Icons.Default.Preview, null, tint = if (state.previewPaused) Color.Gray else Color(0xFF4CAF50)) }, enabled = !state.remoteMode, onClick = { menuExpanded = false; viewModel.togglePreview() })
                DropdownMenuItem(text = { Text(if (state.remoteMode) "切换为本机" else "切换为遥控") }, leadingIcon = { Icon(Icons.Default.SettingsRemote, null, tint = if (state.remoteMode) Color(0xFF4CAF50) else Color.Gray) }, onClick = { menuExpanded = false; viewModel.toggleRemoteMode() })
                DropdownMenuItem(text = { Text("媒体库") }, leadingIcon = { Icon(Icons.Default.Image, null) }, onClick = { menuExpanded = false; viewModel.loadMedia(); onMedia() })
            }
        }

        if (state.blackScreen) Box(Modifier.fillMaxSize().background(Color.Black).pointerInput(Unit) { detectTapGestures(onLongPress = { viewModel.toggleBlackScreen() }) })
    }

    if (settingsOpen) ModalBottomSheet(onDismissRequest = { settingsOpen = false }) {
        Column(Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 8.dp)) {
            Text("预览透明度 ${(previewOpacity * 100).roundToInt()}%")
            IndustrialSlider(
                value = previewOpacity,
                onValueChange = { previewOpacity = it },
                modifier = Modifier.padding(vertical = 3.dp),
            )
            Text("预览宽度 ${previewWidth.roundToInt()} dp")
            IndustrialSlider(
                value = previewWidth,
                onValueChange = { previewWidth = it },
                valueRange = 15f..360f,
                modifier = Modifier.padding(vertical = 3.dp),
            )
            Text("相机变焦 ${(cameraZoom * 100).roundToInt()}%")
            IndustrialSlider(
                value = cameraZoom,
                onValueChange = {
                    cameraZoom = it
                    viewModel.setCameraZoom(it)
                },
                modifier = Modifier.padding(vertical = 3.dp),
            )
            Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
                TextButton(onClick = { viewModel.switchLens(false) }) { Text("BACK") }
                if (viewModel.hasFrontCamera()) TextButton(onClick = { viewModel.switchLens(true) }) { Text("FRONT") }
            }
            Spacer(Modifier.height(20.dp))
        }
    }
}

private tailrec fun Context.findActivity(): Activity? = when (this) { is Activity -> this; is ContextWrapper -> baseContext.findActivity(); else -> null }
