package com.rosetta.messenger.ui.auth

import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import compose.icons.TablerIcons
import compose.icons.tablericons.*
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.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.rosetta.messenger.crypto.CryptoManager
import com.rosetta.messenger.data.AccountManager
import com.rosetta.messenger.data.DecryptedAccount
import com.rosetta.messenger.di.ProtocolGateway
import com.rosetta.messenger.network.PacketUserInfo
import com.rosetta.messenger.ui.icons.TelegramIcons
import com.rosetta.messenger.ui.settings.ProfilePhotoPicker
import com.rosetta.messenger.utils.AvatarFileManager
import com.rosetta.messenger.utils.ImageCropHelper
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.database.RosettaDatabase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull

private val PrimaryBlue = Color(0xFF248AE6)
private val ErrorRed = Color(0xFFFF3B30)

private const val NAME_MAX_LENGTH = 40
private const val USERNAME_MIN_LENGTH = 5
private const val USERNAME_MAX_LENGTH = 32
private val NAME_ALLOWED_REGEX = Regex("^[\\p{L}\\p{N} ._'-]+$")
private val USERNAME_ALLOWED_REGEX = Regex("^[A-Za-z0-9_]+$")

private fun validateName(name: String): String? {
    if (name.isBlank()) return "Name can't be empty"
    if (name.length > NAME_MAX_LENGTH) return "Name is too long (max $NAME_MAX_LENGTH)"
    if (!NAME_ALLOWED_REGEX.matches(name)) return "Only letters, numbers, spaces, . _ - ' are allowed"
    return null
}

private fun validateUsername(username: String): String? {
    if (username.isBlank()) return null // optional
    if (username.length < USERNAME_MIN_LENGTH) return "Username must be at least $USERNAME_MIN_LENGTH characters"
    if (username.length > USERNAME_MAX_LENGTH) return "Username is too long (max $USERNAME_MAX_LENGTH)"
    if (!USERNAME_ALLOWED_REGEX.matches(username)) return "Use only letters, numbers, and underscore"
    return null
}

@Composable
fun SetProfileScreen(
    isDarkTheme: Boolean,
    account: DecryptedAccount?,
    protocolGateway: ProtocolGateway,
    accountManager: AccountManager,
    onComplete: () -> Unit,
    onSkip: () -> Unit
) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()

    var name by remember { mutableStateOf("") }
    var username by remember { mutableStateOf("") }
    var nameTouched by remember { mutableStateOf(false) }
    var usernameTouched by remember { mutableStateOf(false) }
    var avatarUri by remember { mutableStateOf<String?>(null) }
    var showPhotoPicker by remember { mutableStateOf(false) }
    var isSaving by remember { mutableStateOf(false) }
    var visible by remember { mutableStateOf(false) }

    // Username availability check
    var usernameAvailable by remember { mutableStateOf<Boolean?>(null) }
    var isCheckingUsername by remember { mutableStateOf(false) }

    LaunchedEffect(username) {
        val trimmed = username.trim()
        if (trimmed.length < USERNAME_MIN_LENGTH) {
            usernameAvailable = null
            return@LaunchedEffect
        }
        if (validateUsername(trimmed) != null) {
            usernameAvailable = null
            return@LaunchedEffect
        }
        usernameAvailable = null
        isCheckingUsername = true
        delay(600) // debounce
        try {
            val results = protocolGateway.searchUsers(trimmed, 3000)
            val taken = results.any { it.username.equals(trimmed, ignoreCase = true) }
            usernameAvailable = !taken
        } catch (_: Exception) {
            usernameAvailable = null
        }
        isCheckingUsername = false
    }

    val nameError = if (nameTouched) validateName(name.trim()) else null
    val localUsernameError = if (usernameTouched) validateUsername(username.trim()) else null
    val usernameError = localUsernameError
        ?: if (usernameTouched && usernameAvailable == false) "Username is already taken" else null
    val isFormValid = validateName(name.trim()) == null
        && validateUsername(username.trim()) == null
        && usernameAvailable != false

    LaunchedEffect(Unit) { visible = true }

    val cropLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult()
    ) { result ->
        val croppedUri = ImageCropHelper.getCroppedImageUri(result)
        if (croppedUri != null) {
            avatarUri = croppedUri.toString()
        }
    }

    val backgroundColor = if (isDarkTheme) Color(0xFF1A1A1A) else Color(0xFFF8F8FF)
    val cardColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color.White
    val textColor = if (isDarkTheme) Color.White else Color(0xFF1A1A1A)
    val secondaryText = Color(0xFF8E8E93)
    val avatarBg = if (isDarkTheme) Color(0xFF333336) else PrimaryBlue

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(backgroundColor)
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(horizontal = 24.dp)
                .statusBarsPadding()
                .navigationBarsPadding(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Spacer(modifier = Modifier.height(16.dp))

            // Skip button
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.End
            ) {
                TextButton(onClick = onSkip) {
                    Text(
                        text = "Skip",
                        color = PrimaryBlue,
                        fontSize = 16.sp,
                        fontWeight = FontWeight.Medium
                    )
                }
            }

            Spacer(modifier = Modifier.height(24.dp))

            // Avatar
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400)) + scaleIn(tween(400), initialScale = 0.8f)
            ) {
                Box(
                    contentAlignment = Alignment.Center,
                    modifier = Modifier
                        .size(100.dp)
                        .clip(CircleShape)
                        .background(avatarBg)
                        .clickable { showPhotoPicker = true }
                ) {
                    if (avatarUri != null) {
                        AsyncImage(
                            model = ImageRequest.Builder(context)
                                .data(Uri.parse(avatarUri))
                                .crossfade(true)
                                .build(),
                            contentDescription = "Avatar",
                            modifier = Modifier.fillMaxSize(),
                            contentScale = ContentScale.Crop
                        )
                    } else {
                        Icon(
                            painter = TelegramIcons.Camera,
                            contentDescription = "Set photo",
                            tint = Color.White,
                            modifier = Modifier.size(36.dp)
                        )
                    }
                }
            }

            Spacer(modifier = Modifier.height(8.dp))

            TextButton(onClick = { showPhotoPicker = true }) {
                Text(
                    text = "Set Photo",
                    color = PrimaryBlue,
                    fontSize = 14.sp
                )
            }

            Spacer(modifier = Modifier.height(24.dp))

            // Title
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400, delayMillis = 150))
            ) {
                Text(
                    text = "What's your name?",
                    fontSize = 24.sp,
                    fontWeight = FontWeight.Bold,
                    color = textColor,
                    textAlign = TextAlign.Center
                )
            }

            Spacer(modifier = Modifier.height(8.dp))

            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400, delayMillis = 250))
            ) {
                Text(
                    text = "Your friends can find you by this name. It will be displayed in chats, groups, and your profile.",
                    fontSize = 15.sp,
                    color = secondaryText,
                    textAlign = TextAlign.Center,
                    lineHeight = 20.sp
                )
            }

            Spacer(modifier = Modifier.height(28.dp))

            // Name & Username inputs
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400, delayMillis = 350))
            ) {
                Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
                    // Name field
                    Column {
                        TextField(
                            value = name,
                            onValueChange = {
                                name = it.take(NAME_MAX_LENGTH)
                                nameTouched = true
                            },
                            placeholder = {
                                Text("Your name", color = secondaryText)
                            },
                            isError = nameError != null,
                            modifier = Modifier
                                .fillMaxWidth()
                                .clip(RoundedCornerShape(14.dp)),
                            singleLine = true,
                            colors = TextFieldDefaults.colors(
                                focusedTextColor = textColor,
                                unfocusedTextColor = textColor,
                                focusedContainerColor = cardColor,
                                unfocusedContainerColor = cardColor,
                                errorContainerColor = cardColor,
                                focusedIndicatorColor = Color.Transparent,
                                unfocusedIndicatorColor = Color.Transparent,
                                errorIndicatorColor = Color.Transparent,
                                cursorColor = PrimaryBlue
                            )
                        )
                        if (nameError != null) {
                            Text(
                                text = nameError,
                                fontSize = 12.sp,
                                color = ErrorRed,
                                modifier = Modifier.padding(start = 16.dp, top = 4.dp)
                            )
                        }
                    }

                    Spacer(modifier = Modifier.height(8.dp))

                    // Username field
                    Column {
                        TextField(
                            value = username,
                            onValueChange = { raw ->
                                username = raw.take(USERNAME_MAX_LENGTH)
                                    .lowercase()
                                    .filter { it.isLetterOrDigit() || it == '_' }
                                usernameTouched = true
                            },
                            placeholder = {
                                Text("Username", color = secondaryText)
                            },
                            prefix = {
                                Text("@", color = secondaryText, fontSize = 16.sp)
                            },
                            trailingIcon = {
                                when {
                                    isCheckingUsername && username.trim().length >= USERNAME_MIN_LENGTH -> {
                                        CircularProgressIndicator(
                                            modifier = Modifier.size(18.dp),
                                            strokeWidth = 2.dp,
                                            color = secondaryText
                                        )
                                    }
                                    usernameAvailable == true && usernameError == null -> {
                                        Icon(
                                            imageVector = TablerIcons.Check,
                                            contentDescription = "Available",
                                            tint = Color(0xFF4CAF50),
                                            modifier = Modifier.size(20.dp)
                                        )
                                    }
                                    usernameAvailable == false -> {
                                        Icon(
                                            imageVector = TablerIcons.X,
                                            contentDescription = "Taken",
                                            tint = ErrorRed,
                                            modifier = Modifier.size(20.dp)
                                        )
                                    }
                                }
                            },
                            isError = usernameError != null,
                            modifier = Modifier
                                .fillMaxWidth()
                                .clip(RoundedCornerShape(14.dp)),
                            singleLine = true,
                            keyboardOptions = androidx.compose.foundation.text.KeyboardOptions(
                                capitalization = androidx.compose.ui.text.input.KeyboardCapitalization.None,
                                autoCorrect = false
                            ),
                            colors = TextFieldDefaults.colors(
                                focusedTextColor = textColor,
                                unfocusedTextColor = textColor,
                                focusedContainerColor = cardColor,
                                unfocusedContainerColor = cardColor,
                                errorContainerColor = cardColor,
                                focusedIndicatorColor = Color.Transparent,
                                unfocusedIndicatorColor = Color.Transparent,
                                errorIndicatorColor = Color.Transparent,
                                cursorColor = PrimaryBlue
                            )
                        )
                        if (usernameError != null) {
                            Text(
                                text = usernameError,
                                fontSize = 12.sp,
                                color = ErrorRed,
                                modifier = Modifier.padding(start = 16.dp, top = 4.dp)
                            )
                        } else if (usernameAvailable == true) {
                            Text(
                                text = "Username is available!",
                                fontSize = 12.sp,
                                color = Color(0xFF4CAF50),
                                modifier = Modifier.padding(start = 16.dp, top = 4.dp)
                            )
                        } else {
                            Text(
                                text = "Username is optional. People can use it to find you without sharing your key.",
                                fontSize = 12.sp,
                                color = secondaryText.copy(alpha = 0.7f),
                                modifier = Modifier.padding(start = 16.dp, top = 4.dp),
                                lineHeight = 16.sp
                            )
                        }
                    }
                }
            }

            Spacer(modifier = Modifier.height(32.dp))

            // Continue button
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400, delayMillis = 450))
            ) {
                Button(
                    onClick = {
                        if (account == null) {
                            onComplete()
                            return@Button
                        }
                        isSaving = true
                        scope.launch {
                            try {
                                // Wait for server connection (up to 8s)
                                val connected = withTimeoutOrNull(8000) {
                                    while (!protocolGateway.isAuthenticated()) {
                                        delay(300)
                                    }
                                    true
                                } ?: false

                                // Save name and username locally first
                                if (name.trim().isNotEmpty()) {
                                    accountManager.updateAccountName(account.publicKey, name.trim())
                                }
                                if (username.trim().isNotEmpty()) {
                                    accountManager.updateAccountUsername(account.publicKey, username.trim())
                                }
                                // Trigger UI refresh in MainActivity
                                protocolGateway.notifyOwnProfileUpdated()

                                // Send name and username to server
                                if (connected && (name.trim().isNotEmpty() || username.trim().isNotEmpty())) {
                                    val packet = PacketUserInfo()
                                    packet.title = name.trim()
                                    packet.username = username.trim()
                                    packet.privateKey = account.privateKeyHash
                                    protocolGateway.send(packet)
                                    delay(1500)

                                    // Повторяем для надёжности
                                    if (protocolGateway.isAuthenticated()) {
                                        val packet2 = PacketUserInfo()
                                        packet2.title = name.trim()
                                        packet2.username = username.trim()
                                        packet2.privateKey = account.privateKeyHash
                                        protocolGateway.send(packet2)
                                        delay(500)
                                    }
                                }

                                // Save avatar
                                if (avatarUri != null) {
                                    withContext(Dispatchers.IO) {
                                        val uri = Uri.parse(avatarUri)
                                        val rawBytes = context.contentResolver
                                            .openInputStream(uri)?.use { it.readBytes() }
                                        if (rawBytes != null && rawBytes.isNotEmpty()) {
                                            val preparedBase64 = AvatarFileManager
                                                .imagePrepareForNetworkTransfer(context, rawBytes)
                                            if (preparedBase64.isNotBlank()) {
                                                val db = RosettaDatabase.getDatabase(context)
                                                val avatarRepo = AvatarRepository(
                                                    context = context,
                                                    avatarDao = db.avatarDao(),
                                                    currentPublicKey = account.publicKey
                                                )
                                                avatarRepo.saveAvatar(
                                                    fromPublicKey = account.publicKey,
                                                    base64Image = "data:image/png;base64,$preparedBase64"
                                                )
                                            }
                                        }
                                    }
                                }

                                onComplete()
                            } catch (_: Exception) {
                                onComplete()
                            }
                        }
                    },
                    enabled = isFormValid && !isSaving,
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(52.dp),
                    colors = ButtonDefaults.buttonColors(
                        containerColor = PrimaryBlue,
                        contentColor = Color.White,
                        disabledContainerColor = PrimaryBlue.copy(alpha = 0.5f),
                        disabledContentColor = Color.White.copy(alpha = 0.5f)
                    ),
                    shape = RoundedCornerShape(14.dp)
                ) {
                    if (isSaving) {
                        CircularProgressIndicator(
                            modifier = Modifier.size(22.dp),
                            color = Color.White,
                            strokeWidth = 2.dp
                        )
                    } else {
                        Text(
                            text = "Continue",
                            fontSize = 17.sp,
                            fontWeight = FontWeight.SemiBold
                        )
                    }
                }
            }

            Spacer(modifier = Modifier.weight(1f))

            // Examples of where name appears
            AnimatedVisibility(
                visible = visible,
                enter = fadeIn(tween(400, delayMillis = 550))
            ) {
                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(bottom = 24.dp),
                    horizontalAlignment = Alignment.CenterHorizontally
                ) {
                    Text(
                        text = "Your name will appear in:",
                        fontSize = 13.sp,
                        color = secondaryText,
                        fontWeight = FontWeight.Medium
                    )
                    Spacer(modifier = Modifier.height(6.dp))
                    Text(
                        text = "Chat list  •  Messages  •  Groups  •  Profile",
                        fontSize = 13.sp,
                        color = secondaryText.copy(alpha = 0.7f)
                    )
                }
            }
        }
    }

    ProfilePhotoPicker(
        isVisible = showPhotoPicker,
        onDismiss = { showPhotoPicker = false },
        onPhotoSelected = { uri ->
            showPhotoPicker = false
            val cropIntent = ImageCropHelper.createCropIntent(context, uri, isDarkTheme)
            cropLauncher.launch(cropIntent)
        },
        isDarkTheme = isDarkTheme
    )
}
