package com.example.mystictale.Screen

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
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.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.paint
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import coil.compose.AsyncImagePainter
import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest
import com.example.mystictale.R
import com.example.mystictale.ViewModels.AuthViewModel
import com.example.mystictale.models.UserState
import com.example.mystictale.resources.components.ChooseGenderForProfile
import com.example.mystictale.resources.components.ImageForBitmap
import com.example.mystictale.resources.components.ImagePainter
import com.example.mystictale.resources.components.Loading
import com.example.mystictale.resources.components.ProfileTextField
import com.example.mystictale.resources.components.dateComponents.DateOfBirthTextFieldForProfile
import com.example.mystictale.resources.components.dateComponents.FormattingDateForDatabase
import com.example.mystictale.resources.components.dateComponents.FormattingDateForProfile
import com.example.mystictale.resources.components.dateComponents.ValidationDate
import com.example.mystictale.resources.components.dateComponents.isDateValid
import com.example.mystictale.ui.theme.DarkPurple
import com.example.mystictale.ui.theme.Grey
import com.example.mystictale.ui.theme.OpenSans
import com.vanpra.composematerialdialogs.MaterialDialog
import com.vanpra.composematerialdialogs.datetime.date.datepicker
import com.vanpra.composematerialdialogs.rememberMaterialDialogState
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.Locale

@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun Profile(navController: NavController, viewModel: AuthViewModel) {

    val user by viewModel.user
    val userState by viewModel.userState
    val focusManager = LocalFocusManager.current
    val context = LocalContext.current
    val keyboardController = LocalSoftwareKeyboardController.current
    val isEnabled = remember { mutableStateOf(false) }
    val flagName = remember { mutableStateOf(false) }
    val flag = remember { mutableStateOf(true) }
    val flag1 = remember { mutableStateOf(false) }
    val flag2 = remember { mutableStateOf(false) }
    val nameFlag = remember { mutableStateOf(false) }
    val dateOfBirthFlag = remember { mutableStateOf(false) }

    val dateDialogState = rememberMaterialDialogState()


    if (flag.value) {
        viewModel.selectProfile()
        flag.value = false
    }
    if (user.isNotEmpty()) {
        val newAvatar = remember { mutableStateOf(byteArrayOf()) }
        val avatarFrombase = rememberAsyncImagePainter(
            model = ImageRequest.Builder(LocalContext.current).data(user.last().avatar)
                .size(100, 100).build()
        ).state
        val newAvatarBitmap = remember { mutableStateOf<ImageBitmap?>(null) }
        val name = remember { mutableStateOf(user.last().name) }
        val dateOfBirth =
            remember { mutableStateOf(FormattingDateForProfile(user.last().date_of_birth)) }
        val formatForScreen = SimpleDateFormat("ddMMyyyy", Locale.getDefault())
        val formatter = DateTimeFormatter.ofPattern("ddMMyyyy")
        val date =
            FormattingDateForProfile(user.last().date_of_birth)!!.let { formatForScreen.parse(it) }
        val dateForDatePicker = remember {
            mutableStateOf(
                date!!.toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDate()
            )
        }
        val formattedDate by remember {
            derivedStateOf {
                DateTimeFormatter.ofPattern("ddMMyyyy").format(dateForDatePicker.value)
            }
        }
        val dateForBase = FormattingDateForDatabase(dateOfBirth.value!!)
        val gender = remember {
            mutableStateOf(
                if (user.last().id_gender == 1) {
                    "Женский"
                } else {
                    "Мужской"
                }
            )
        }
        val launcher =
            rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
                if (uri == null) return@rememberLauncherForActivityResult
                newAvatar.value = bitmapToByteArray(context, uri)

            }
        Column(
            Modifier
                .fillMaxSize()
                .paint(
                    painterResource(id = R.drawable.background),
                    contentScale = ContentScale.FillBounds
                )
                .pointerInput(Unit) {
                    detectTapGestures(onTap = {
                        keyboardController?.hide()
                        focusManager.clearFocus()
                    })
                }
                .padding(10.dp)
                .padding(top = 50.dp),
            verticalArrangement = Arrangement.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Box(modifier = Modifier.fillMaxWidth()) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Text(
                        text = "Профиль",
                        fontFamily = OpenSans,
                        fontWeight = FontWeight.Bold,
                        fontSize = 40.sp,
                        color = Color.White
                    )
                }
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.End,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Icon(
                        painter = painterResource(id = R.drawable.update),
                        contentDescription = "update your profile",
                        tint = if (!isEnabled.value) Grey else Color.Transparent,

                        modifier = Modifier
                            .padding(end = 5.dp)
                            .height(21.dp)
                            .width(21.dp)
                            .clickable {
                                if (!isEnabled.value) {
                                    isEnabled.value = !isEnabled.value
                                    if (viewModel.gender == 1) {
                                        gender.value = "Женский"
                                    } else {
                                        gender.value = "Мужской"
                                    }
                                }
                            }

                    )
                }
            }
            Spacer(modifier = Modifier.height(20.dp))
            if (newAvatar.value.isEmpty()) {
                if (avatarFrombase is AsyncImagePainter.State.Success) {
                    ImagePainter(
                        isEnabled = isEnabled.value,
                        image = avatarFrombase.painter,
                        launcher = launcher
                    )
                }
                if (avatarFrombase is AsyncImagePainter.State.Loading) {
                    Box(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(200.dp),
                        contentAlignment = Alignment.Center
                    ) {
                        CircularProgressIndicator()
                    }
                }
                if (avatarFrombase is AsyncImagePainter.State.Error) {

                    if (user.last().id_gender == 1) {
                        ImagePainter(
                            isEnabled = isEnabled.value,
                            image = painterResource(R.drawable.girl),
                            launcher = launcher
                        )
                    } else {
                        ImagePainter(
                            isEnabled = isEnabled.value,
                            image = painterResource(R.drawable.girl),
                            launcher = launcher
                        )
                    }

                }
            } else {
                newAvatarBitmap.value = ByteArrayImage(newAvatar.value)
                ImageForBitmap(
                    isEnabled = isEnabled.value,
                    image = newAvatarBitmap.value!!,
                    launcher = launcher
                )

            }
            Spacer(modifier = Modifier.height(10.dp))
            Column(
                Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 20.dp)
            ) {
                Text(
                    text = "Имя",
                    fontFamily = OpenSans,
                    fontWeight = FontWeight.Bold,
                    fontSize = 14.sp,
                    color = Grey
                )
                Spacer(modifier = Modifier.height(5.dp))
                ProfileTextField(
                    value = name.value,
                    onValue = {
                        name.value = it
                        nameFlag.value = false
                    }, placeholder = "Имя",
                    keyboardType = KeyboardType.Text,
                    isEnable = isEnabled.value,
                    flag = flagName.value,
                    date = false
                )
                if (nameFlag.value) {
                    Text(
                        "Введите имя",
                        fontWeight = FontWeight.Light,
                        fontFamily = OpenSans,
                        fontSize = 13.sp,
                        color = Color.Red
                    )
                }
            }
            Spacer(modifier = Modifier.height(10.dp))
            Column(
                Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 20.dp)
            ) {
                Text(
                    text = "Дата рождения",
                    fontFamily = OpenSans,
                    fontWeight = FontWeight.Bold,
                    fontSize = 14.sp,
                    color = Grey
                )
                Spacer(modifier = Modifier.height(5.dp))

                DateOfBirthTextFieldForProfile(
                    dateOfBirth = dateOfBirth.value!!,
                    onValue = { dob ->
                        dateOfBirth.value = dob.filter { it.isDigit() }.take(8)
                        dateOfBirthFlag.value = false

                    },
                    dateDialogState = dateDialogState,
                    flag = dateOfBirthFlag.value,
                    enabled = isEnabled.value
                )
                if (dateOfBirthFlag.value) {
                    if (dateOfBirth.value!!.isEmpty()) {
                        Text(
                            "Введите дату рождения",
                            fontWeight = FontWeight.Light,
                            fontFamily = OpenSans,
                            fontSize = 13.sp,
                            color = Color.Red
                        )
                    } else if (dateOfBirth.value!!.length < 8) {
                        Text(
                            "Неверная дата рождения",
                            fontWeight = FontWeight.Light,
                            fontFamily = OpenSans,
                            fontSize = 13.sp,
                            color = Color.Red
                        )
                    } else if (!isDateValid(dateOfBirth.value!!)) {
                        Text(
                            "Неверная дата рождения",
                            fontWeight = FontWeight.Light,
                            fontFamily = OpenSans,
                            fontSize = 13.sp,
                            color = Color.Red
                        )
                    } else if (LocalDate.parse(dateOfBirth.value, formatter) > LocalDate.now()) {
                        Text(
                            "Неверная дата рождения",
                            fontWeight = FontWeight.Light,
                            fontFamily = OpenSans,
                            fontSize = 13.sp,
                            color = Color.Red
                        )
                    }
                }
            }
            Spacer(modifier = Modifier.height(5.dp))
            Column(
                Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 20.dp)
            ) {
                Text(
                    text = "Пол",
                    fontFamily = OpenSans,
                    fontWeight = FontWeight.Bold,
                    fontSize = 14.sp,
                    color = Grey
                )
                Spacer(modifier = Modifier.height(5.dp))

                ChooseGenderForProfile(
                    viewModel = viewModel,
                    gender = gender.value,
                    isEnabled = isEnabled.value
                )


            }

            AnimatedVisibility(visible = isEnabled.value, Modifier.padding(40.dp)) {
                Button(
                    onClick = {
                        if (ValidationDate(
                                dateOfBirth.value!!,
                                formatter
                            ) || name.value.isEmpty()
                        ) {
                            if (ValidationDate(dateOfBirth.value!!, formatter)) {
                                dateOfBirthFlag.value = true

                            }
                            if (name.value.isEmpty()) {
                                nameFlag.value = true
                            }
                        } else {
                            viewModel.name = name.value
                            viewModel.dateOfBirth = dateForBase
                            viewModel.gender = if (gender.value == "Женский") {
                                1
                            } else {
                                2
                            }
                            viewModel.addAvatar(newAvatar.value)
                            flag1.value = true
                        }

                    },
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(48.dp)
                        .padding(horizontal = 30.dp),
                    shape = RoundedCornerShape(12.dp),
                    colors = ButtonColors(
                        containerColor = DarkPurple,
                        contentColor = Color.White,
                        disabledContentColor = Color.White,
                        disabledContainerColor = DarkPurple
                    )
                ) {
                    Text("Сохранить", fontSize = 20.sp, fontWeight = FontWeight.Bold)

                }
            }


        }
        MaterialDialog(
            dialogState = dateDialogState,
            buttons = {
                positiveButton(text = "Ok")
                negativeButton("cancel")
            })
        {
            datepicker(
                initialDate = dateForDatePicker.value,
                allowedDateValidator = {
                    it <= LocalDate.now()
                }


            ) {
                dateForDatePicker.value = it
                dateOfBirth.value = formattedDate.toString()

            }
        }
    } else {
        Box(
            Modifier
                .fillMaxSize()
                .paint(
                    painterResource(id = R.drawable.background),
                    contentScale = ContentScale.FillBounds
                )
        ) {
            Loading()
        }
    }
    if (flag1.value) {
        when (userState) {
            is UserState.Loading -> {
                Loading()
            }

            is UserState.Success -> {
                val message = (userState as UserState.Success).message
                viewModel.updateProfile()
                flag1.value = false
                flag2.value = true
            }

            is UserState.Error -> {
                val message = (userState as UserState.Error).message
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
                flag1.value = false
            }
        }
    }
    if (flag2.value) {
        when (userState) {
            is UserState.Loading -> {
                Loading()
            }

            is UserState.Success -> {
                Toast.makeText(context, "Изменения сохранены", Toast.LENGTH_SHORT).show()
                isEnabled.value = false
                flag2.value = false
            }

            is UserState.Error -> {
                val message = (userState as UserState.Error).message
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
                flag2.value = false
            }
        }
    }


}

fun bitmapToByteArray(context: Context, uri: Uri): ByteArray {
    val inputStream = context.contentResolver.openInputStream(uri)
    val bitmap = BitmapFactory.decodeStream(inputStream)
    val baos = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos)
    return baos.toByteArray()
}


fun ByteArrayImage(byteArray: ByteArray): ImageBitmap {
    // Конвертируем массив байтов в Bitmap с уменьшением масштаба
    val options = BitmapFactory.Options().apply {
        inJustDecodeBounds = true // Сначала считываем только размеры изображения
    }
    BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)

    // Рассчитываем inSampleSize для уменьшения изображения
    options.inSampleSize = calculateInSampleSize(options, reqWidth = 300, reqHeight = 200)
    options.inJustDecodeBounds = false // Теперь декодируем само изображение

    // Декодируем уменьшенное изображение
    val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)

    // Преобразуем Bitmap в ImageBitmap
    return bitmap.asImageBitmap()


}

fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
    val (height: Int, width: Int) = options.outHeight to options.outWidth
    var inSampleSize = 1

    if (height > reqHeight || width > reqWidth) {
        val halfHeight: Int = height / 2
        val halfWidth: Int = width / 2

        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
            inSampleSize *= 2
        }
    }
    return inSampleSize
}