package com.lazy.emulate.ui.screens.game

import android.app.Activity
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Handler
import android.os.Looper
import android.view.PixelCopy
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.WindowManager
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.AspectRatio
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.lazy.emulate.data.PreferencesManager
import com.lazy.emulate.data.model.Game
import com.lazy.emulate.emulation.DisplayMode
import com.lazy.emulate.emulation.EmulationEngine
import com.lazy.emulate.emulation.EmulatorCore
import com.lazy.emulate.emulation.SaveSlotInfo
import com.lazy.emulate.emulation.cores.Ps1Core
import com.lazy.emulate.input.ControllerLayout
import com.lazy.emulate.input.ControllerManager
import com.lazy.emulate.input.OverlayVisibility
import com.lazy.emulate.ui.components.TouchControllerOverlay
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

@Composable
fun GameScreen(
    game: Game,
    controllerManager: ControllerManager,
    preferencesManager: PreferencesManager,
    onBack: () -> Unit
) {
    val context = LocalContext.current
    var core by remember { mutableStateOf<EmulatorCore?>(null) }
    var isPaused by remember { mutableStateOf(false) }
    var displayMode by remember { mutableStateOf(preferencesManager.displayMode) }
    var loadError by remember { mutableStateOf<String?>(null) }
    var surfaceViewRef by remember { mutableStateOf<SurfaceView?>(null) }

    // Launch menu: shown before emulation starts if saves exist
    var showLaunchMenu by remember { mutableStateOf(true) }
    var pendingLoadSlot by remember { mutableIntStateOf(-1) }

    // In-game menu
    var showGameMenu by remember { mutableStateOf(false) }
    var saveSlots by remember { mutableStateOf<List<SaveSlotInfo>>(emptyList()) }

    val activeController by controllerManager.activeController.collectAsState()
    val overlayVisibility = preferencesManager.overlayVisibility
    val showTouchControls = when (overlayVisibility) {
        OverlayVisibility.ALWAYS_SHOW -> true
        OverlayVisibility.ALWAYS_HIDE -> false
        OverlayVisibility.AUTO -> activeController == null
    }

    val layout = remember(game.consoleType) {
        ControllerLayout.defaultForConsole(game.consoleType)
    }

    // Keep the screen on while a game is on-screen. This also keeps the system out of the
    // deeper sleep / power-saving states that aggravate USB OTG selective-suspend on
    // Samsung devices, where the adapter drops every ~60-120 seconds otherwise.
    DisposableEffect(Unit) {
        val window = (context as? Activity)?.window
        window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        onDispose {
            window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }

    DisposableEffect(game.id) {
        val loaded = EmulationEngine.startGame(context, game.consoleType, game.romPath)
        if (loaded != null) {
            core = loaded
            loaded.setDisplayMode(displayMode)
            controllerManager.onButtonEvent = { button, pressed ->
                if (pressed) loaded.onButtonPressed(button) else loaded.onButtonReleased(button)
            }
            controllerManager.onAnalogEvent = { x, y, stick ->
                loaded.onAnalogStick(x, y, stick)
            }
            // Check if any saves exist to decide whether to show launch menu
            val slots = loaded.getAllSaveSlots()
            val hasSaves = slots.any { it.exists }
            if (hasSaves) {
                saveSlots = slots
                showLaunchMenu = true
            } else {
                showLaunchMenu = false
            }
        } else {
            showLaunchMenu = false
            loadError = "Failed to load game. Check that the core .so and BIOS are installed."
        }
        onDispose {
            (core as? Ps1Core)?.releaseSurface()
            EmulationEngine.stopActiveGame()
            controllerManager.onButtonEvent = null
            controllerManager.onAnalogEvent = null
        }
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black)
    ) {
        if (showLaunchMenu) {
            // Launch menu - shown before emulation starts
            LaunchMenu(
                gameTitle = game.title,
                slots = saveSlots,
                onContinue = { slot ->
                    pendingLoadSlot = slot
                    showLaunchMenu = false
                },
                onNewGame = {
                    pendingLoadSlot = -1
                    showLaunchMenu = false
                },
                onBack = onBack
            )
        } else {
            // Emulation surface
            if (core != null) {
                AndroidView(
                    factory = { ctx ->
                        SurfaceView(ctx).also { surfaceViewRef = it }.apply {
                            holder.addCallback(object : SurfaceHolder.Callback {
                                override fun surfaceCreated(holder: SurfaceHolder) {
                                    core?.setSurface(holder.surface)
                                    // Load state BEFORE starting emulation so the game's
                                    // first frame already has the restored state
                                    if (pendingLoadSlot >= 0) {
                                        core?.loadState(pendingLoadSlot)
                                        pendingLoadSlot = -1
                                    }
                                    core?.start()
                                }

                                override fun surfaceChanged(
                                    holder: SurfaceHolder, format: Int, width: Int, height: Int
                                ) {
                                }

                                override fun surfaceDestroyed(holder: SurfaceHolder) {
                                    core?.pause()
                                    (core as? Ps1Core)?.releaseSurface()
                                }
                            })
                        }
                    },
                    modifier = Modifier.fillMaxSize()
                )
            }

            // Error or placeholder message
            val msg = loadError
                ?: if (core == null || !game.consoleType.isImplemented)
                    "${game.consoleType.displayName} emulation coming soon"
                else null

            if (msg != null) {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center
                ) {
                    Text(
                        text = msg,
                        style = MaterialTheme.typography.headlineMedium,
                        color = Color.White.copy(alpha = 0.7f)
                    )
                }
            }

            // Touch controls
            if (showTouchControls && core != null && !showGameMenu) {
                TouchControllerOverlay(
                    layout = layout,
                    onButtonPressed = { core?.onButtonPressed(it) },
                    onButtonReleased = { core?.onButtonReleased(it) },
                    onAnalogStick = { x, y, stick -> core?.onAnalogStick(x, y, stick) }
                )
            }

            // HUD controls (hidden when game menu is open)
            if (!showGameMenu) {
                IconButton(
                    onClick = onBack,
                    modifier = Modifier
                        .align(Alignment.TopStart)
                        .padding(8.dp)
                ) {
                    Icon(
                        Icons.AutoMirrored.Filled.ArrowBack,
                        contentDescription = "Back",
                        tint = Color.White.copy(alpha = 0.7f)
                    )
                }

                IconButton(
                    onClick = {
                        isPaused = !isPaused
                        if (isPaused) core?.pause() else core?.resume()
                    },
                    modifier = Modifier
                        .align(Alignment.TopEnd)
                        .padding(8.dp)
                ) {
                    Icon(
                        if (isPaused) Icons.Default.PlayArrow else Icons.Default.Pause,
                        contentDescription = if (isPaused) "Resume" else "Pause",
                        tint = Color.White.copy(alpha = 0.7f)
                    )
                }

                IconButton(
                    onClick = {
                        core?.pause()
                        saveSlots = core?.getAllSaveSlots() ?: emptyList()
                        showGameMenu = true
                    },
                    modifier = Modifier
                        .align(Alignment.TopEnd)
                        .padding(top = 8.dp, end = 48.dp)
                ) {
                    Icon(
                        Icons.Default.Menu,
                        contentDescription = "Game Menu",
                        tint = Color.White.copy(alpha = 0.7f)
                    )
                }

                IconButton(
                    onClick = {
                        displayMode = displayMode.next()
                        preferencesManager.displayMode = displayMode
                        core?.setDisplayMode(displayMode)
                    },
                    modifier = Modifier
                        .align(Alignment.TopEnd)
                        .padding(top = 8.dp, end = 88.dp)
                ) {
                    Icon(
                        Icons.Default.AspectRatio,
                        contentDescription = "Display: ${displayMode.label}",
                        tint = Color.White.copy(alpha = 0.7f)
                    )
                }
            }

            // In-game menu overlay
            if (showGameMenu) {
                GameMenu(
                    slots = saveSlots,
                    onSave = { slot ->
                        val c = core ?: return@GameMenu
                        c.saveState(slot)
                        val sv = surfaceViewRef
                        val screenshotPath = c.getScreenshotPath(slot)
                        if (sv != null && screenshotPath != null) {
                            captureScreenshot(sv, screenshotPath)
                        }
                        saveSlots = c.getAllSaveSlots()
                    },
                    onLoad = { slot ->
                        val c = core ?: return@GameMenu
                        c.loadState(slot)
                        if (!isPaused) c.resume()
                        showGameMenu = false
                    },
                    onDelete = { slot ->
                        val c = core ?: return@GameMenu
                        c.deleteState(slot)
                        saveSlots = c.getAllSaveSlots()
                    },
                    onResume = {
                        if (!isPaused) core?.resume()
                        showGameMenu = false
                    }
                )
            }
        }
    }
}

@Composable
private fun LaunchMenu(
    gameTitle: String,
    slots: List<SaveSlotInfo>,
    onContinue: (slot: Int) -> Unit,
    onNewGame: () -> Unit,
    onBack: () -> Unit
) {
    val dateFormat = remember { SimpleDateFormat("MMM d, yyyy  h:mm a", Locale.getDefault()) }
    val existingSlots = slots.filter { it.exists }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black)
            .padding(24.dp)
    ) {
        IconButton(
            onClick = onBack,
            modifier = Modifier.align(Alignment.TopStart)
        ) {
            Icon(
                Icons.AutoMirrored.Filled.ArrowBack,
                contentDescription = "Back",
                tint = Color.White.copy(alpha = 0.7f)
            )
        }

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .align(Alignment.Center),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(16.dp)
        ) {
            Text(
                text = gameTitle,
                style = MaterialTheme.typography.headlineMedium,
                color = Color.White,
                textAlign = TextAlign.Center
            )

            Spacer(Modifier.height(8.dp))

            Text(
                text = "Continue",
                style = MaterialTheme.typography.titleMedium,
                color = Color.White.copy(alpha = 0.7f)
            )

            existingSlots.forEach { slot ->
                val thumbnail = remember(slot.screenshotPath, slot.lastModified) {
                    slot.screenshotPath?.let { path ->
                        try { BitmapFactory.decodeFile(path) } catch (_: Exception) { null }
                    }
                }
                Row(
                    modifier = Modifier
                        .fillMaxWidth(0.8f)
                        .clip(RoundedCornerShape(12.dp))
                        .border(1.dp, Color.White.copy(alpha = 0.3f), RoundedCornerShape(12.dp))
                        .clickable { onContinue(slot.slot) }
                        .padding(12.dp),
                    horizontalArrangement = Arrangement.spacedBy(12.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Box(
                        modifier = Modifier
                            .width(96.dp)
                            .aspectRatio(4f / 3f)
                            .clip(RoundedCornerShape(6.dp))
                            .background(Color.DarkGray),
                        contentAlignment = Alignment.Center
                    ) {
                        if (thumbnail != null) {
                            Image(
                                bitmap = thumbnail.asImageBitmap(),
                                contentDescription = null,
                                contentScale = ContentScale.Crop,
                                modifier = Modifier.fillMaxSize()
                            )
                        }
                    }
                    Column {
                        Text(
                            text = "Slot ${slot.slot + 1}",
                            style = MaterialTheme.typography.titleSmall,
                            fontWeight = FontWeight.Medium,
                            color = Color.White
                        )
                        Text(
                            text = dateFormat.format(Date(slot.lastModified)),
                            style = MaterialTheme.typography.bodySmall,
                            color = Color.White.copy(alpha = 0.5f)
                        )
                    }
                }
            }

            Spacer(Modifier.height(8.dp))

            OutlinedButton(
                onClick = onNewGame,
                colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.White),
                modifier = Modifier.fillMaxWidth(0.8f)
            ) {
                Text("New Game")
            }
        }
    }
}

@Composable
private fun GameMenu(
    slots: List<SaveSlotInfo>,
    onSave: (slot: Int) -> Unit,
    onLoad: (slot: Int) -> Unit,
    onDelete: (slot: Int) -> Unit,
    onResume: () -> Unit
) {
    val dateFormat = remember { SimpleDateFormat("MMM d, yyyy  h:mm a", Locale.getDefault()) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black.copy(alpha = 0.85f))
            .clickable(enabled = false) {},
        contentAlignment = Alignment.Center
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth(0.9f)
                .padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Text(
                text = "Save / Load",
                style = MaterialTheme.typography.titleLarge,
                color = Color.White
            )

            Spacer(Modifier.height(8.dp))

            slots.forEach { slot ->
                val thumbnail = remember(slot.screenshotPath, slot.lastModified) {
                    slot.screenshotPath?.let { path ->
                        try { BitmapFactory.decodeFile(path) } catch (_: Exception) { null }
                    }
                }
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clip(RoundedCornerShape(8.dp))
                        .border(1.dp, Color.White.copy(alpha = 0.2f), RoundedCornerShape(8.dp))
                        .padding(8.dp),
                    horizontalArrangement = Arrangement.spacedBy(10.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    // Thumbnail
                    Box(
                        modifier = Modifier
                            .width(72.dp)
                            .aspectRatio(4f / 3f)
                            .clip(RoundedCornerShape(4.dp))
                            .background(Color.DarkGray),
                        contentAlignment = Alignment.Center
                    ) {
                        if (thumbnail != null) {
                            Image(
                                bitmap = thumbnail.asImageBitmap(),
                                contentDescription = null,
                                contentScale = ContentScale.Crop,
                                modifier = Modifier.fillMaxSize()
                            )
                        } else {
                            Text(
                                text = "Empty",
                                style = MaterialTheme.typography.labelSmall,
                                color = Color.White.copy(alpha = 0.3f)
                            )
                        }
                    }

                    // Slot info
                    Column(modifier = Modifier.weight(1f)) {
                        Text(
                            text = "Slot ${slot.slot + 1}",
                            style = MaterialTheme.typography.bodyMedium,
                            fontWeight = FontWeight.Medium,
                            color = Color.White
                        )
                        Text(
                            text = if (slot.exists) dateFormat.format(Date(slot.lastModified))
                            else "No save data",
                            style = MaterialTheme.typography.labelSmall,
                            color = Color.White.copy(alpha = 0.5f)
                        )
                    }

                    // Save button
                    TextButton(
                        onClick = { onSave(slot.slot) },
                        modifier = Modifier.size(width = 56.dp, height = 36.dp)
                    ) {
                        Text("Save", style = MaterialTheme.typography.labelMedium)
                    }

                    // Load button
                    TextButton(
                        onClick = { onLoad(slot.slot) },
                        enabled = slot.exists,
                        modifier = Modifier.size(width = 56.dp, height = 36.dp)
                    ) {
                        Text("Load", style = MaterialTheme.typography.labelMedium)
                    }

                    // Delete button
                    IconButton(
                        onClick = { onDelete(slot.slot) },
                        enabled = slot.exists,
                        modifier = Modifier.size(36.dp)
                    ) {
                        Icon(
                            Icons.Default.Delete,
                            contentDescription = "Delete save",
                            tint = if (slot.exists) Color.White.copy(alpha = 0.7f) else Color.White.copy(alpha = 0.2f)
                        )
                    }
                }
            }

            Spacer(Modifier.height(8.dp))

            Button(onClick = onResume) {
                Text("Resume")
            }
        }
    }
}

private fun captureScreenshot(surfaceView: SurfaceView, outputPath: String) {
    try {
        val bitmap = Bitmap.createBitmap(
            surfaceView.width, surfaceView.height, Bitmap.Config.ARGB_8888
        )
        PixelCopy.request(
            surfaceView, bitmap,
            { result ->
                if (result == PixelCopy.SUCCESS) {
                    val thumb = Bitmap.createScaledBitmap(bitmap, 320, 240, true)
                    FileOutputStream(File(outputPath)).use { out ->
                        thumb.compress(Bitmap.CompressFormat.JPEG, 85, out)
                    }
                    thumb.recycle()
                }
                bitmap.recycle()
            },
            Handler(Looper.getMainLooper())
        )
    } catch (_: Exception) {
        // Screenshot is best-effort
    }
}
