package com.syncflow.ui.auth

import android.accounts.AccountManager
import android.app.Activity
import android.view.WindowManager
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.rememberScrollState
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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.syncflow.R
import com.syncflow.domain.model.ProviderType

// All providers in display order
private val ALL_PROVIDERS = listOf(
    ProviderType.NEXTCLOUD,
    ProviderType.OWNCLOUD,
    ProviderType.SFTPGO,
    ProviderType.WEBDAV,
    ProviderType.SFTP,
    ProviderType.GOOGLE_DRIVE,
    ProviderType.DROPBOX,
    ProviderType.ONEDRIVE,
)

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AccountSetupScreen(
    onDone: () -> Unit,
    vm: AccountSetupViewModel = hiltViewModel(),
) {
    val state by vm.state.collectAsState()
    val context = LocalContext.current

    LaunchedEffect(state.done) { if (state.done) onDone() }

    val googleAccountLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val name = result.data?.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)
            if (name != null) vm.onGoogleAccountChosen(name)
        }
    }

    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        if (state.providerType == null) "Choose a service" else state.providerType!!.friendlyName(),
                        fontWeight = FontWeight.SemiBold,
                    )
                },
                navigationIcon = {
                    IconButton(onClick = {
                        if (state.providerType != null) vm.update { copy(providerType = null, testResult = null, error = null) }
                        else onDone()
                    }) {
                        Icon(
                            if (state.providerType != null) Icons.Default.ArrowBack else Icons.Default.Close,
                            contentDescription = null,
                        )
                    }
                },
                actions = {
                    if (state.providerType != null) {
                        TextButton(
                            onClick = vm::save,
                            enabled = !state.isSaving && state.testResult is TestResult.Success,
                        ) {
                            if (state.isSaving) CircularProgressIndicator(Modifier.size(18.dp), strokeWidth = 2.dp)
                            else Text("Save")
                        }
                    }
                },
            )
        },
    ) { padding ->
        if (state.providerType == null) {
            ProviderPickerContent(
                modifier = Modifier.padding(padding),
                onPick = { vm.update { copy(providerType = it) } },
            )
        } else {
            CredentialContent(
                state = state,
                modifier = Modifier.padding(padding),
                vm = vm,
                onDropboxConnect = {
                    launchDropboxOAuth(context, vm.credentialStore, context.getString(R.string.dropbox_app_key))
                },
                onGoogleSignIn = {
                    val intent = AccountManager.newChooseAccountIntent(
                        null, null, arrayOf("com.google"), null, null, null, null,
                    )
                    googleAccountLauncher.launch(intent)
                },
                onOneDriveSignIn = {
                    launchOneDriveOAuth(context, vm.credentialStore, context.getString(R.string.onedrive_client_id))
                },
            )
        }
    }
}

// ─── Step 1: Provider picker grid ────────────────────────────────────────────

@Composable
private fun ProviderPickerContent(modifier: Modifier = Modifier, onPick: (ProviderType) -> Unit) {
    Column(modifier = modifier.fillMaxSize()) {
        Text(
            "Select the service you want to sync with",
            style = MaterialTheme.typography.bodyMedium,
            color = MaterialTheme.colorScheme.onSurfaceVariant,
            modifier = Modifier.padding(horizontal = 20.dp, vertical = 8.dp),
        )
        LazyVerticalGrid(
            columns = GridCells.Fixed(2),
            contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
            horizontalArrangement = Arrangement.spacedBy(12.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp),
            modifier = Modifier.fillMaxSize(),
        ) {
            items(ALL_PROVIDERS) { provider ->
                ProviderCard(provider = provider, onClick = { onPick(provider) })
            }
        }
    }
}

@Composable
private fun ProviderCard(provider: ProviderType, onClick: () -> Unit) {
    ElevatedCard(
        modifier = Modifier
            .fillMaxWidth()
            .aspectRatio(1.4f)
            .clip(MaterialTheme.shapes.large)
            .clickable(onClick = onClick),
        elevation = CardDefaults.elevatedCardElevation(defaultElevation = 3.dp),
    ) {
        Column(
            modifier = Modifier.fillMaxSize().padding(16.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Image(
                painter = painterResource(provider.iconRes()),
                contentDescription = null,
                modifier = Modifier.size(48.dp),
            )
            Spacer(Modifier.height(10.dp))
            Text(
                provider.friendlyName(),
                style = MaterialTheme.typography.titleSmall,
                fontWeight = FontWeight.Medium,
            )
            provider.subtitle()?.let { sub ->
                Text(
                    sub,
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.onSurfaceVariant,
                )
            }
        }
    }
}

// ─── Step 2: Credential form ──────────────────────────────────────────────────

@Composable
private fun CredentialContent(
    state: AccountSetupState,
    modifier: Modifier,
    vm: AccountSetupViewModel,
    onDropboxConnect: () -> Unit,
    onGoogleSignIn: () -> Unit,
    onOneDriveSignIn: () -> Unit,
) {
    val provider = state.providerType ?: return

    // Prevent screenshots and screen recording while credentials are visible
    val activity = LocalContext.current as? Activity
    DisposableEffect(Unit) {
        activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
        onDispose {
            activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
        }
    }

    Column(
        modifier = modifier
            .padding(horizontal = 20.dp)
            .verticalScroll(rememberScrollState()),
        verticalArrangement = Arrangement.spacedBy(14.dp),
    ) {
        Spacer(Modifier.height(4.dp))

        // Account display name
        OutlinedTextField(
            value = state.displayName,
            onValueChange = { vm.update { copy(displayName = it) } },
            label = { Text("Account name (optional)") },
            placeholder = { Text(provider.friendlyName()) },
            leadingIcon = { Icon(Icons.Default.Badge, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        )

        HorizontalDivider()

        // Provider-specific fields
        when {
            provider == ProviderType.GOOGLE_DRIVE -> OAuthSection(
                providerName = "Google Drive",
                email = state.oauthEmail,
                isConnected = state.oauthToken.isNotBlank(),
                onConnect = onGoogleSignIn,
                connectLabel = "Choose Google Account",
                description = "Picks any Google account already added to this device.",
            )
            provider == ProviderType.DROPBOX -> OAuthSection(
                providerName = "Dropbox",
                email = state.oauthEmail,
                isConnected = state.oauthToken.isNotBlank(),
                onConnect = onDropboxConnect,
                connectLabel = "Authorize with Dropbox",
                description = "Opens Dropbox in your browser. Works with any Dropbox account.",
            )
            provider == ProviderType.ONEDRIVE -> OAuthSection(
                providerName = "OneDrive",
                email = state.oauthEmail,
                isConnected = state.oauthToken.isNotBlank(),
                onConnect = onOneDriveSignIn,
                connectLabel = "Sign in with Microsoft",
                description = "Personal, work, or school Microsoft account.",
            )
            provider == ProviderType.SFTP -> SftpFields(state, vm)
            else -> ServerFields(provider, state, vm)
        }

        // Test Connection (required before Save)
        HorizontalDivider()
        Button(
            onClick = vm::testConnection,
            enabled = !state.isTestingConnection && credentialsFilled(state),
            modifier = Modifier.fillMaxWidth(),
            colors = ButtonDefaults.buttonColors(
                containerColor = when (state.testResult) {
                    is TestResult.Success -> MaterialTheme.colorScheme.primary
                    is TestResult.Failure -> MaterialTheme.colorScheme.error
                    null -> MaterialTheme.colorScheme.secondary
                },
            ),
        ) {
            when {
                state.isTestingConnection -> {
                    CircularProgressIndicator(Modifier.size(18.dp), strokeWidth = 2.dp, color = Color.White)
                    Spacer(Modifier.width(10.dp))
                    Text("Testing…")
                }
                state.testResult is TestResult.Success -> {
                    Icon(Icons.Default.CheckCircle, null, Modifier.size(18.dp))
                    Spacer(Modifier.width(8.dp))
                    Text("Connected — tap Save ↑")
                }
                state.testResult is TestResult.Failure -> {
                    Icon(Icons.Default.Refresh, null, Modifier.size(18.dp))
                    Spacer(Modifier.width(8.dp))
                    Text("Retry Test Connection")
                }
                else -> {
                    Icon(Icons.Default.NetworkCheck, null, Modifier.size(18.dp))
                    Spacer(Modifier.width(8.dp))
                    Text("Test Connection")
                }
            }
        }

        when (val r = state.testResult) {
            is TestResult.Failure -> Text(r.message, color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodySmall)
            is TestResult.Success -> Text("Connection successful!", color = MaterialTheme.colorScheme.primary, style = MaterialTheme.typography.bodySmall)
            null -> if (credentialsFilled(state)) Text("Test required before saving.", style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
        }

        state.error?.let { Text(it, color = MaterialTheme.colorScheme.error, style = MaterialTheme.typography.bodySmall) }

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

// ─── Credential field composables ────────────────────────────────────────────

@Composable
private fun OAuthSection(
    providerName: String,
    email: String,
    isConnected: Boolean,
    onConnect: () -> Unit,
    connectLabel: String,
    description: String,
) {
    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        if (!isConnected) {
            Text(description, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
        } else {
            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                Icon(Icons.Default.CheckCircle, null, Modifier.size(20.dp), tint = MaterialTheme.colorScheme.primary)
                Column {
                    Text("Authorized", style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Medium)
                    if (email.isNotBlank()) Text(email, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant)
                }
            }
        }
        OutlinedButton(onClick = onConnect, modifier = Modifier.fillMaxWidth()) {
            Icon(if (isConnected) Icons.Default.SwitchAccount else Icons.Default.Login, null, Modifier.size(18.dp))
            Spacer(Modifier.width(8.dp))
            Text(if (isConnected) "Switch account" else connectLabel)
        }
    }
}

@Composable
private fun ServerFields(provider: ProviderType, state: AccountSetupState, vm: AccountSetupViewModel) {
    val urlHint = when (provider) {
        ProviderType.NEXTCLOUD -> "https://cloud.example.com"
        ProviderType.OWNCLOUD -> "https://owncloud.example.com"
        ProviderType.SFTPGO -> "https://sftpgo.example.com"
        else -> "https://dav.example.com"
    }
    val urlNote = when (provider) {
        ProviderType.NEXTCLOUD -> "Just the base URL — WebDAV path is added automatically."
        ProviderType.OWNCLOUD -> "Just the base URL — WebDAV path is added automatically."
        ProviderType.SFTPGO -> "Base URL only — SFTPGo WebDAV path added automatically."
        else -> null
    }

    Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
        OutlinedTextField(
            value = state.serverUrl,
            onValueChange = { vm.update { copy(serverUrl = it) } },
            label = { Text("Server URL") },
            placeholder = { Text(urlHint) },
            leadingIcon = { Icon(Icons.Default.Language, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri, imeAction = ImeAction.Next),
        )
        urlNote?.let { Text(it, style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant) }
        if (state.httpWarning) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.spacedBy(6.dp),
                modifier = Modifier.fillMaxWidth(),
            ) {
                Icon(Icons.Default.Warning, null, Modifier.size(16.dp), tint = MaterialTheme.colorScheme.error)
                Text(
                    "HTTP sends credentials in plaintext. Use HTTPS for security.",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.error,
                )
            }
        }
        OutlinedTextField(
            value = state.username,
            onValueChange = { vm.update { copy(username = it) } },
            label = { Text("Username") },
            leadingIcon = { Icon(Icons.Default.Person, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        )
        PasswordField(value = state.password, onValueChange = { vm.update { copy(password = it) } }, label = "Password")
    }
}

@Composable
private fun SftpFields(state: AccountSetupState, vm: AccountSetupViewModel) {
    var useKey by remember { mutableStateOf(false) }
    Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
        OutlinedTextField(
            value = state.serverUrl,
            onValueChange = { vm.update { copy(serverUrl = it) } },
            label = { Text("Hostname or IP") },
            placeholder = { Text("sftp.example.com") },
            leadingIcon = { Icon(Icons.Default.Dns, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri, imeAction = ImeAction.Next),
        )
        OutlinedTextField(
            value = state.port,
            onValueChange = { vm.update { copy(port = it) } },
            label = { Text("Port") },
            placeholder = { Text("22") },
            leadingIcon = { Icon(Icons.Default.SettingsEthernet, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Next),
        )
        OutlinedTextField(
            value = state.username,
            onValueChange = { vm.update { copy(username = it) } },
            label = { Text("Username") },
            leadingIcon = { Icon(Icons.Default.Person, null) },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(),
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        )
        Row(verticalAlignment = Alignment.CenterVertically) {
            Switch(checked = useKey, onCheckedChange = { useKey = it })
            Spacer(Modifier.width(10.dp))
            Text("Use SSH private key", style = MaterialTheme.typography.bodySmall)
        }
        if (useKey) {
            OutlinedTextField(
                value = state.privateKey,
                onValueChange = { vm.update { copy(privateKey = it) } },
                label = { Text("Private key (PEM)") },
                placeholder = { Text("-----BEGIN RSA PRIVATE KEY-----\n…") },
                modifier = Modifier.fillMaxWidth().height(120.dp),
            )
        } else {
            PasswordField(value = state.password, onValueChange = { vm.update { copy(password = it) } }, label = "Password")
        }
    }
}

@Composable
private fun PasswordField(value: String, onValueChange: (String) -> Unit, label: String) {
    var visible by remember { mutableStateOf(false) }
    OutlinedTextField(
        value = value,
        onValueChange = onValueChange,
        label = { Text(label) },
        leadingIcon = { Icon(Icons.Default.Lock, null) },
        trailingIcon = {
            IconButton(onClick = { visible = !visible }) {
                Icon(if (visible) Icons.Default.VisibilityOff else Icons.Default.Visibility, null)
            }
        },
        visualTransformation = if (visible) VisualTransformation.None else PasswordVisualTransformation(),
        singleLine = true,
        modifier = Modifier.fillMaxWidth(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done),
    )
}

// ─── Helpers ──────────────────────────────────────────────────────────────────

private fun credentialsFilled(state: AccountSetupState): Boolean {
    val p = state.providerType ?: return false
    return when {
        p.isOAuth() -> state.oauthToken.isNotBlank()
        p == ProviderType.SFTP -> state.serverUrl.isNotBlank() && state.username.isNotBlank()
        else -> state.serverUrl.isNotBlank() && state.username.isNotBlank()
    }
}

private fun ProviderType.iconRes() = when (this) {
    ProviderType.NEXTCLOUD -> R.drawable.ic_provider_nextcloud
    ProviderType.OWNCLOUD -> R.drawable.ic_provider_owncloud
    ProviderType.SFTPGO -> R.drawable.ic_provider_sftpgo
    ProviderType.WEBDAV -> R.drawable.ic_provider_webdav
    ProviderType.SFTP -> R.drawable.ic_provider_sftp
    ProviderType.GOOGLE_DRIVE -> R.drawable.ic_provider_googledrive
    ProviderType.DROPBOX -> R.drawable.ic_provider_dropbox
    ProviderType.ONEDRIVE -> R.drawable.ic_provider_onedrive
}

private fun ProviderType.subtitle() = when (this) {
    ProviderType.NEXTCLOUD -> "Self-hosted"
    ProviderType.OWNCLOUD -> "Self-hosted"
    ProviderType.SFTPGO -> "Self-hosted"
    ProviderType.WEBDAV -> "Any WebDAV server"
    ProviderType.SFTP -> "SSH file transfer"
    ProviderType.GOOGLE_DRIVE -> "Google account"
    ProviderType.DROPBOX -> "Dropbox account"
    ProviderType.ONEDRIVE -> "Microsoft account"
}
