package com.example.triphelper.view.RouteScreens

import android.util.Log
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.triphelper.domain.Constants
import com.example.triphelper.model.Attractions
import com.example.triphelper.model.City
import com.example.triphelper.model.Country
import com.example.triphelper.model.Hotels
import com.example.triphelper.model.Metro
import com.example.triphelper.model.Organization_of_tours
import com.example.triphelper.model.Restaurants
import com.example.triphelper.model.Rules
import com.example.triphelper.model.Tours
import dagger.hilt.android.lifecycle.HiltViewModel
import io.github.jan.supabase.postgrest.from
import io.github.jan.supabase.postgrest.query.Columns
import io.github.jan.supabase.postgrest.query.Order
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject


@HiltViewModel
class RouteViewModel @Inject constructor() : ViewModel() {
    private var _navigationTo = MutableStateFlow<String?>(null)
    val navigationTo = _navigationTo.asStateFlow()

    private val _ruleses: MutableStateFlow<List<Rules>> = MutableStateFlow(listOf())
    val ruleses: StateFlow<List<Rules>> = _ruleses.asStateFlow()

    private val _titleCountry: MutableStateFlow<String> = MutableStateFlow("")
    val titleCountry: Flow<String> = _titleCountry.asStateFlow()

    private var _country: MutableStateFlow<List<Country>> = MutableStateFlow(listOf())
    val country: StateFlow<List<Country>> = _country.asStateFlow()

    private var _city: MutableStateFlow<List<City>> = MutableStateFlow(listOf())
    val city: StateFlow<List<City>> = _city.asStateFlow()

    private val _idCountry = MutableStateFlow<Int?>(null)
    val idCountry: StateFlow<Int?> = _idCountry.asStateFlow()

    var wrong = mutableStateOf(false)
    var routeWrong = mutableStateOf(false)
    var routeWrongText = mutableStateOf("")

    private val _titleToure: MutableStateFlow<String> = MutableStateFlow("")
    val titleToure: Flow<String> = _titleToure.asStateFlow()

    private val _orgTour: MutableStateFlow<List<Organization_of_tours>> = MutableStateFlow(listOf())
    val orgTour: StateFlow<List<Organization_of_tours>> = _orgTour.asStateFlow()

    private var _attractions: MutableStateFlow<List<Attractions>> = MutableStateFlow(listOf())
    val attractions: StateFlow<List<Attractions>> = _attractions.asStateFlow()

    private var _hotels: MutableStateFlow<List<Hotels>> = MutableStateFlow(listOf())
    val hotels: StateFlow<List<Hotels>> = _hotels.asStateFlow()

    private var _restaurants: MutableStateFlow<List<Restaurants>> = MutableStateFlow(listOf())
    val restaurants: StateFlow<List<Restaurants>> = _restaurants.asStateFlow()

    private var _metro: MutableStateFlow<List<Metro>> = MutableStateFlow(listOf())
    val metro: StateFlow<List<Metro>> = _metro.asStateFlow()

    fun getCountry() {
        viewModelScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    val response = Constants.supabase
                        .from("country")
                        .select() {
                            order(column = "title", order = Order.ASCENDING)
                        }
                        .decodeList<Country>()
                    _country.value = response
                }
            } catch (e: Exception) {
                Log.e("getCountry", "Error retrieving country data", e)
                routeWrong.value = false
            }
        }
    }

    suspend fun getIdCountry(titleCountry: String) {
        try {
            val response = Constants.supabase
                .from("country")
                .select {
                    filter {
                        eq("title", titleCountry)
                    }
                }
                .decodeSingleOrNull<Country>()
            _idCountry.value = response?.id
            _titleCountry.value = response?.title.toString()
            if (_idCountry.value == null) {
                routeWrongText.value = "Не выбрана страна"
                wrong.value = true
            } else {
                wrong.value = false
            }
            Log.i("id", "${_idCountry.value}")
        } catch (e: Exception) {
            Log.e("getCountry", "Error retrieving country data", e)
            routeWrong.value = false
        }
    }

    fun getCity(countryTitle: String) {
        viewModelScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    getIdCountry(countryTitle)
                    if (_idCountry.value == null) {
                        wrong.value = true
                    } else {
                        val response = Constants.supabase
                            .from("city")
                            .select(
                                Columns.raw(
                                    "id, " +
                                            "country(id,title,flag), " +
                                            "title"
                                )
                            ) {
                                order(column = "title", order = Order.ASCENDING)
                                filter {
                                    _idCountry.value?.let { eq("country", it) }
                                }
                            }
                            .decodeList<City>()
                        _city.value = response
                        if (_city.value == null) {
                            wrong.value = true
                            routeWrong.value = false
                            routeWrongText.value = "Не выбранны данные"
                        } else {

                            wrong.value = false
                            routeWrong.value = true
                        }
                        Log.i("City", "${_city.value}")
                    }
                }
            } catch (e: Exception) {
                Log.e("getCountry", "Error retrieving country data", e)
                routeWrong.value = false
            }
        }
    }

    suspend fun getNameToure(numberTour: Int) {
        try {
            withContext(Dispatchers.IO) {
                val response = Constants.supabase.from("tours")
                    .select {
                        filter {
                            eq("id", numberTour)
                        }
                    }.decodeSingleOrNull<Tours>()
                _titleToure.value = response?.title.toString()
                Log.i("getCity", _titleToure.value)
            }
        } catch (e: Exception) {
            Log.e("getCity", "Error")
        }
    }


    fun GetOrgTour(numberTour: Int, titleCity:String) {
        viewModelScope.launch {
            try {
                GetMetro(titleCity)
                withContext(Dispatchers.IO) {
                    val columns = Columns.raw(
                        """
                    id,
                    tours!inner(id,title),
                    attractions!inner(id,city!inner(id,country!inner(id,title,flag),title),currency!inner(id,country!inner(id,title,flag),title),name,visiting,work_schedule,price_showing,photo,history,address,route,schedule_more,price,coordinates),
                    hotels!inner(id,city!inner(id,country!inner(id,title,flag),title),rating,quantity_of_rooms,floors,name,photo_hotel,address,basic_info,interior,photo_interior,rooms,photo_room,services,price,coordinates),
                    restaurants!inner(id,city!inner(id,country!inner(id,title,flag),title),currency!inner(id,country!inner(id,title,flag),title),name,work_schedule,phone,photo,address,basic_info,interior,recommendations,price,average_check,coordinates)
                """.trimIndent()
                    )
                    val responce = Constants.supabase.from("organization_of_tours").select(
                        columns = columns
                    ) {
                        filter {
                            eq("attractions.city.title", titleCity)
                        }
                    }.decodeList<Organization_of_tours>()
                    val new_responce = responce.filter { it.tours.id == numberTour }
                    _orgTour.value = new_responce
                    Log.i("orgTour", titleCity)
                }
            }catch (e:Exception){
                Log.e("orgTour", "Error")
            }
        }
    }
    fun GetAttractions(idAttractions: Int){
        viewModelScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    val columns = Columns.raw("""
                    id,
                    city!inner(id,country!inner(id,title,flag),title),
                    currency!inner(id,country!inner(id,title,flag),title),
                    name,
                    visiting,
                    work_schedule,
                    price_showing,
                    photo,
                    history,
                    address,
                    route,
                    schedule_more,
                    price,
                    coordinates
                """.trimIndent()
                    )
                    val responce = Constants.supabase.from("attractions").select(
                        columns = columns
                    ) {
                        filter {
                            eq("id", idAttractions)
                        }
                    }.decodeList<Attractions>()
                    _attractions.value = responce
                    Log.i("AttractDesc", "Success")
                }
            }catch (e:Exception){
                Log.e("AttractDesc", "Error")
            }
        }
    }
    fun GetHotel(idHotel: Int){
        viewModelScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    val columns = Columns.raw("""
                    id,
                    city!inner(id,country!inner(id,title,flag),title),
                    rating,
                    quantity_of_rooms,
                    floors,
                    name,
                    photo_hotel,
                    address,
                    basic_info,
                    interior,
                    photo_interior,
                    rooms,
                    photo_room,
                    services,
                    price,
                    coordinates
                """.trimIndent()
                    )
                    val responce = Constants.supabase.from("hotels").select(
                        columns = columns
                    ) {
                        filter {
                            eq("id", idHotel)
                        }
                    }.decodeList<Hotels>()
                    _hotels.value = responce
                    Log.i("HotelsDesc", "Success")
                }
            }catch (e:Exception){
                Log.e("HotelsDesc", "Error")
            }
        }
    }
    fun GetRestaurants(idRestaurants: Int){
        viewModelScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    val columns = Columns.raw("""
                    id,
                    city!inner(id,country!inner(id,title,flag),title),
                    currency!inner(id,country!inner(id,title,flag),title),
                    name,
                    work_schedule,
                    phone,
                    photo,
                    address,
                    basic_info,
                    interior,
                    recommendations,
                    price,
                    average_check,
                    coordinates
                """.trimIndent()
                    )
                    val responce = Constants.supabase.from("restaurants").select(
                        columns = columns
                    ) {
                        filter {
                            eq("id", idRestaurants)
                        }
                    }.decodeList<Restaurants>()
                    _restaurants.value = responce
                    Log.i("RestDesc", "Success")
                }
            }catch (e:Exception){
                Log.e("RestDesc", "Error")
            }
        }
    }
    fun GetMetro(titleCity: String){
        viewModelScope.launch {
            withContext(Dispatchers.IO){
                val columns = Columns.raw("""
                    id,
                    city!inner(id, country!inner(id, title, flag), title),
                    photo
                """.trimIndent())
                val responce = Constants.supabase.from("metro").select(
                    columns = columns
                ){
                    filter {
                        eq("city.title", titleCity)
                    }
                }.decodeList<Metro>()
                _metro.value = responce
                if (responce.isNullOrEmpty()) {
                    Log.i("metro", "No metro data found for $titleCity")
                } else {
                    _metro.value = responce
                    Log.i("metro", "Success")
                }
                Log.i("metro", "${_metro.value}")
            }
        }
    }
}