package com.rosetta.messenger.ui.auth

import android.os.Build
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
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.statusBarsPadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
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.LocalView
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 com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.animateLottieCompositionAsState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.rosetta.messenger.R
import com.rosetta.messenger.di.ProtocolGateway
import com.rosetta.messenger.network.DeviceResolveSolution
import com.rosetta.messenger.network.Packet
import com.rosetta.messenger.network.PacketDeviceResolve
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import compose.icons.TablerIcons
import compose.icons.tablericons.DeviceMobile
import kotlinx.coroutines.launch

@Composable
fun DeviceConfirmScreen(
    isDarkTheme: Boolean,
    protocolGateway: ProtocolGateway,
    onExit: () -> Unit
) {
    val view = LocalView.current
    if (!view.isInEditMode) {
        SideEffect {
            val window = (view.context as? android.app.Activity)?.window ?: return@SideEffect
            val insetsController = androidx.core.view.WindowCompat.getInsetsController(window, view)
            window.statusBarColor = android.graphics.Color.TRANSPARENT
            insetsController.isAppearanceLightStatusBars = false
        }
    }

    val themeAnimSpec =
        tween<Color>(durationMillis = 500, easing = CubicBezierEasing(0.4f, 0f, 0.2f, 1f))

    val backgroundColor by
        animateColorAsState(
            targetValue = if (isDarkTheme) AuthBackground else AuthBackgroundLight,
            animationSpec = themeAnimSpec
        )
    val surfaceColor by
        animateColorAsState(
            targetValue = if (isDarkTheme) AuthSurface else AuthSurfaceLight,
            animationSpec = themeAnimSpec
        )
    val borderColor by
        animateColorAsState(
            targetValue = if (isDarkTheme) Color(0xFF3E3E43) else Color(0xFFE3E3E8),
            animationSpec = themeAnimSpec
        )
    val textColor by
        animateColorAsState(
            targetValue = if (isDarkTheme) Color.White else Color.Black,
            animationSpec = themeAnimSpec
        )
    val secondaryTextColor by
        animateColorAsState(
            targetValue = if (isDarkTheme) Color(0xFF8E8E93) else Color(0xFF666666),
            animationSpec = themeAnimSpec
        )
    val accentColor = PrimaryBlue
    val exitButtonColor = if (isDarkTheme) Color(0xFF3A2629) else Color(0xFFFFEAED)
    val exitButtonTextColor = Color(0xFFFF5E61)
    val onExitState by rememberUpdatedState(onExit)
    val scope = rememberCoroutineScope()

    val lifecycleOwner = androidx.compose.ui.platform.LocalLifecycleOwner.current
    var isResumed by remember(lifecycleOwner) {
        mutableStateOf(
            lifecycleOwner.lifecycle.currentState.isAtLeast(
                androidx.lifecycle.Lifecycle.State.RESUMED
            )
        )
    }
    DisposableEffect(lifecycleOwner) {
        val observer = androidx.lifecycle.LifecycleEventObserver { _, _ ->
            isResumed = lifecycleOwner.lifecycle.currentState.isAtLeast(
                androidx.lifecycle.Lifecycle.State.RESUMED
            )
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.device_confirm))
    val progress by animateLottieCompositionAsState(
        composition = composition,
        iterations = LottieConstants.IterateForever,
        isPlaying = isResumed
    )

    val localDeviceName = remember {
        listOf(Build.MANUFACTURER.orEmpty(), Build.MODEL.orEmpty())
            .filter { it.isNotBlank() }
            .distinct()
            .joinToString(" ")
            .ifBlank { "this device" }
    }

    DisposableEffect(Unit) {
        val callback: (Packet) -> Unit = callback@{ packet ->
            val resolve = packet as? PacketDeviceResolve ?: return@callback
            if (resolve.solution == DeviceResolveSolution.DECLINE) {
                scope.launch { onExitState() }
            }
        }
        protocolGateway.waitPacket(0x18, callback)
        onDispose {
            protocolGateway.unwaitPacket(0x18, callback)
        }
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(backgroundColor)
            .statusBarsPadding()
            .navigationBarsPadding()
            .padding(horizontal = 22.dp),
        contentAlignment = Alignment.Center
    ) {
        Column(
            modifier =
                Modifier
                    .fillMaxWidth()
                    .widthIn(max = 420.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Spacer(modifier = Modifier.weight(0.2f))

            Box(
                modifier =
                    Modifier.size(102.dp),
                contentAlignment = Alignment.Center
            ) {
                LottieAnimation(
                    composition = composition,
                    progress = { progress },
                    modifier = Modifier.size(82.dp)
                )
            }

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

            Row(verticalAlignment = Alignment.CenterVertically) {
                Icon(
                    imageVector = TablerIcons.DeviceMobile,
                    contentDescription = null,
                    tint = accentColor,
                    modifier = Modifier.size(16.dp)
                )
                Spacer(modifier = Modifier.size(6.dp))
                Text(
                    text = "NEW DEVICE REQUEST",
                    color = accentColor,
                    fontSize = 12.sp,
                    fontWeight = FontWeight.SemiBold
                )
            }

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

            Text(
                text = "Waiting for approval",
                color = textColor,
                fontSize = 30.sp,
                lineHeight = 36.sp,
                fontWeight = FontWeight.Bold,
                textAlign = TextAlign.Center
            )

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

            Text(
                text = "Open Rosetta on your first device and approve this login request.",
                color = secondaryTextColor,
                fontSize = 15.sp,
                textAlign = TextAlign.Center,
                lineHeight = 22.sp
            )

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

            Surface(
                modifier = Modifier.fillMaxWidth(),
                color = surfaceColor,
                shape = RoundedCornerShape(14.dp),
                border = BorderStroke(1.dp, borderColor)
            ) {
                Column(
                    modifier = Modifier.padding(horizontal = 14.dp, vertical = 12.dp),
                    verticalArrangement = Arrangement.spacedBy(4.dp)
                ) {
                    Text(
                        text = "This device",
                        color = secondaryTextColor,
                        fontSize = 12.sp,
                        fontWeight = FontWeight.Medium
                    )
                    Text(
                        text = localDeviceName,
                        color = textColor,
                        fontSize = 17.sp,
                        fontWeight = FontWeight.SemiBold
                    )
                }
            }

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

            Text(
                text = "If this wasn't you, tap Exit.",
                color = secondaryTextColor,
                fontSize = 13.sp,
                textAlign = TextAlign.Center
            )

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

            Button(
                onClick = onExitState,
                modifier =
                    Modifier
                        .fillMaxWidth()
                        .height(52.dp),
                colors = ButtonDefaults.buttonColors(
                    containerColor = exitButtonColor,
                    contentColor = exitButtonTextColor
                ),
                border = BorderStroke(1.dp, exitButtonTextColor.copy(alpha = 0.35f)),
                shape = RoundedCornerShape(14.dp)
            ) {
                Text(
                    text = "Exit",
                    fontSize = 17.sp,
                    fontWeight = FontWeight.SemiBold
                )
            }

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

            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.Center
            ) {
                Text(
                    text = "Waiting for confirmation",
                    color = secondaryTextColor,
                    fontSize = 12.sp
                )
                Spacer(modifier = Modifier.size(8.dp))
                WaitingDots(color = secondaryTextColor)
            }

            Spacer(modifier = Modifier.weight(0.24f))
        }
    }
}

@Composable
private fun WaitingDots(color: Color) {
    val transition = rememberInfiniteTransition(label = "waiting-dots")
    val progress by transition.animateFloat(
        initialValue = 0f,
        targetValue = 1f,
        animationSpec =
            infiniteRepeatable(
                animation = tween(durationMillis = 1000, easing = FastOutSlowInEasing)
            ),
        label = "waiting-dots-progress"
    )

    Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
        repeat(3) { index ->
            val shifted = (progress + index * 0.22f) % 1f
            val alpha = 0.3f + (1f - shifted) * 0.7f
            Box(
                modifier =
                    Modifier
                        .size(5.dp)
                        .clip(CircleShape)
                        .background(color.copy(alpha = alpha))
            )
        }
    }
}
