@file:OptIn(SupabaseExperimental::class)

package com.example.iplace.main.viewModel

import android.content.Context
import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavHostController
import com.example.iplace.domain.Constants
import com.example.iplace.model.Category
import com.example.iplace.model.Gender
import com.example.iplace.model.Place
import com.example.iplace.model.Users
import io.github.jan.supabase.annotations.SupabaseExperimental
import io.github.jan.supabase.gotrue.auth
import io.github.jan.supabase.gotrue.providers.builtin.Email
import io.github.jan.supabase.postgrest.from
import io.github.jan.supabase.postgrest.query.Columns
import io.github.jan.supabase.realtime.selectAsFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch

class MainViewModel(): ViewModel() {

    private val _authData = mutableStateOf(AuthData())
    val authData: State<AuthData> = _authData

    fun onSignInEmailPassword(context: Context,emailUser: String, passwordUser1: String, navController: NavHostController) {
        _authData.value = AuthData(email = emailUser, password = passwordUser1)
        viewModelScope.launch {
            try {
                val user = Constants.supabase.auth.signInWith(Email) {
                    email = emailUser
                    password = passwordUser1
                }

                println(user.toString())
                println(Constants.supabase.auth.currentUserOrNull()!!.id)
                println("Success")
                navController.navigate("menuV")
            } catch (e: Exception) {
                println("Error")
                println(e.message.toString())
            }
        }
    }
    fun onSignUpEmail(context: Context,emailUser: String, passwordUser1: String, passwordUser2: String, navController: NavHostController) {
        _authData.value = AuthData(email = emailUser, password = passwordUser1)

        if(emailUser != "" && passwordUser1 != "" && passwordUser2 != "" ) {

            if(passwordUser1 == passwordUser2) {
                if(passwordUser1.length >= 8){

                    viewModelScope.launch {
                        try{
                            val user = Constants.supabase.auth.signUpWith(Email) {
                                email = emailUser
                                password = passwordUser1
                            }

                            println(user.toString())
                            println(Constants.supabase.auth.currentUserOrNull()!!.id)
                            println("Success")

                            navController.navigate("creatingUser")
                        }
                        catch (e: Exception) {
                            println("Error")
                            println(e.message.toString())
                        }

                    }
                }
                else Log.i("Reg", "Длина пароля должна быть от 8 до 64 символов")
            }
            else Log.i("Reg", "Пароли не совпадают")

        }
        else Log.i("Reg", "Не все поля заполнены")

    }

    fun resetPassword(passwordUser: String, navController: NavHostController) {
        viewModelScope.launch {
            try {
                // Получаем email и password из authData
                val email = authData.value.email
                val password = authData.value.password

                // Проверяем, авторизован ли пользователь
                if (Constants.supabase.auth.currentUserOrNull() == null) {
                    // Если нет, то пытаемся авторизоваться с сохраненными данными
                    if (email.isNotEmpty() && password.isNotEmpty()) {
                        Constants.supabase.auth.signInWith(Email) {
                            this.email = email
                            this.password = password
                        }
                    } else {
                        // Обработка ситуации, когда нет сохраненных данных
                        Log.e("AddNewUserInTable", "No user data found for sign-in.")
                        return@launch
                    }
                }

                val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return@launch
                val emailUser = Constants.supabase.auth.currentUserOrNull()?.email ?: return@launch
                Log.d("my_tag", idUser)

                Constants.supabase.auth.resetPasswordForEmail(email = emailUser)
                Constants.supabase.auth.updateUser {
                    this.password = passwordUser
                }
                Log.d("my_tag", "Success changed password")
                navController.navigate("profile")
            } catch (e: Exception) {
                Log.d("my_tag", e.message!!)
            }
        }

    }

    fun AddNewUserInTable(nameUser: String, address: String, about_me: String, id_genderFK: String, img_user: String, navController: NavHostController){
        viewModelScope.launch {
            try {
                // Получаем email и password из authData
                val email = authData.value.email
                val password = authData.value.password

                // Проверяем, авторизован ли пользователь
                if (Constants.supabase.auth.currentUserOrNull() == null) {
                    // Если нет, то пытаемся авторизоваться с сохраненными данными
                    if (email.isNotEmpty() && password.isNotEmpty()) {
                        Constants.supabase.auth.signInWith(Email) {
                            this.email = email
                            this.password = password
                        }
                    } else {
                        // Обработка ситуации, когда нет сохраненных данных
                        Log.e("AddNewUserInTable", "No user data found for sign-in.")
                        return@launch
                    }
                }

                val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return@launch
                val newUser = Users(id_uuid = idUser, name = nameUser, address = address, about_me = about_me, id_genderFK = 1, img_user = "dsad")

                Constants.supabase.from("users").insert(newUser)

                navController.navigate("policyConditionality")
            } catch (e: Exception) {
                Log.e("AddNewUserInTable", "Error adding user: ${e.message}")
            }
        }
    }


//    fun AddNewPlaceInTable(title: String, address: String, description: String, navController: NavHostController){
//        viewModelScope.launch {
//            try {
//                val newPlace = Place(id_place = \\ ,title = title, address = address, description = description, img_place = "", id_categoryFK = 1,mapping = "", author = "")
//
//                Constants.supabase.from("place").insert(newPlace)
//
//                navController.navigate("menuV")
//            } catch (e: Exception) {
//                Log.e("AddNewPlaceInTable", "Error adding place: ${e.message}")
//            }
//        }
//    }

    suspend fun getGenderList() = Constants.supabase.from("gender")
        .select()
        .decodeList<Gender>()

    suspend fun getCategoryList() = Constants.supabase.from("category")
        .select()
        .decodeList<Category>()

    private val _place = mutableStateOf<Place?>(null)
    val place: State<Place?> = _place

    suspend fun getPlaceList() = Constants.supabase.from("place")
        .select()
        .decodeList<Place>()


    fun getPlaceListRealTime() = Constants.supabase.from("Place")
        .selectAsFlow(Place ::id_place)

    suspend fun getPlaceById(id: String?) = Constants.supabase.from("place")
        .select(columns = Columns.list("id_place","title","img_place","id_categoryFK","description","address","mapping","author")){
            filter {
                Place::id_place eq id
            }
        }.decodeSingle<Place>()



    suspend fun  insertPlace(place: Place, navController: NavHostController){
        try {
            Log.e("insertPlace", "Зашел")
            Constants.supabase.from("place")
            .insert(place)

            navController.navigate("menuV")
            Log.e("insertPlace", "Без ошибок добавление")
        } catch (e: Exception) {
            Log.e("insertPlace", "Error : ${e.message}")
        }
    }

    suspend fun  deletePlace(place: Place){
        Constants.supabase.from("place")
            .delete{
                filter {
                    Place::id_place eq place.id_place
                }
            }
    }

    suspend fun  upsertPlace(place: Place, navController: NavHostController){
        try {
            Constants.supabase.from("place")
                .upsert(place)

            navController.navigate("menuV")
            Log.e("upsertPlace", "Без ошибок добавление")
        } catch (e: Exception) {
            Log.e("upsertPlace", "Error : ${e.message}")
        }
    }

    suspend fun  updatePlace(place: Place){
        Constants.supabase.from("place")
            .update(
                {
                    set("title", place.title)
                    set("img_place", place.img_place)
                    set("id_categoryFK", place.id_categoryFK)
                    set("description", place.description)
                    set("address", place.address)
                    set("mapping", place.mapping)
                    set("author", place.author)
                }
            ) {
                filter {
                    Place::id_place eq place.id_place
                }
            }
    }
    private val _user = mutableStateOf<Users?>(null)
    val user: State<Users?> = _user
    suspend fun getUserById() {
        try {
            // Получаем email и password из authData
            val email = authData.value.email
            val password = authData.value.password

            // Проверяем, авторизован ли пользователь
            if (Constants.supabase.auth.currentUserOrNull() == null) {
                // Если нет, то пытаемся авторизоваться с сохраненными данными
                if (email.isNotEmpty() && password.isNotEmpty()) {
                    Constants.supabase.auth.signInWith(Email) {
                        this.email = email
                        this.password = password
                    }
                } else {
                    // Обработка ситуации, когда нет сохраненных данных
                    Log.e("AddNewUserInTable", "No user data found for sign-in.")
                    return
                }
            }
            val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return

            val userResult = Constants.supabase.from("users")
                .select(columns = Columns.list("name","address","about_me","id_genderFK","img_user","id_uuid")){
                    filter {
                        Users::id_uuid eq idUser
                    }
                }.decodeSingle<Users>()

            // Обновляем состояние _user в ViewModel
            _user.value = userResult

        } catch (e: Exception) {
            Log.e("getPlaceById", "Error : ${e.message}")
        }
    }

    suspend fun  insertUser(users: Users){
        Constants.supabase.from("users")
            .insert(users)
    }
    suspend fun  deleteUser(users: Users, navController: NavHostController){
        try {
            // Получаем email и password из authData
            val email = authData.value.email
            val password = authData.value.password

            // Проверяем, авторизован ли пользователь
            if (Constants.supabase.auth.currentUserOrNull() == null) {
                // Если нет, то пытаемся авторизоваться с сохраненными данными
                if (email.isNotEmpty() && password.isNotEmpty()) {
                    Constants.supabase.auth.signInWith(Email) {
                        this.email = email
                        this.password = password
                    }
                } else {
                    // Обработка ситуации, когда нет сохраненных данных
                    Log.e("AddNewUserInTable", "No user data found for sign-in.")
                    return
                }
            }
            val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return
            Constants.supabase.from("users")
            .delete{
                filter {
                    Users::id_uuid eq idUser
                }
            }
            navController.navigate("selectEnter")
            Log.e("updateUser", "Без ошибок удаление")

        } catch (e: Exception) {
            Log.e("getPlaceById", "Error : ${e.message}")
        }
    }
    suspend fun  upsertUser(users: Users){
        Constants.supabase.from("users")
            .upsert(users)
    }


    suspend fun  updateUser(users: Users, navController: NavHostController){
        try {
            // Получаем email и password из authData
            val email = authData.value.email
            val password = authData.value.password

            // Проверяем, авторизован ли пользователь
            if (Constants.supabase.auth.currentUserOrNull() == null) {
                // Если нет, то пытаемся авторизоваться с сохраненными данными
                if (email.isNotEmpty() && password.isNotEmpty()) {
                    Constants.supabase.auth.signInWith(Email) {
                        this.email = email
                        this.password = password
                    }
                } else {
                    // Обработка ситуации, когда нет сохраненных данных
                    Log.e("AddNewUserInTable", "No user data found for sign-in.")
                    return
                }
            }
            val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return

            Constants.supabase.from("users")
            .update(
                {
                    set("name", users.name)
                    set("address", users.address)
                    set("about_me", users.about_me)
                    set("img_user", users.img_user)
                    set("id_genderFK", users.id_genderFK)
                }
            ) {
                filter {
                    Users::id_uuid eq idUser
                }
            }
            navController.navigate("profile")
            Log.e("updateUser", "Без ошибок добавление")
        } catch (e: Exception) {
            Log.e("getPlaceById", "Error : ${e.message}")
        }

    }

}








