package solutions.tretter.mindmachine

import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.util.Log
import android.view.View
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.background
import solutions.tretter.mindmachine.session.DurationSliderCard
import solutions.tretter.mindmachine.session.FlashSequenceEditor
import solutions.tretter.mindmachine.session.SetupTimelineEditor
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.Image
import androidx.compose.foundation.Image
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Settings
import androidx.compose.ui.res.painterResource
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.SegmentedButton
import androidx.compose.material3.SingleChoiceSegmentedButtonRow
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.layout.ContentScale
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.google.android.gms.ads.MobileAds
import solutions.tretter.mindmachine.audio.BinauralAudioEngine
import solutions.tretter.mindmachine.audio.HeadsetMonitor
import solutions.tretter.mindmachine.ads.AdBanner
import solutions.tretter.mindmachine.ads.rememberInterstitialController
import solutions.tretter.mindmachine.data.SettingsRepository
import solutions.tretter.mindmachine.data.UserProgramRepository
import solutions.tretter.mindmachine.domain.RuntimeState
import solutions.tretter.mindmachine.session.FlashColor
import solutions.tretter.mindmachine.session.MainViewModel
import solutions.tretter.mindmachine.session.SplitFlashFrame
import kotlinx.coroutines.launch
import solutions.tretter.mindmachine.session.flashIntervalMsToSeconds
import solutions.tretter.mindmachine.session.flashIntervalSecondsToMs
import solutions.tretter.mindmachine.session.formatDuration
import solutions.tretter.mindmachine.session.sessionProgressFraction
import solutions.tretter.mindmachine.session.shouldShowActiveControlsByDefault
import solutions.tretter.mindmachine.session.shouldUseImmersiveFullscreen
import kotlinx.coroutines.delay
import kotlin.math.roundToInt
import kotlin.math.roundToLong
import java.util.Locale


private const val SESSION_ENTRY_HOME = "home"
private const val SESSION_ENTRY_SETUP = "setup"

private val MindMachineColors = darkColorScheme(
    primary = Color(0xFF8AB4FF),
    onPrimary = Color(0xFF001B3D),
    primaryContainer = Color(0xFF004689),
    onPrimaryContainer = Color(0xFFD7E3FF),
    secondary = Color(0xFFFFD166),
    onSecondary = Color(0xFF2E2300),
    background = Color(0xFF05070D),
    onBackground = Color(0xFFF3F6FF),
    surface = Color(0xFF121621),
    onSurface = Color(0xFFF3F6FF),
    error = Color(0xFFFF6B6B),
    onError = Color(0xFF3A0002)
)

class MainActivity : ComponentActivity() {
    private val settingsRepo by lazy { SettingsRepository(applicationContext) }
    private val billingManager by lazy {
        solutions.tretter.mindmachine.billing.BillingManager(
            applicationContext,
            onNoAdsEntitlementChanged = { hasNoAds ->
                lifecycleScope.launch { settingsRepo.updateNoAds(hasNoAds) }
            },
        ).also { it.start() }
    }
    private val vm: MainViewModel by viewModels {
        MainViewModel.Factory(
            settingsRepo,
            UserProgramRepository(applicationContext),
            HeadsetMonitor(applicationContext),
            BinauralAudioEngine(),
            billingManager,
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MobileAds.initialize(this) {}
        setContent {
            MaterialTheme(colorScheme = MindMachineColors) {
                App(vm, billingManager)
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun App(vm: MainViewModel = viewModel(), billingManager: solutions.tretter.mindmachine.billing.BillingManager) {
    val nav = rememberNavController()
    val ui by vm.ui.collectAsStateWithLifecycle()
    val lifecycle = LocalLifecycleOwner.current.lifecycle
    val activity = LocalContext.current as? Activity

    DisposableEffect(lifecycle, activity, ui.runtimeState) {
        val observer = LifecycleEventObserver { _, event ->
            val appActuallyBackgrounded = activity?.isChangingConfigurations != true
            if (
                event == Lifecycle.Event.ON_STOP &&
                ui.runtimeState == RuntimeState.RUNNING &&
                appActuallyBackgrounded
            ) {
                vm.pause("Session paused because app moved to background.")
            }
        }
        lifecycle.addObserver(observer)
        onDispose { lifecycle.removeObserver(observer) }
    }

    if (!ui.settingsInitialized) {
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(MaterialTheme.colorScheme.background)
        )
        return
    }

    val startRoute = if (ui.settings.safetyAcknowledged) "home" else "safety"
    NavHost(navController = nav, startDestination = startRoute, modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
        composable("safety") {
            SafetyScreen(
                onAck = {
                    vm.acknowledgeSafety()
                    nav.navigate("home") { popUpTo(0) }
                },
                onHolder = { nav.navigate("holder") }
            )
        }
        composable("home") {
            var confirmDeleteProgramId by remember { mutableStateOf<String?>(null) }
            var confirmDeleteProgramName by remember { mutableStateOf("") }
            val interstitial = rememberInterstitialController(enabled = !ui.settings.noAds)

            Column(
                Modifier
                    .fillMaxSize()
                    .safeDrawingPadding()
            ) {
                TopAppBar(
                    title = {
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Image(
                                painter = painterResource(R.drawable.ic_app_logo),
                                contentDescription = "MindMachine",
                                modifier = Modifier.size(60.dp)
                            )
                            Spacer(Modifier.width(8.dp))
                            Text("MindMachine")
                        }
                    },
                    actions = {
                    IconButton(
                        onClick = {
                            vm.createNewProgramDraft()
                            nav.navigate("setup")
                        }
                    ) {
                        Icon(Icons.Filled.Add, contentDescription = "Add")
                    }
                    IconButton(onClick = { nav.navigate("settings") }) {
                        Icon(Icons.Filled.Settings, contentDescription = "Settings")
                    }
                }
                )
                LazyColumn(
                    Modifier
                        .weight(1f)
                        .padding(12.dp),
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    item {
                        TextButton(onClick = { nav.navigate("holder") }) { Text("User Guidance/Disclaimer") }
                    }
                    items(ui.presets) { p ->
                        Card(
                            colors = CardDefaults.cardColors(
                                containerColor = MaterialTheme.colorScheme.surface,
                                contentColor = MaterialTheme.colorScheme.onSurface
                            ),
                            modifier = Modifier.fillMaxWidth().clickable {
                                vm.choosePreset(p.id)
                                nav.navigate("setup")
                            }.padding(4.dp)
                        ) {
                            Row(
                                modifier = Modifier.fillMaxWidth().padding(12.dp),
                                horizontalArrangement = Arrangement.SpaceBetween,
                                verticalAlignment = Alignment.CenterVertically,
                            ) {
                                Column(Modifier.weight(1f)) {
                                    Text(p.name, style = MaterialTheme.typography.titleMedium)
                                    Text(p.description)
                                    Text("${formatDuration(p.defaultDurationSec)} • ${p.visualPatternType} • binaural ${formatMaxTwoDecimals(p.binauralDifferenceHz)}")
                                }
                                Row(
                                    verticalAlignment = Alignment.CenterVertically,
                                    horizontalArrangement = Arrangement.spacedBy(8.dp)
                                ) {
                                    IconButton(
                                        onClick = {
                                            val go = {
                                                val started = vm.startSessionFromProgramSelection(p.id)
                                                if (started) {
                                                    nav.navigate("active/$SESSION_ENTRY_HOME")
                                                }
                                            }

                                            if (ui.settings.noAds) {
                                                go()
                                            } else {
                                                interstitial?.show(onDone = go) ?: go()
                                            }
                                        },
                                        modifier = Modifier.size(48.dp)
                                    ) {
                                        Icon(
                                            imageVector = Icons.Filled.PlayArrow,
                                            contentDescription = "Play ${p.name}",
                                            tint = Color(0xFF4CAF50),
                                            modifier = Modifier.size(38.dp)
                                        )
                                    }
                                    if (p.id in ui.deletableProgramIds) {
                                        Box(
                                            modifier = Modifier
                                                .size(24.dp)
                                                .clickable {
                                                    confirmDeleteProgramId = p.id
                                                    confirmDeleteProgramName = p.name
                                                },
                                            contentAlignment = Alignment.Center
                                        ) {
                                            Icon(
                                                imageVector = Icons.Filled.Delete,
                                                contentDescription = "Delete ${p.name}",
                                                tint = Color(0xFFFF5252),
                                                modifier = Modifier.fillMaxSize()
                                            )
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                AdBanner(
                    enabled = !ui.settings.noAds,
                    modifier = Modifier.fillMaxWidth()
                )
            }

            if (confirmDeleteProgramId != null) {
                AlertDialog(
                    onDismissRequest = {
                        confirmDeleteProgramId = null
                        confirmDeleteProgramName = ""
                    },
                    title = { Text("Delete program?") },
                    text = { Text("Delete \"$confirmDeleteProgramName\"?") },
                    confirmButton = {
                        TextButton(onClick = {
                            confirmDeleteProgramId?.let(vm::deleteProgram)
                            confirmDeleteProgramId = null
                            confirmDeleteProgramName = ""
                        }) {
                            Text("Delete", color = Color(0xFFFF5252))
                        }
                    },
                    dismissButton = {
                        TextButton(onClick = {
                            confirmDeleteProgramId = null
                            confirmDeleteProgramName = ""
                        }) { Text("Cancel") }
                    }
                )
            }
        }
        composable("setup") {
            val interstitial = rememberInterstitialController(enabled = !ui.settings.noAds)
            SetupScreen(
                vm = vm,
                onStart = {
                    val go = {
                        val started = vm.startSession()
                        if (started) {
                            nav.navigate("active/$SESSION_ENTRY_SETUP")
                        }
                    }

                    if (ui.settings.noAds) {
                        go()
                    } else {
                        interstitial?.show(onDone = go) ?: go()
                    }
                },
            )
        }
        composable(
            route = "active/{entryPoint}",
            arguments = listOf(navArgument("entryPoint") { type = NavType.StringType })
        ) { backStackEntry ->
            val entryPoint = backStackEntry.arguments?.getString("entryPoint") ?: SESSION_ENTRY_SETUP
            ActiveSessionScreen(
                vm = vm,
                onFinish = {
                    nav.navigate(entryPoint) {
                        popUpTo("active/$entryPoint") { inclusive = true }
                        launchSingleTop = true
                    }
                },
                onBackToEntry = {
                    vm.stop()
                    nav.navigate(entryPoint) {
                        popUpTo("active/$entryPoint") { inclusive = true }
                        launchSingleTop = true
                    }
                }
            )
        }
        composable("settings") {
            SettingsScreen(vm, onRemoveAds = { nav.navigate("remove_ads") })
        }
        composable("remove_ads") {
            RemoveAdsScreen(billingManager = billingManager, vm = vm)
        }
        composable("holder") {
            PositioningScreen()
        }
    }
}

@Composable
fun SimpleScreen(title: String, subtitle: String, actions: @Composable ColumnScope.() -> Unit) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .safeDrawingPadding()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Text(title, style = MaterialTheme.typography.headlineMedium, color = MaterialTheme.colorScheme.onBackground)
        Text(subtitle, color = MaterialTheme.colorScheme.onBackground)
        actions()
    }
}

@Composable
fun SafetyScreen(onAck: () -> Unit, onHolder: () -> Unit) {
    var checked by remember { mutableStateOf(false) }
    Column(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .safeDrawingPadding()
            .padding(16.dp)
    ) {
        Text("Read before using MindMachine", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
        Spacer(Modifier.height(12.dp))
        Text(
            "Flashing lights may be unsafe for people with epilepsy, seizure sensitivity, or migraine triggers.\n\nDo not use while driving, walking, cycling, or operating machinery.\n\nFor immersive visual sessions, keep your eyes closed. Do not stare at the screen.\n\nDo not place the phone directly on your eyes. Avoid pressure on face/eyes and ensure comfortable breathing/airflow.\n\nUse at your own risk. This app is a prototype and not a medical device.\n\nStop immediately for discomfort, dizziness, headache, nausea, anxiety, or eye strain.\n\nBinaural mode requires stereo headphones.",
            color = MaterialTheme.colorScheme.onBackground
        )
        Row(verticalAlignment = Alignment.CenterVertically) {
            Checkbox(checked = checked, onCheckedChange = { checked = it })
            Text("I understand the risks and will stop immediately if I feel discomfort.", color = MaterialTheme.colorScheme.onBackground)
        }
        Button(onClick = onAck, enabled = checked, modifier = Modifier.semantics { contentDescription = "I Understand" }) { Text("I Understand") }
        TextButton(onClick = onHolder) { Text("Positioning Guidance") }
    }
}

@Composable
fun SetupScreen(
    vm: MainViewModel,
    onStart: () -> Unit,
) {
    val ui by vm.ui.collectAsStateWithLifecycle()
    val scrollState = rememberScrollState()
    val containerModifier = Modifier
        .fillMaxSize()
        .background(MaterialTheme.colorScheme.background)
        .windowInsetsPadding(WindowInsets.statusBars)
        .windowInsetsPadding(WindowInsets.navigationBars)
        .then(if (setupScreenUsesScrollableContainer()) Modifier.verticalScroll(scrollState) else Modifier)
        .padding(horizontal = 16.dp, vertical = 12.dp)

    var programName by remember(ui.selectedPreset.id) { mutableStateOf(ui.selectedPreset.name) }

    val hasUnsavedChanges = setupScreenHasUnsavedChanges(
        hasUnsavedTimelineChanges = ui.hasUnsavedChanges,
        editedProgramName = programName,
        savedProgramName = ui.savedProgramName,
    )

    Column(
        modifier = containerModifier,
        verticalArrangement = Arrangement.spacedBy(14.dp),
    ) {
        Text(
            ui.selectedPreset.name,
            style = MaterialTheme.typography.headlineSmall,
            color = MaterialTheme.colorScheme.onBackground,
        )

        TextField(
            value = programName,
            onValueChange = { programName = it },
            label = { Text("Program name") },
            modifier = Modifier.fillMaxWidth(),
        )

        DurationSliderCard(
            durationSec = ui.timeline.durationSec,
            onDurationSecChanged = { vm.setDurationSec(it) },
        )

        // Integrated timeline editor (no separate screen).
        SetupTimelineEditor(
            state = ui.timeline,
            onStateChanged = vm::updateTimeline,
            onCurveGranularityChanged = vm::setCurveGranularitySec,
        )

        FlashSequenceEditor(
            sequence = ui.timeline.flashSequence,
            onSequenceChanged = { sequence -> vm.updateTimeline(ui.timeline.withFlashSequence(sequence)) },
        )

        Row(horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth()) {
            if (hasUnsavedChanges) {
                OutlinedButton(
                    onClick = { vm.saveCurrentProgram(programName) },
                    modifier = Modifier.weight(1f).height(52.dp)
                ) {
                    Text("Save")
                }
            } else {
                Button(onClick = onStart, modifier = Modifier.weight(1f).height(52.dp)) { Text("Start") }
            }
        }
        if (ui.error != null) Text(ui.error!!, color = if (ui.error!!.startsWith("Saved")) Color(0xFF72E39A) else MaterialTheme.colorScheme.error)
        Spacer(Modifier.height(8.dp))
    }
}

internal fun setupScreenFlashIntervalLabel(flashIntervalMs: Int): String =
    "Flash interval: ${"%.2f".format(flashIntervalMsToSeconds(flashIntervalMs))} s"

internal fun formatMaxTwoDecimals(value: Float): String =
    String.format(Locale.US, "%.2f", value).trimEnd('0').trimEnd('.')

internal fun setupScreenHasUnsavedChanges(
    hasUnsavedTimelineChanges: Boolean,
    editedProgramName: String,
    savedProgramName: String,
): Boolean {
    val nameChanged = editedProgramName.trim() != savedProgramName.trim()
    return hasUnsavedTimelineChanges || nameChanged
}

internal fun setupScreenUsesScrollableContainer(): Boolean = true

@Composable
fun ActiveSessionScreen(vm: MainViewModel, onFinish: () -> Unit, onBackToEntry: () -> Unit) {
    val ui by vm.ui.collectAsStateWithLifecycle()
    if (ui.runtimeState == RuntimeState.COMPLETED) onFinish()

    BackHandler {
        onBackToEntry()
    }

    val isVisualMode = true
    val context = LocalContext.current
    DisposableEffect(isVisualMode) {
        val activity = context as? Activity
        val previous = activity?.requestedOrientation
        if (isVisualMode) {
            activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
        }
        onDispose {
            if (isVisualMode) {
                activity?.requestedOrientation = previous ?: ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            }
        }
    }

    val immersiveFullscreen = shouldUseImmersiveFullscreen(isVisualMode, ui.runtimeState)
    var revealSystemBarsSignal by remember { mutableIntStateOf(0) }
    ApplyImmersiveMode(
        enabled = immersiveFullscreen,
        revealSignal = revealSystemBarsSignal,
    )

    var showOverlay by remember(ui.runtimeState) { mutableStateOf(shouldShowActiveControlsByDefault(ui.runtimeState)) }
    LaunchedEffect(ui.runtimeState) {
        showOverlay = shouldShowActiveControlsByDefault(ui.runtimeState)
    }
    var brightnessOverlayVisible by remember { mutableStateOf(false) }
    var brightnessOverlayToken by remember { mutableIntStateOf(0) }
    val timingLogTag = "MindMachineTiming"

    LaunchedEffect(brightnessOverlayToken) {
        if (!brightnessOverlayVisible) return@LaunchedEffect
        delay(2500)
        brightnessOverlayVisible = false
    }

    LaunchedEffect(ui.runtimeState) {
        when (ui.runtimeState) {
            RuntimeState.COUNTDOWN -> Log.d(timingLogTag, "COUNTDOWN_START")
            RuntimeState.RUNNING -> Log.d(timingLogTag, "IMMERSIVE_START")
            RuntimeState.STOPPED, RuntimeState.COMPLETED, RuntimeState.PAUSED, RuntimeState.INTERRUPTED, RuntimeState.ERROR -> {
                Log.d(timingLogTag, "IMMERSIVE_STOP state=${ui.runtimeState}")
            }
            else -> Unit
        }
    }

    ApplyKeepScreenOn(enabled = true)

    ApplyScreenBrightnessOverride(
        enabled = true,
        brightnessPercent = ui.settings.immersiveBrightnessPercent,
    )

    ApplyPreferredRefreshRate(
        enabled = true,
        preferLowest = ui.settings.preferLowestRefreshRate,
    )

    val progress = sessionProgressFraction(
        durationSec = ui.timeline.durationSec,
        remainingSec = ui.remainingSec,
    )

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black)
            .then(if (immersiveFullscreen) Modifier else Modifier.safeDrawingPadding())
            .pointerInput(immersiveFullscreen) {
                detectTapGestures {
                    brightnessOverlayVisible = true
                    brightnessOverlayToken++
                    if (!immersiveFullscreen) {
                        showOverlay = !showOverlay
                    }
                }
            }
    ) {
        if (isVisualMode) {
            AndroidView(
                modifier = Modifier.fillMaxSize(),
                factory = { ctx ->
                    SplitFlashRenderView(ctx).apply {
                        setRunning(ui.runtimeState == RuntimeState.RUNNING)
                        updateIntervals(ui.runtimeParams.flashOnMs, ui.runtimeParams.flashOffMs)
                        setFlashSequence(ui.config.flashSequence)
                        setMonochrome(ui.config.monochromeFlashMode)
                    }
                },
                update = { view ->
                    view.updateIntervals(ui.runtimeParams.flashOnMs, ui.runtimeParams.flashOffMs)
                    view.setFlashSequence(ui.config.flashSequence)
                    view.setMonochrome(ui.config.monochromeFlashMode)
                    view.setRunning(ui.runtimeState == RuntimeState.RUNNING)
                }
            )
        }

        if (ui.runtimeState == RuntimeState.COUNTDOWN) {
            Text(
                "${ui.countdownSec}",
                modifier = Modifier.align(Alignment.Center),
                style = MaterialTheme.typography.displayLarge,
                color = Color.White
            )
        }

        if (immersiveFullscreen && ui.settings.showImmersiveProgressBar) {
            LinearProgressIndicator(
                progress = { progress },
                modifier = Modifier
                    .align(Alignment.BottomCenter)
                    .fillMaxWidth()
                    .height(5.dp),
                trackColor = Color.White.copy(alpha = 0.2f),
                color = Color.White,
            )
        }

        if (brightnessOverlayVisible) {
            Column(
                Modifier
                    .align(Alignment.TopCenter)
                    .padding(top = 24.dp)
                    .fillMaxWidth(0.45f)
                    .background(Color.Black.copy(alpha = 0.72f))
                    .padding(horizontal = 12.dp, vertical = 10.dp)
            ) {
                Text(
                    text = "Brightness ${ui.settings.immersiveBrightnessPercent}%",
                    color = Color.White,
                    style = MaterialTheme.typography.bodyMedium,
                )
                Slider(
                    value = ui.settings.immersiveBrightnessPercent.toFloat(),
                    onValueChange = {
                        vm.updateImmersiveBrightnessPercent(it.roundToInt())
                        brightnessOverlayVisible = true
                        brightnessOverlayToken++
                    },
                    valueRange = 5f..100f,
                )
            }
        }

        if (showOverlay) {
            Column(
                Modifier
                    .align(Alignment.BottomCenter)
                    .fillMaxWidth()
                    .background(Color.Black.copy(alpha = 0.72f))
                    .padding(16.dp)
            ) {
                Text("${ui.selectedPreset.name} • ${ui.remainingSec}s", color = Color.White)
                if (ui.runtimeState == RuntimeState.RUNNING) {
                    Button(onClick = { vm.pause() }, modifier = Modifier.fillMaxWidth()) { Text("Pause") }
                } else {
                    Button(onClick = { vm.resume() }, modifier = Modifier.fillMaxWidth()) { Text("Resume") }
                }
                OutlinedButton(
                    onClick = {
                        vm.stop()
                        onFinish()
                    },
                    modifier = Modifier.fillMaxWidth()
                ) { Text("Stop") }
                if (ui.interruptionReason != null) {
                    Text(ui.interruptionReason!!, color = Color.White)
                    if (ui.runtimeState == RuntimeState.INTERRUPTED) {
                        OutlinedButton(onClick = { vm.switchToVisualOnlyAndResume() }, modifier = Modifier.fillMaxWidth()) {
                            Text("Resume Visual-only")
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun ApplyKeepScreenOn(enabled: Boolean) {
    val activity = LocalContext.current as? Activity ?: return
    val window = activity.window

    DisposableEffect(window, enabled) {
        if (enabled) {
            window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        } else {
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
        onDispose {
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        }
    }
}

@Composable
private fun ApplyScreenBrightnessOverride(enabled: Boolean, brightnessPercent: Int) {
    val activity = LocalContext.current as? Activity ?: return
    val window = activity.window

    DisposableEffect(window) {
        onDispose {
            val reset = window.attributes
            reset.screenBrightness = -1f
            window.attributes = reset
        }
    }

    LaunchedEffect(enabled, brightnessPercent) {
        val params = window.attributes
        params.screenBrightness = if (enabled) {
            (brightnessPercent.coerceIn(5, 100) / 100f)
        } else {
            -1f
        }
        window.attributes = params
    }
}

@Composable
private fun ApplyPreferredRefreshRate(enabled: Boolean, preferLowest: Boolean) {
    val activity = LocalContext.current as? Activity ?: return
    val window = activity.window
    val timingLogTag = "MindMachineTiming"

    DisposableEffect(window) {
        onDispose {
            val params = window.attributes
            params.preferredRefreshRate = 0f
            params.preferredDisplayModeId = 0
            window.attributes = params
        }
    }

    LaunchedEffect(enabled, preferLowest) {
        val params = window.attributes
        if (enabled && preferLowest) {
            val display = activity.display
            val chosenMode = display?.supportedModes?.minByOrNull { it.refreshRate }
            params.preferredDisplayModeId = chosenMode?.modeId ?: 0
            params.preferredRefreshRate = chosenMode?.refreshRate ?: 0f
            Log.d(
                timingLogTag,
                "DISPLAY_MODE_REQUEST modeId=${chosenMode?.modeId ?: 0} refreshHz=${chosenMode?.refreshRate ?: 0f} supported=${display?.supportedModes?.joinToString { "${it.modeId}:${it.refreshRate}" }}"
            )
        } else {
            params.preferredDisplayModeId = 0
            params.preferredRefreshRate = 0f
        }
        window.attributes = params
    }
}

@Composable
private fun ApplyImmersiveMode(enabled: Boolean, revealSignal: Int) {
    val context = LocalContext.current
    val activity = context as? Activity ?: return
    val window = activity.window
    val controller = remember(window) { WindowInsetsControllerCompat(window, window.decorView) }

    DisposableEffect(window) {
        onDispose {
            controller.show(WindowInsetsCompat.Type.systemBars())
            WindowCompat.setDecorFitsSystemWindows(window, true)
        }
    }

    LaunchedEffect(enabled) {
        if (enabled) {
            WindowCompat.setDecorFitsSystemWindows(window, false)
            controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            controller.hide(WindowInsetsCompat.Type.systemBars())
        } else {
            controller.show(WindowInsetsCompat.Type.systemBars())
            WindowCompat.setDecorFitsSystemWindows(window, true)
        }
    }

    LaunchedEffect(revealSignal, enabled) {
        if (!enabled || revealSignal == 0) return@LaunchedEffect
        controller.show(WindowInsetsCompat.Type.systemBars())
        delay(2500)
        if (enabled) {
            controller.hide(WindowInsetsCompat.Type.systemBars())
        }
    }
}

private class SplitFlashRenderView(context: Context) : View(context) {
    private val timingLogTag = "MindMachineTiming"
    private val handler = Handler(Looper.getMainLooper())
    private val leftPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val rightPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    private var isRunning = false
    private var phase = 1 // start black
    private var rawOnMs = 167L
    private var rawOffMs = 167L
    private var onMs = 167L
    private var offMs = 167L
    private var monochrome = false
    private var flashSequence = solutions.tretter.mindmachine.session.defaultFlashSequence()
    private var started = false
    private var startUptimeMs = 0L
    private var nextToggleUptimeMs = 0L
    private var toggleCount = 0L
    private var lateToggleCount = 0L
    private var maxLatenessMs = 0L

    private val toggleRunnable = object : Runnable {
        override fun run() {
            if (!isRunning) return

            val now = SystemClock.uptimeMillis()
            val latenessMs = (now - nextToggleUptimeMs).coerceAtLeast(0L)
            val previousPhase = phase

            if (latenessMs > 0L) {
                lateToggleCount += 1
                maxLatenessMs = maxOf(maxLatenessMs, latenessMs)
            }

            phase = (phase + 1) % phaseCount()
            toggleCount += 1
            invalidate()

            val nextDuration = if (isVisiblePhase(phase)) onMs else offMs
            nextToggleUptimeMs += nextDuration

            val shouldLogToggle = toggleCount <= 20 || latenessMs > framePeriodMs() || toggleCount % 60L == 0L
            if (shouldLogToggle) {
                Log.d(
                    timingLogTag,
                    "toggle#$toggleCount prev=${phaseName(previousPhase)} next=${phaseName(phase)} " +
                        "scheduledMs=${nextToggleUptimeMs - startUptimeMs - nextDuration} " +
                        "actualMs=${now - startUptimeMs} latenessMs=$latenessMs " +
                        "lateCount=$lateToggleCount maxLateMs=$maxLatenessMs"
                )
            }

            scheduleNext()
        }
    }

    fun updateIntervals(flashOnMs: Int, flashOffMs: Int) {
        val newRawOnMs = flashOnMs.coerceIn(50, 2000).toLong()
        val newRawOffMs = flashOffMs.coerceIn(50, 2000).toLong()
        val frameMs = framePeriodMs().coerceAtLeast(1L)
        val newOnMs = snapToFrameMs(newRawOnMs, frameMs)
        val newOffMs = snapToFrameMs(newRawOffMs, frameMs)

        val changed = newRawOnMs != rawOnMs || newRawOffMs != rawOffMs || newOnMs != onMs || newOffMs != offMs
        if (!changed) return

        rawOnMs = newRawOnMs
        rawOffMs = newRawOffMs
        onMs = newOnMs
        offMs = newOffMs

        if (isRunning) {
            Log.d(
                timingLogTag,
                "config onMs=$rawOnMs offMs=$rawOffMs refreshHz=${"%.2f".format(refreshRate())} frameMs=$frameMs snappedOnMs=$onMs snappedOffMs=$offMs"
            )
        }

        if (isRunning && started) {
            val now = SystemClock.uptimeMillis()
            val nextDuration = if (isVisiblePhase(phase)) onMs else offMs
            nextToggleUptimeMs = maxOf(nextToggleUptimeMs, now + 1L)
            val remaining = (nextToggleUptimeMs - now).coerceAtLeast(1L)
            if (remaining > nextDuration) {
                nextToggleUptimeMs = now + nextDuration
            }
            scheduleNext()
        }
    }

    fun setRunning(running: Boolean) {
        if (isRunning == running) return
        isRunning = running
        handler.removeCallbacks(toggleRunnable)

        if (!running) {
            started = false
            phase = 1
            invalidate()
            return
        }

        started = true
        phase = 0
        startUptimeMs = SystemClock.uptimeMillis()
        nextToggleUptimeMs = startUptimeMs + onMs
        toggleCount = 0L
        lateToggleCount = 0L
        maxLatenessMs = 0L
        Log.d(
            timingLogTag,
            "session-start phase=${phaseName(phase)} modeId=${display?.mode?.modeId ?: 0} refreshHz=${"%.2f".format(refreshRate())} frameMs=${framePeriodMs()} nowMs=$startUptimeMs"
        )
        invalidate()
        scheduleNext()
    }

    fun setMonochrome(enabled: Boolean) {
        if (monochrome == enabled) return
        monochrome = enabled
        invalidate()
    }

    fun setFlashSequence(sequence: List<solutions.tretter.mindmachine.session.FlashSequenceRow>) {
        val normalized = sequence.ifEmpty { solutions.tretter.mindmachine.session.defaultFlashSequence() }
        if (flashSequence == normalized) return
        flashSequence = normalized
        if (started) {
            phase %= phaseCount()
        }
        invalidate()
    }

    override fun onDetachedFromWindow() {
        handler.removeCallbacks(toggleRunnable)
        super.onDetachedFromWindow()
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val mid = width / 2f
        val (leftColor, rightColor) = colorsForPhase(phase)
        leftPaint.color = leftColor
        rightPaint.color = rightColor
        canvas.drawRect(0f, 0f, mid, height.toFloat(), leftPaint)
        canvas.drawRect(mid, 0f, width.toFloat(), height.toFloat(), rightPaint)
    }

    private fun scheduleNext() {
        handler.removeCallbacks(toggleRunnable)
        handler.postAtTime(toggleRunnable, nextToggleUptimeMs)
    }
    private fun colorsForPhase(phase: Int): Pair<Int, Int> {
        if (!isVisiblePhase(phase)) return Pair(android.graphics.Color.BLACK, android.graphics.Color.BLACK)
        if (monochrome) return Pair(android.graphics.Color.WHITE, android.graphics.Color.WHITE)
        val row = flashSequence[(phase / 2).mod(flashSequence.size)]
        val left = paletteColor(row.leftColor)
        val right = if (row.splitScreen) paletteColor(row.rightColor) else left
        return Pair(left, right)
    }

    private fun phaseName(phase: Int): String {
        if (!isVisiblePhase(phase)) return "BLACK"
        val row = flashSequence[(phase / 2).mod(flashSequence.size)]
        return if (row.splitScreen) {
            "${row.leftColor.name}_${row.rightColor.name}"
        } else {
            row.leftColor.name
        }
    }

    private fun isVisiblePhase(phase: Int): Boolean = phase % 2 == 0

    private fun phaseCount(): Int = (flashSequence.size.coerceAtLeast(1)) * 2

    private fun paletteColor(color: solutions.tretter.mindmachine.session.FlashPaletteColor): Int = when (color) {
        solutions.tretter.mindmachine.session.FlashPaletteColor.BLACK -> android.graphics.Color.BLACK
        solutions.tretter.mindmachine.session.FlashPaletteColor.WHITE -> android.graphics.Color.WHITE
        solutions.tretter.mindmachine.session.FlashPaletteColor.RED -> android.graphics.Color.RED
        solutions.tretter.mindmachine.session.FlashPaletteColor.GREEN -> android.graphics.Color.GREEN
        solutions.tretter.mindmachine.session.FlashPaletteColor.YELLOW -> android.graphics.Color.YELLOW
        solutions.tretter.mindmachine.session.FlashPaletteColor.BLUE -> android.graphics.Color.BLUE
    }

    private fun refreshRate(): Float = display?.refreshRate?.takeIf { it > 0f } ?: 60f

    private fun framePeriodMs(): Long = (1000f / refreshRate()).roundToLong().coerceAtLeast(1L)

    private fun snapToFrameMs(valueMs: Long, frameMs: Long): Long = ((valueMs + frameMs / 2) / frameMs).coerceAtLeast(1L) * frameMs
}

private fun FlashColor.toComposeColor(): Color = when (this) {
    FlashColor.RED -> Color.Red
    FlashColor.GREEN -> Color.Green
    FlashColor.BLACK -> Color.Black
}

@Composable
private fun rememberSplitFlashFrame(
    isRunning: Boolean,
    flashOnMs: Int,
    flashOffMs: Int,
): androidx.compose.runtime.State<SplitFlashFrame> {
    val latestFlashOnMs = rememberUpdatedState(flashOnMs)
    val latestFlashOffMs = rememberUpdatedState(flashOffMs)

    // The screen can only change on vsync boundaries. If the configured interval is not a
    // multiple of the refresh period, the *visual* interval will wobble by ~1 frame.
    // Snapping intervals to whole frames makes the blink look uniform.
    val refreshRateHz = LocalView.current.display?.refreshRate ?: 60f
    val framePeriodNanos = remember(refreshRateHz) {
        (1_000_000_000.0 / refreshRateHz.coerceAtLeast(1f)).roundToLong().coerceAtLeast(1L)
    }

    val timingLogTag = "MindMachineTiming"

    return produceState(initialValue = SplitFlashFrame(FlashColor.BLACK, FlashColor.BLACK), isRunning, framePeriodNanos) {
        if (!isRunning) {
            value = SplitFlashFrame(FlashColor.BLACK, FlashColor.BLACK)
            return@produceState
        }

        // Drive the blink schedule from the frame clock, but keep phase boundaries aligned
        // to a monotonic time base (frameTimeNanos) so the *configured timing* stays steady
        // even if some frames are late.
        //
        // Key idea: instead of "advance by whatever elapsed since last frame", we keep an
        // explicit nextToggleTime and only advance the phase when now >= nextToggleTime.
        var started = false
        var phase = 0 // 0=RG, 1=BK, 2=GR, 3=BK
        var nextToggleNanos = 0L
        var onNanos = 0L
        var offNanos = 0L
        var lastLoggedFlashOnMs = -1
        var lastLoggedFlashOffMs = -1
        var toggleCount = 0L
        var lateToggleCount = 0L
        var maxLatenessNanos = 0L
        var lastToggleAtNanos = 0L
        var sessionStartNanos = 0L

        fun phaseName(p: Int): String = when (p) {
            0 -> "RED_GREEN"
            1 -> "BLACK"
            2 -> "GREEN_RED"
            else -> "BLACK"
        }

        fun frameForPhase(p: Int): SplitFlashFrame = when (p) {
            0 -> SplitFlashFrame(left = FlashColor.RED, right = FlashColor.GREEN)
            1 -> SplitFlashFrame(left = FlashColor.BLACK, right = FlashColor.BLACK)
            2 -> SplitFlashFrame(left = FlashColor.GREEN, right = FlashColor.RED)
            else -> SplitFlashFrame(left = FlashColor.BLACK, right = FlashColor.BLACK)
        }

        fun updateDurations() {
            val rawOn = latestFlashOnMs.value.coerceIn(50, 2000).toLong() * 1_000_000L
            val rawOff = latestFlashOffMs.value.coerceIn(50, 2000).toLong() * 1_000_000L

            val onFrames = ((rawOn + framePeriodNanos / 2) / framePeriodNanos).coerceAtLeast(1L)
            val offFrames = ((rawOff + framePeriodNanos / 2) / framePeriodNanos).coerceAtLeast(1L)

            onNanos = onFrames * framePeriodNanos
            offNanos = offFrames * framePeriodNanos

            val currentFlashOnMs = latestFlashOnMs.value.coerceIn(50, 2000)
            val currentFlashOffMs = latestFlashOffMs.value.coerceIn(50, 2000)
            if (currentFlashOnMs != lastLoggedFlashOnMs || currentFlashOffMs != lastLoggedFlashOffMs) {
                Log.d(
                    timingLogTag,
                    "config onMs=$currentFlashOnMs offMs=$currentFlashOffMs refreshHz=${"%.2f".format(refreshRateHz)} " +
                        "frameMs=${"%.3f".format(framePeriodNanos / 1_000_000.0)} snappedOnMs=${"%.3f".format(onNanos / 1_000_000.0)} " +
                        "snappedOffMs=${"%.3f".format(offNanos / 1_000_000.0)}"
                )
                lastLoggedFlashOnMs = currentFlashOnMs
                lastLoggedFlashOffMs = currentFlashOffMs
            }
        }

        while (true) {
            withFrameNanos { now ->
                if (!started) {
                    updateDurations()
                    phase = 0
                    nextToggleNanos = now + onNanos
                    value = frameForPhase(phase)
                    started = true
                    sessionStartNanos = now
                    lastToggleAtNanos = now
                    Log.d(
                        timingLogTag,
                        "session-start phase=${phaseName(phase)} refreshHz=${"%.2f".format(refreshRateHz)} " +
                            "frameMs=${"%.3f".format(framePeriodNanos / 1_000_000.0)} nowNs=$now"
                    )
                    return@withFrameNanos
                }

                updateDurations()

                // Catch up if we missed one or more phase boundaries due to frame delays.
                while (now >= nextToggleNanos) {
                    val scheduledToggleNanos = nextToggleNanos
                    val previousPhase = phase
                    phase = (phase + 1) % 4
                    val latenessNanos = now - scheduledToggleNanos
                    val actualDeltaNanos = now - lastToggleAtNanos
                    val dur = if (phase == 0 || phase == 2) onNanos else offNanos
                    nextToggleNanos += dur
                    toggleCount += 1
                    lastToggleAtNanos = now

                    if (latenessNanos > 0L) {
                        lateToggleCount += 1
                        if (latenessNanos > maxLatenessNanos) {
                            maxLatenessNanos = latenessNanos
                        }
                    }

                    val shouldLogToggle = toggleCount <= 20 || latenessNanos > framePeriodNanos || toggleCount % 60L == 0L
                    if (shouldLogToggle) {
                        Log.d(
                            timingLogTag,
                            "toggle#$toggleCount prev=${phaseName(previousPhase)} next=${phaseName(phase)} " +
                                "scheduledMs=${"%.3f".format((scheduledToggleNanos - sessionStartNanos) / 1_000_000.0)} " +
                                "actualMs=${"%.3f".format((now - sessionStartNanos) / 1_000_000.0)} " +
                                "actualDeltaMs=${"%.3f".format(actualDeltaNanos / 1_000_000.0)} " +
                                "latenessMs=${"%.3f".format(latenessNanos / 1_000_000.0)} " +
                                "lateCount=$lateToggleCount maxLateMs=${"%.3f".format(maxLatenessNanos / 1_000_000.0)}"
                        )
                    }
                }

                value = frameForPhase(phase)
            }
        }
    }
}

@Composable
fun SettingsScreen(vm: MainViewModel, onRemoveAds: () -> Unit) {
    val ui by vm.ui.collectAsStateWithLifecycle()
    val scrollState = rememberScrollState()
    Column(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .safeDrawingPadding()
            .verticalScroll(scrollState)
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Text("Settings", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)

        Text("Countdown: ${ui.settings.countdownSeconds}s", color = MaterialTheme.colorScheme.onBackground)
        Slider(
            value = ui.settings.countdownSeconds.toFloat(),
            onValueChange = { vm.updateCountdownSeconds(it.roundToInt()) },
            valueRange = 0f..10f,
            steps = 9,
        )

        Row(verticalAlignment = Alignment.CenterVertically) {
            Checkbox(
                checked = ui.settings.forceAudioWithoutHeadphones,
                onCheckedChange = vm::updateForceAudioWithoutHeadphones,
            )
            Text("force audio without headphones", color = MaterialTheme.colorScheme.onBackground)
        }

        Row(verticalAlignment = Alignment.CenterVertically) {
            Checkbox(checked = ui.settings.showImmersiveProgressBar, onCheckedChange = vm::updateShowImmersiveProgressBar)
            Text("Show immersive bottom progress bar", color = MaterialTheme.colorScheme.onBackground)
        }

        Row(verticalAlignment = Alignment.CenterVertically) {
            Checkbox(checked = ui.settings.preferLowestRefreshRate, onCheckedChange = vm::updatePreferLowestRefreshRate)
            Text("Prefer lowest display refresh rate during sessions", color = MaterialTheme.colorScheme.onBackground)
        }

        Button(onClick = onRemoveAds) {
            Text(if (ui.settings.noAds) "Ads removed" else "Remove ads")
        }

        HorizontalDivider()
        Text(
            "About/Disclaimer: MindMachine is a prototype and not a medical device. Use at your own risk. For immersive visual sessions, keep your eyes closed.",
            color = MaterialTheme.colorScheme.onBackground
        )
    }
}

@Composable
fun RemoveAdsScreen(billingManager: solutions.tretter.mindmachine.billing.BillingManager, vm: MainViewModel) {
    val ui by vm.ui.collectAsStateWithLifecycle()
    val activity = LocalContext.current as? Activity
    val details by billingManager.productDetails.collectAsStateWithLifecycle()

    val subDetails = details[solutions.tretter.mindmachine.billing.BillingProducts.SUB_REMOVE_ADS_MONTHLY]
    val subPrice = subDetails
        ?.subscriptionOfferDetails
        ?.firstOrNull()
        ?.pricingPhases
        ?.pricingPhaseList
        ?.firstOrNull()
        ?.formattedPrice

    val inAppDetails = details[solutions.tretter.mindmachine.billing.BillingProducts.INAPP_REMOVE_ADS_FOREVER]
    val inAppPrice = inAppDetails?.oneTimePurchaseOfferDetails?.formattedPrice

    Column(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .safeDrawingPadding()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        Text("Remove Ads", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)
        Text(
            if (ui.settings.noAds) "You already have ads removed." else "MindMachine is free with ads. You can remove ads via subscription or one-time purchase.",
            color = MaterialTheme.colorScheme.onBackground
        )

        Button(
            enabled = activity != null && !ui.settings.noAds,
            onClick = {
                activity?.let { billingManager.launchPurchase(it, solutions.tretter.mindmachine.billing.BillingProducts.SUB_REMOVE_ADS_MONTHLY) }
            }
        ) {
            Text("Subscribe: ${subPrice ?: "$0.99"}/month")
        }

        Button(
            enabled = activity != null && !ui.settings.noAds,
            onClick = {
                activity?.let { billingManager.launchPurchase(it, solutions.tretter.mindmachine.billing.BillingProducts.INAPP_REMOVE_ADS_FOREVER) }
            }
        ) {
            Text("Buy: ${inAppPrice ?: "$19.99"} one-time")
        }

        TextButton(onClick = { billingManager.refresh() }) { Text("Restore / Refresh purchases") }

        Text(
            "Note: Purchases only work when the app is installed from Google Play (Internal testing/Production). Debug sideloaded builds won’t complete real billing flows.",
            color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f)
        )
    }
}

@Composable
fun PositioningScreen() {
    val scrollState = rememberScrollState()
    Column(
        Modifier
            .fillMaxSize()
            .background(MaterialTheme.colorScheme.background)
            .safeDrawingPadding()
            .verticalScroll(scrollState)
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text("Positioning Guidance", style = MaterialTheme.typography.headlineSmall, color = MaterialTheme.colorScheme.onBackground)

        Image(
            painter = painterResource(R.drawable.positioning_guide),
            contentDescription = "Positioning guide",
            contentScale = ContentScale.Fit,
            modifier = Modifier
                .fillMaxWidth()
                .height(260.dp)
                .padding(vertical = 6.dp)
        )

        Text("• Lie on your back in a safe, comfortable place.", color = MaterialTheme.colorScheme.onBackground)
        Text("• Rest the phone across the upper nose/forehead area so it stays stable.", color = MaterialTheme.colorScheme.onBackground)
        Text("• Keep your eyes closed during immersive visual sessions.", color = MaterialTheme.colorScheme.onBackground)

        Text("Warnings", style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onBackground)
        Text("• Flashing lights may be unsafe for people with epilepsy, seizure sensitivity, or migraine triggers.", color = MaterialTheme.colorScheme.onBackground)
        Text("• Do not stare at the screen, for immersive visual sessions, keep your eyes closed.", color = MaterialTheme.colorScheme.onBackground)
        Text("• Stop immediately for discomfort, dizziness, headache, nausea, anxiety, or eye strain.", color = MaterialTheme.colorScheme.onBackground)

        Spacer(Modifier.height(12.dp))
        Text("Disclaimer", style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.onBackground)
        Text(
            "MindMachine is provided \"as is\" for informational and experimental purposes only, without warranties of any kind. You assume all risks of use. MindMachine is not a medical device and does not provide medical advice. To the maximum extent permitted by law, the developers and distributors disclaim all liability for any claims, damages, losses, or injuries arising from or related to use of the app.",
            color = MaterialTheme.colorScheme.onBackground
        )
    }
}
