package dev.privacyllc.period.feature.settings

import android.Manifest
import android.content.res.Configuration
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.privacyllc.period.core.datastore.NotificationPrivacy
import dev.privacyllc.period.core.datastore.UserPreferences
import dev.privacyllc.period.designsystem.PeriodTheme
import java.time.LocalTime
import java.time.format.DateTimeFormatter

/**
 * Notification settings — §28's privacy mode and §29's six toggles.
 *
 * A child of [SettingsScreen] rather than the Settings tab itself. It carried a
 * "Batch 05 · working surface" banner until the §36 tree existed to hold it;
 * the banner is gone because the claim it made is no longer true, not because
 * the screen changed.
 */
@Composable
fun NotificationSettingsScreen(viewModel: NotificationSettingsViewModel = hiltViewModel()) {
    val prefs by viewModel.state.collectAsStateWithLifecycle()
    val needsPermission by viewModel.needsPermission.collectAsStateWithLifecycle()

    val launcher = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission(),
    ) { viewModel.permissionHandled() }

    // §31: asked when a reminder is switched on, never on first launch. A
    // permission dialog before the user has seen the app is one answered "deny"
    // out of reflex, and there is no second chance.
    LaunchedEffect(needsPermission) {
        if (needsPermission && Build.VERSION.SDK_INT >= 33) {
            launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
        } else if (needsPermission) {
            viewModel.permissionHandled()
        }
    }

    NotificationSettingsContent(prefs, viewModel)
}

@Composable
private fun NotificationSettingsContent(
    prefs: UserPreferences,
    viewModel: NotificationSettingsViewModel?,
) {
    Column(
        Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
    ) {
        Text("How reminders appear", style = MaterialTheme.typography.titleMedium)
        Spacer(Modifier.height(4.dp))
        Text(
            "This is what someone standing next to you can read on your lock screen.",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )
        Spacer(Modifier.height(8.dp))

        Column(Modifier.selectableGroup()) {
            PrivacyRow("Discreet", "\"Quick check-in\"", prefs.notificationPrivacy == NotificationPrivacy.DISCREET) {
                viewModel?.setPrivacy(NotificationPrivacy.DISCREET)
            }
            PrivacyRow("Maximum privacy", "\"Reminder\"", prefs.notificationPrivacy == NotificationPrivacy.MAXIMUM_PRIVACY) {
                viewModel?.setPrivacy(NotificationPrivacy.MAXIMUM_PRIVACY)
            }
            PrivacyRow("Direct", "\"Your period may start soon\"", prefs.notificationPrivacy == NotificationPrivacy.DIRECT) {
                viewModel?.setPrivacy(NotificationPrivacy.DIRECT)
            }
        }

        Spacer(Modifier.height(20.dp))
        HorizontalDivider()
        Spacer(Modifier.height(20.dp))

        Text("What to remind me about", style = MaterialTheme.typography.titleMedium)
        Spacer(Modifier.height(8.dp))

        // Six switches, not one. §29 makes them independent, and "period
        // reminders yes, fertility no" is the common case rather than an edge.
        Toggle("Period approaching", prefs.periodApproachingEnabled) { viewModel?.setPeriodApproaching(it) }
        Toggle("Period expected today", prefs.periodExpectedTodayEnabled) { viewModel?.setPeriodExpectedToday(it) }
        Toggle("Did it start?", prefs.didItStartEnabled) { viewModel?.setDidItStart(it) }
        Toggle("Period end check-in", prefs.periodEndCheckInEnabled) { viewModel?.setPeriodEndCheckIn(it) }
        Toggle("Fertile window approaching", prefs.fertileWindowReminderEnabled) { viewModel?.setFertileWindow(it) }
        Toggle("Estimated ovulation", prefs.ovulationReminderEnabled) { viewModel?.setOvulation(it) }

        Spacer(Modifier.height(20.dp))
        HorizontalDivider()
        Spacer(Modifier.height(20.dp))

        Text("When", style = MaterialTheme.typography.titleMedium)
        Spacer(Modifier.height(8.dp))
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            listOf(
                "Morning" to LocalTime.of(9, 0),
                "Afternoon" to LocalTime.of(14, 0),
                "Evening" to LocalTime.of(19, 0),
            ).forEach { (label, time) ->
                TextButton(onClick = { viewModel?.setReminderTime(time) }) { Text(label) }
            }
        }
        Text(
            "Currently ${prefs.reminderTime.format(timeFormat)}",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )

        Spacer(Modifier.height(24.dp))
        Text(
            "Reminders are scheduled with WorkManager and may arrive a few minutes either " +
                "side of this time. Nothing about your cycle leaves the device.",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )
    }
}

@Composable
    // The whole row is the target, not the radio.
    //
    // Found by tapping the label "Maximum privacy" on a device and watching
    // nothing happen: only the RadioButton was clickable, so the option that
    // decides what a lock screen shows could only be changed by hitting a
    // ~20dp circle. selectable() on the Row with onClick = null on the radio is
    // Material's documented pattern, and it also merges the semantics — TalkBack
    // now announces one selectable option per row instead of a radio button
    // followed by two loose pieces of text.
private fun PrivacyRow(title: String, example: String, selected: Boolean, onSelect: () -> Unit) {
    Card(Modifier.fillMaxWidth().padding(vertical = 3.dp)) {
        Row(
            Modifier
                .fillMaxWidth()
                .selectable(
                    selected = selected,
                    role = Role.RadioButton,
                    onClick = onSelect,
                )
                .padding(12.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            RadioButton(selected = selected, onClick = null)
            Spacer(Modifier.height(8.dp))
            Column(Modifier.padding(start = 8.dp)) {
                Text(title, style = MaterialTheme.typography.titleSmall)
                Text(
                    example,
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
            }
        }
    }
}

@Composable
private fun Toggle(label: String, checked: Boolean, onChange: (Boolean) -> Unit) {
    Row(
        Modifier.fillMaxWidth().padding(vertical = 6.dp),
        horizontalArrangement = Arrangement.SpaceBetween,
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(label, style = MaterialTheme.typography.bodyLarge)
        Switch(checked = checked, onCheckedChange = onChange)
    }
}

private val timeFormat = DateTimeFormatter.ofPattern("HH:mm")

@Preview(name = "Notification settings", showBackground = true, heightDp = 900)
@Preview(
    name = "Notification settings dark",
    showBackground = true,
    heightDp = 900,
    uiMode = Configuration.UI_MODE_NIGHT_YES,
)
@Composable
private fun PreviewSettings() = PeriodTheme {
    NotificationSettingsContent(UserPreferences.Defaults, null)
}
