@file:OptIn(SupabaseExperimental::class)

package com.example.iplace.main.viewModel

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.Favourites
import com.example.iplace.model.FavouritesInsert
import com.example.iplace.model.Gender
import com.example.iplace.model.Place
import com.example.iplace.model.PlaceInsert
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.launch

class MainViewModel(): ViewModel() {
    private val _emailPassword = mutableStateOf(EmailPassword())
    val emailPassword: State<EmailPassword> = _emailPassword //перерменные для хранения логина и пароля пользователя который авторизовался в системе
    val InfoText = mutableStateOf("") //текст который выводится как информирующий для каких либо сообщений о статусе работы

    //авторизация
    fun AutorisationFun(emailUser: String, passwordUser1: String, navController: NavHostController) {
        _emailPassword.value = EmailPassword(email = emailUser, password = passwordUser1) //при авторизации запоминаем логин и id пользователя
        if(emailUser != "" && passwordUser1 != "" ) {
            viewModelScope.launch {
                try {
                    Constants.supabase.auth.signInWith(Email) {
                        email = emailUser
                        password = passwordUser1
                    }

                    println("Success")
                    navController.navigate("menuV")
                    InfoText.value = "Успешно"
                } catch (e: Exception) {
                    println(e.message.toString())
                    InfoText.value = "Неверный логин или пароль"
                }
            }
        }
        else{
            Log.i("AutorisationFun", "Не все поля заполнены") //текст о ошибке в логкэт
            InfoText.value = "Не все поля заполнены" //текст о ошибке странице
        }

    }
    //регистрация
    fun RegistrationFun(emailUser: String, passwordUser1: String, passwordUser2: String, navController: NavHostController) {
        _emailPassword.value = EmailPassword(email = emailUser, password = passwordUser1) //запоминаем логин и пароль

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

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

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


                            println("Success")
                            InfoText.value = "Успешно"
                            navController.navigate("creatingUser")
                        }
                        catch (e: Exception) {

                            println(e.message.toString())
                            InfoText.value = "Логин не существует"
                        }

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

    }
    //изменение пароля пользователя
    fun UpdatePasswordFun(passwordUser1: String, passwordUser2: String, navController: NavHostController) {
        if(passwordUser1 != "" && passwordUser2 != ""){
            if(passwordUser1  == passwordUser2){
                if(passwordUser1.length >= 8){
                    viewModelScope.launch {
                        try {

                            val email = emailPassword.value.email // Получаем email и password из emailPassword
                            val password = emailPassword.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", "Нет сохраненных данных")
                                    InfoText.value = "Не успешно"
                                    return@launch
                                }
                            }

                            val emailUser = Constants.supabase.auth.currentUserOrNull()?.email ?: return@launch //находим логин пользователя

                            Constants.supabase.auth.resetPasswordForEmail(email = emailUser)
                            Constants.supabase.auth.updateUser {
                                this.password = passwordUser1 //обновляем пароль
                            }
                            Log.d("UpdatePasswordFun", "Success changed password")
                            InfoText.value = "Успешно"
                            navController.navigate("profile")

                        } catch (e: Exception) {
                            Log.d("UpdatePasswordFun", e.message!!)
                            InfoText.value = "Не успешно"
                        }
                    }
                }
                else{
                    Log.i("UpdatePasswordFun", "Длина пароля должна быть от 8 до 64 символов")
                    InfoText.value = "Длина пароля должна быть от 8 до 64 символов"
                }
            }
            else{
                Log.i("UpdatePasswordFun", "Пароли не совадают")
                InfoText.value = "Пароли не совадают"
            }
        }
        else{
            Log.i("UpdatePasswordFun", "Заполните все поля")
            InfoText.value = "Заполните все поля"
        }

    }
    //создание пользователя в таблицу Users public
    fun AddUserFun(nameUser: String, address: String, about_me: String, id_genderFK: String, img_user: String, navController: NavHostController){
        viewModelScope.launch {
            try {
                // Получаем email и password из authData
                val email = emailPassword.value.email
                val password = emailPassword.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("AddUserFun", "Нет сохраненных данных")
                        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")
                InfoText.value = "Успешно"
            } catch (e: Exception) {
                Log.e("AddUserFun", "Error adding user: ${e.message}")
                InfoText.value = "Не успешно"
            }
        }
    }

    //переменные для получения значений из таблицы категорий в бд
    private val _categoryList = mutableStateOf<List<Category>>(emptyList())
    init {
        viewModelScope.launch {
            _categoryList.value = getCategoryList()
        }
    }
    //получить лист категорий из бд
    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)

    //получить место котрое соответсвует определенному id
    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: PlaceInsert, navController: NavHostController){

        try {
            Log.e("insertPlace", "Зашел")
            Constants.supabase.from("place")
            .insert(place)

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

    //получить лист избранного из бд
    suspend fun getFavouritesList() = Constants.supabase.from("favourites")
        .select()
        .decodeList<Favourites>()

    //добавить запись в избронное для пользователя
    suspend fun  insertFavourites(idPlace: Int){
        viewModelScope.launch {
            try {
                // Получаем email и password из authData
                val email = emailPassword.value.email
                val password = emailPassword.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", "Нет сохраненных данных")
                        return@launch
                    }
                }

                val idUser = Constants.supabase.auth.currentUserOrNull()?.id ?: return@launch
                val newFavourites = FavouritesInsert(id_placeFK = idPlace, id_userFK = idUser)

                Constants.supabase.from("favourites")
                    .upsert(newFavourites)
                Log.e("insertFavourites", "Без ошибок добавление")
                InfoText.value = "Успешно"
            } catch (e: Exception) {
                Log.e("insertFavourites", "Error adding user: ${e.message}")
                InfoText.value = "Не успешно"
            }
        }

    }

//удаление места
    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", "Без ошибок добавление")
            InfoText.value = "Успешно"
        } catch (e: Exception) {
            Log.e("upsertPlace", "Error : ${e.message}")
            InfoText.value = "Не успешно"
        }
    }

    //обновление места
    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
                }
            }
    }

//получение данных о пользователе который авторизировался в системе по его uuid
    private val _user = mutableStateOf<Users?>(null)
    val user: State<Users?> = _user
    suspend fun getUserById() {
        try {
            // Получаем email и password из authData
            val email = emailPassword.value.email
            val password = emailPassword.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
            InfoText.value = "Успешно"

        } catch (e: Exception) {
            InfoText.value = "Не успешно"
            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 = emailPassword.value.email
            val password = emailPassword.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", "Нет сохраненных данных")
                    return
                }
            }
            //удаляем пользователя из БД по его uuid
            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", "Без ошибок удаление")
            InfoText.value = "Успешно"
        } catch (e: Exception) {
            Log.e("getPlaceById", "Error : ${e.message}")
            InfoText.value = "Не успешно"
        }
    }


    //обновляем данные о пользователе
    suspend fun  updateUser(users: Users, navController: NavHostController){
        try {
            // Получаем email и password из authData
            val email = emailPassword.value.email
            val password = emailPassword.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", "Без ошибок добавление")
            InfoText.value = "Успешно"
        } catch (e: Exception) {
            InfoText.value = "Не успешно"
            Log.e("getPlaceById", "Error : ${e.message}")
        }

    }



}








