package com.bytelyst.platform.ui

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.bytelyst.platform.BLAuthClient
import kotlinx.coroutines.launch

// ── Auth UI Configuration ────────────────────────────────────

/** OAuth providers supported by BLAuthUI. */
enum class BLAuthProvider { GOOGLE, MICROSOFT, APPLE }

/**
 * Configuration passed to BLAuthUI screens.
 * Host product provides its theme colors and enabled providers.
 */
data class BLAuthUIConfig(
    val productName: String = "ByteLyst",
    val enabledProviders: List<BLAuthProvider> = listOf(BLAuthProvider.GOOGLE, BLAuthProvider.APPLE),
)

// ── BLLoginScreen ────────────────────────────────────────────

/**
 * Full login screen with email/password + social buttons + passkey option.
 * Host product wraps this in its MaterialTheme for consistent theming.
 *
 * @param config UI configuration (product name, enabled providers).
 * @param onLogin Called with (email, password) when user taps Sign In.
 * @param onSocialLogin Called with provider when user taps a social button.
 * @param onPasskeyLogin Called when user taps "Use Passkey" (null to hide).
 * @param onForgotPassword Called when user taps "Forgot Password?" (null to hide).
 * @param onCreateAccount Called when user taps "Create Account" (null to hide).
 */
@Composable
fun BLLoginScreen(
    config: BLAuthUIConfig = BLAuthUIConfig(),
    onLogin: suspend (String, String) -> Unit,
    onSocialLogin: (BLAuthProvider) -> Unit,
    onPasskeyLogin: (() -> Unit)? = null,
    onForgotPassword: (() -> Unit)? = null,
    onCreateAccount: (() -> Unit)? = null,
) {
    var email by remember { mutableStateOf("") }
    var password by remember { mutableStateOf("") }
    var isLoading by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    val scope = rememberCoroutineScope()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(horizontal = 24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Spacer(Modifier.height(48.dp))

        // Header
        Text(
            text = "Sign in to ${config.productName}",
            style = MaterialTheme.typography.headlineSmall,
            color = MaterialTheme.colorScheme.onSurface,
        )
        Spacer(Modifier.height(8.dp))
        Text(
            text = "Welcome back",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
        )
        Spacer(Modifier.height(32.dp))

        // Social Buttons
        if (config.enabledProviders.isNotEmpty()) {
            config.enabledProviders.forEach { provider ->
                SocialButton(provider = provider, onClick = { onSocialLogin(provider) })
                Spacer(Modifier.height(12.dp))
            }
            DividerRow()
            Spacer(Modifier.height(16.dp))
        }

        // Email / Password
        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Email") },
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
        )
        Spacer(Modifier.height(12.dp))

        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Password") },
            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
        )
        Spacer(Modifier.height(16.dp))

        // Error
        errorMessage?.let {
            Text(
                text = it,
                style = MaterialTheme.typography.bodySmall,
                color = MaterialTheme.colorScheme.error,
                textAlign = TextAlign.Center,
            )
            Spacer(Modifier.height(8.dp))
        }

        // Sign In Button
        Button(
            onClick = {
                scope.launch {
                    isLoading = true
                    errorMessage = null
                    try {
                        onLogin(email, password)
                    } catch (e: BLAuthClient.MfaRequiredException) {
                        // MFA required — handled by caller
                    } catch (e: Exception) {
                        errorMessage = e.message ?: "Login failed"
                    }
                    isLoading = false
                }
            },
            enabled = email.isNotBlank() && password.isNotBlank() && !isLoading,
            modifier = Modifier.fillMaxWidth().height(52.dp),
            shape = RoundedCornerShape(10.dp),
        ) {
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.size(20.dp),
                    strokeWidth = 2.dp,
                    color = MaterialTheme.colorScheme.onPrimary,
                )
                Spacer(Modifier.width(8.dp))
            }
            Text("Sign In")
        }
        Spacer(Modifier.height(12.dp))

        // Passkey
        if (onPasskeyLogin != null) {
            OutlinedButton(
                onClick = onPasskeyLogin,
                modifier = Modifier.fillMaxWidth().height(52.dp),
                shape = RoundedCornerShape(10.dp),
            ) {
                Icon(Icons.Default.Key, contentDescription = null, modifier = Modifier.size(20.dp))
                Spacer(Modifier.width(8.dp))
                Text("Sign in with Passkey")
            }
            Spacer(Modifier.height(16.dp))
        }

        // Forgot Password / Create Account
        if (onForgotPassword != null) {
            TextButton(onClick = onForgotPassword) {
                Text("Forgot Password?")
            }
        }

        if (onCreateAccount != null) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text(
                    "Don't have an account?",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
                TextButton(onClick = onCreateAccount) {
                    Text("Create Account")
                }
            }
        }

        Spacer(Modifier.height(32.dp))
    }
}

// ── BLMfaChallengeScreen ─────────────────────────────────────

/**
 * 6-digit TOTP code entry with recovery code fallback.
 *
 * @param challenge The MFA challenge from login response.
 * @param onVerify Called with (challengeToken, code, method) on submit.
 * @param onCancel Called when user cancels.
 */
@Composable
fun BLMfaChallengeScreen(
    challenge: BLAuthClient.MfaChallenge,
    onVerify: suspend (String, String, String) -> Unit,
    onCancel: (() -> Unit)? = null,
) {
    var code by remember { mutableStateOf("") }
    var isLoading by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    var useRecovery by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Icon(
            imageVector = Icons.Default.Lock,
            contentDescription = null,
            modifier = Modifier.size(56.dp),
            tint = MaterialTheme.colorScheme.primary,
        )
        Spacer(Modifier.height(16.dp))

        Text(
            text = "Two-Factor Authentication",
            style = MaterialTheme.typography.titleMedium,
        )
        Spacer(Modifier.height(8.dp))

        Text(
            text = if (useRecovery) "Enter a recovery code"
                   else "Enter the 6-digit code from your authenticator app",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(24.dp))

        OutlinedTextField(
            value = code,
            onValueChange = { code = it },
            label = { Text(if (useRecovery) "Recovery Code" else "Code") },
            keyboardOptions = KeyboardOptions(
                keyboardType = if (useRecovery) KeyboardType.Text else KeyboardType.Number,
            ),
            singleLine = true,
            textStyle = LocalTextStyle.current.copy(
                fontFamily = FontFamily.Monospace,
                textAlign = TextAlign.Center,
            ),
            modifier = Modifier.width(200.dp),
        )
        Spacer(Modifier.height(16.dp))

        errorMessage?.let {
            Text(it, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error)
            Spacer(Modifier.height(8.dp))
        }

        Button(
            onClick = {
                scope.launch {
                    isLoading = true
                    errorMessage = null
                    val method = if (useRecovery) "recovery" else "totp"
                    try {
                        onVerify(challenge.mfaChallenge, code, method)
                    } catch (e: Exception) {
                        errorMessage = e.message ?: "Verification failed"
                        code = ""
                    }
                    isLoading = false
                }
            },
            enabled = code.isNotBlank() && !isLoading,
            modifier = Modifier.fillMaxWidth().height(52.dp),
            shape = RoundedCornerShape(10.dp),
        ) {
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.size(20.dp),
                    strokeWidth = 2.dp,
                    color = MaterialTheme.colorScheme.onPrimary,
                )
                Spacer(Modifier.width(8.dp))
            }
            Text("Verify")
        }
        Spacer(Modifier.height(16.dp))

        TextButton(onClick = {
            useRecovery = !useRecovery
            code = ""
            errorMessage = null
        }) {
            Text(if (useRecovery) "Use authenticator code" else "Use recovery code")
        }

        if (onCancel != null) {
            TextButton(onClick = onCancel) {
                Text("Cancel", color = MaterialTheme.colorScheme.onSurfaceVariant)
            }
        }
    }
}

// ── BLPasskeyScreen ──────────────────────────────────────────

/**
 * Passkey prompt with biometric hint text.
 * Triggers Android Credential Manager for passkey authentication.
 *
 * @param onAuthenticate Called when user taps Continue (triggers passkey flow).
 * @param onCancel Called when user taps "Use another method".
 */
@Composable
fun BLPasskeyScreen(
    onAuthenticate: suspend () -> Unit,
    onCancel: (() -> Unit)? = null,
) {
    var isLoading by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    val scope = rememberCoroutineScope()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(24.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Icon(
            imageVector = Icons.Default.Key,
            contentDescription = null,
            modifier = Modifier.size(56.dp),
            tint = MaterialTheme.colorScheme.primary,
        )
        Spacer(Modifier.height(16.dp))

        Text(
            text = "Sign in with Passkey",
            style = MaterialTheme.typography.titleMedium,
        )
        Spacer(Modifier.height(8.dp))

        Text(
            text = "Use your fingerprint, face, or screen lock to sign in",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(24.dp))

        errorMessage?.let {
            Text(it, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error)
            Spacer(Modifier.height(8.dp))
        }

        Button(
            onClick = {
                scope.launch {
                    isLoading = true
                    errorMessage = null
                    try {
                        onAuthenticate()
                    } catch (e: Exception) {
                        errorMessage = e.message ?: "Passkey authentication failed"
                    }
                    isLoading = false
                }
            },
            enabled = !isLoading,
            modifier = Modifier.fillMaxWidth().height(52.dp),
            shape = RoundedCornerShape(10.dp),
        ) {
            if (isLoading) {
                CircularProgressIndicator(
                    modifier = Modifier.size(20.dp),
                    strokeWidth = 2.dp,
                    color = MaterialTheme.colorScheme.onPrimary,
                )
                Spacer(Modifier.width(8.dp))
            }
            Icon(Icons.Default.Fingerprint, contentDescription = null, modifier = Modifier.size(20.dp))
            Spacer(Modifier.width(8.dp))
            Text("Continue")
        }
        Spacer(Modifier.height(16.dp))

        if (onCancel != null) {
            TextButton(onClick = onCancel) {
                Text("Use another method")
            }
        }
    }
}

// ── BLDeviceListScreen ───────────────────────────────────────

/**
 * Device management screen — list trusted/remembered devices, revoke trust.
 *
 * @param devices List of devices from BLAuthClient.listDevices().
 * @param onRevokeDevice Called with device ID when user revokes a device.
 * @param onRevokeAll Called when user revokes all devices.
 * @param isLoading Whether data is loading.
 */
@Composable
fun BLDeviceListScreen(
    devices: List<BLAuthClient.Device>,
    onRevokeDevice: (String) -> Unit,
    onRevokeAll: (() -> Unit)? = null,
    isLoading: Boolean = false,
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(
                text = "Your Devices",
                style = MaterialTheme.typography.titleMedium,
            )
            if (onRevokeAll != null && devices.isNotEmpty()) {
                TextButton(onClick = onRevokeAll) {
                    Text("Revoke All", color = MaterialTheme.colorScheme.error)
                }
            }
        }
        Spacer(Modifier.height(16.dp))

        if (isLoading) {
            Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator()
            }
        } else if (devices.isEmpty()) {
            Text(
                text = "No devices found",
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
            )
        } else {
            devices.forEach { device ->
                DeviceCard(device = device, onRevoke = { onRevokeDevice(device.fingerprint) })
                Spacer(Modifier.height(8.dp))
            }
        }
    }
}

@Composable
private fun DeviceCard(
    device: BLAuthClient.Device,
    onRevoke: () -> Unit,
) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
    ) {
        Row(
            modifier = Modifier.padding(16.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Icon(
                imageVector = when (device.platform) {
                    "ios" -> Icons.Default.PhoneIphone
                    "android" -> Icons.Default.PhoneAndroid
                    "macos", "windows", "linux" -> Icons.Default.Laptop
                    else -> Icons.Default.Devices
                },
                contentDescription = device.platform,
                modifier = Modifier.size(32.dp),
                tint = when (device.trustLevel) {
                    "trusted" -> MaterialTheme.colorScheme.primary
                    "remembered" -> MaterialTheme.colorScheme.secondary
                    else -> MaterialTheme.colorScheme.onSurfaceVariant
                },
            )
            Spacer(Modifier.width(12.dp))

            Column(modifier = Modifier.weight(1f)) {
                Text(
                    text = device.name,
                    style = MaterialTheme.typography.bodyLarge,
                )
                Text(
                    text = "${device.trustLevel} · ${device.platform}",
                    style = MaterialTheme.typography.bodySmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
            }

            if (device.trustLevel == "trusted" || device.trustLevel == "remembered") {
                IconButton(onClick = onRevoke) {
                    Icon(
                        Icons.Default.Close,
                        contentDescription = "Revoke",
                        tint = MaterialTheme.colorScheme.error,
                    )
                }
            }
        }
    }
}

// ── BLStepUpDialog ───────────────────────────────────────────

/**
 * Re-authentication dialog for sensitive operations.
 * Supports password re-entry.
 *
 * @param reason Description of why re-auth is needed.
 * @param onStepUp Called with (method, credential) — returns step-up token.
 * @param onComplete Called with the step-up token on success.
 * @param onDismiss Called when user dismisses the dialog.
 */
@Composable
fun BLStepUpDialog(
    reason: String = "This action requires re-authentication",
    onStepUp: suspend (String, String) -> String,
    onComplete: (String) -> Unit,
    onDismiss: () -> Unit,
) {
    var password by remember { mutableStateOf("") }
    var isLoading by remember { mutableStateOf(false) }
    var errorMessage by remember { mutableStateOf<String?>(null) }
    val scope = rememberCoroutineScope()

    AlertDialog(
        onDismissRequest = onDismiss,
        icon = {
            Icon(Icons.Default.Lock, contentDescription = null, modifier = Modifier.size(32.dp))
        },
        title = { Text("Confirm Your Identity") },
        text = {
            Column {
                Text(
                    text = reason,
                    style = MaterialTheme.typography.bodyMedium,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
                Spacer(Modifier.height(16.dp))

                OutlinedTextField(
                    value = password,
                    onValueChange = { password = it },
                    label = { Text("Password") },
                    visualTransformation = PasswordVisualTransformation(),
                    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
                    singleLine = true,
                    modifier = Modifier.fillMaxWidth(),
                )

                errorMessage?.let {
                    Spacer(Modifier.height(8.dp))
                    Text(it, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.error)
                }
            }
        },
        confirmButton = {
            Button(
                onClick = {
                    scope.launch {
                        isLoading = true
                        errorMessage = null
                        try {
                            val token = onStepUp("password", password)
                            onComplete(token)
                            onDismiss()
                        } catch (e: Exception) {
                            errorMessage = e.message ?: "Verification failed"
                        }
                        isLoading = false
                    }
                },
                enabled = password.isNotBlank() && !isLoading,
            ) {
                if (isLoading) {
                    CircularProgressIndicator(
                        modifier = Modifier.size(16.dp),
                        strokeWidth = 2.dp,
                        color = MaterialTheme.colorScheme.onPrimary,
                    )
                    Spacer(Modifier.width(8.dp))
                }
                Text("Confirm")
            }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) {
                Text("Cancel")
            }
        },
    )
}

// ── Shared Components ────────────────────────────────────────

@Composable
private fun SocialButton(
    provider: BLAuthProvider,
    onClick: () -> Unit,
) {
    OutlinedButton(
        onClick = onClick,
        modifier = Modifier.fillMaxWidth().height(52.dp),
        shape = RoundedCornerShape(10.dp),
    ) {
        Icon(
            imageVector = when (provider) {
                BLAuthProvider.GOOGLE -> Icons.Default.Public
                BLAuthProvider.MICROSOFT -> Icons.Default.Business
                BLAuthProvider.APPLE -> Icons.Default.Star
            },
            contentDescription = null,
            modifier = Modifier.size(20.dp),
        )
        Spacer(Modifier.width(8.dp))
        Text(
            text = "Continue with ${
                when (provider) {
                    BLAuthProvider.GOOGLE -> "Google"
                    BLAuthProvider.MICROSOFT -> "Microsoft"
                    BLAuthProvider.APPLE -> "Apple"
                }
            }",
        )
    }
}

@Composable
private fun DividerRow() {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp),
    ) {
        HorizontalDivider(modifier = Modifier.weight(1f))
        Text(
            text = "or",
            style = MaterialTheme.typography.bodySmall,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            modifier = Modifier.padding(horizontal = 16.dp),
        )
        HorizontalDivider(modifier = Modifier.weight(1f))
    }
}
