package com.example.modifier.ui.login

import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.provider.Settings
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.modifier.Utils
import com.example.modifier.http.request.LoginRequest
import com.example.modifier.http.response.ErrorResponse
import com.example.modifier.http.response.LoginResponse
import com.example.modifier.model.ServerConfig
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
import io.ktor.client.request.post
import io.ktor.client.request.setBody
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.contentType
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json
import javax.inject.Inject

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "serverConfig")

@HiltViewModel
class LoginViewModel @Inject constructor() : ViewModel() {
    private val TAG = "LoginViewModel"

    companion object {
        val URL = stringPreferencesKey("url")
        val USERNAME = stringPreferencesKey("username")
        val PASSWORD = stringPreferencesKey("password")
        val DEVICE_LABEL = stringPreferencesKey("device_label")
        val TOKEN = stringPreferencesKey("token")
    }

    private val _uiState = MutableStateFlow<LoginUiState>(LoginUiState.Normal)
    val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
    val serverConfig = MutableLiveData<ServerConfig>()

    @Inject
    @ApplicationContext
    lateinit var appContext: Context

    suspend fun loadConfig() {
        appContext.dataStore.data.map {
            ServerConfig(
                url = it[URL] ?: "",
                username = it[USERNAME] ?: "",
                password = it[PASSWORD] ?: "",
                deviceLabel = it[DEVICE_LABEL] ?: "",
                token = it[TOKEN] ?: ""
            )
        }.collect {
            serverConfig.postValue(it)
        };
    }

    suspend fun saveConfig() {
        appContext.dataStore.edit {
            it[URL] = serverConfig.value?.url ?: ""
            it[USERNAME] = serverConfig.value?.username ?: ""
            it[PASSWORD] = serverConfig.value?.password ?: ""
            it[DEVICE_LABEL] = serverConfig.value?.deviceLabel ?: ""
            it[TOKEN] = serverConfig.value?.token ?: ""
        }
    }

    suspend fun login() {
        Log.d(TAG, "login")
        _uiState.value = LoginUiState.Loading
        val client = HttpClient(OkHttp) {
            defaultRequest {
                url(serverConfig.value!!.url!!)
            }
            install(ContentNegotiation) {
                json(Json {
                    prettyPrint = true
                    isLenient = true
                    ignoreUnknownKeys = true
                })
            }
        }

        val response = client.post("/api/auth/login") {
            contentType(ContentType.Application.Json)
            setBody(LoginRequest(serverConfig.value!!.username!!, serverConfig.value!!.password!!))
        }
        when (response.status) {
            HttpStatusCode.OK -> {
                val loginResponse = response.body<LoginResponse>()
                Log.i(TAG, "response: $loginResponse")
            }

            else -> {
                val errorResponse = response.body<ErrorResponse>()
                Log.e(TAG, "error: $errorResponse")
            }
        }
    }

    suspend fun checkRootAccess() {

    }
}