package com.example.modifier.repo

import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.provider.Settings
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.example.modifier.BuildConfig
import com.example.modifier.data.AppPreferences
import com.example.modifier.utils.getContext
import com.example.modifier.utils.shellRun
import com.example.modifier.utils.uniqueId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

val Context.appPreferencesDataStore by preferencesDataStore(name = "${BuildConfig.APPLICATION_ID}.appPreferences")

class AppPrefsRepo private constructor(private val context: Context) {

    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { AppPrefsRepo(getContext()) }
    }

    private object PreferencesKeys {
        val SERVER = stringPreferencesKey("server")
        val ID = stringPreferencesKey("id")
        val NAME = stringPreferencesKey("name")
        val PREVENT_CLEAN = booleanPreferencesKey("prevent_clean")
        val PREVENT_REQUEST = booleanPreferencesKey("prevent_request")
        val PREVENT_RESET = booleanPreferencesKey("prevent_reset")
        val STORE_NUM = intPreferencesKey("store_num")
        val ADB_PAIRED = booleanPreferencesKey("adb_paired")
    }

    val appPrefs = MutableStateFlow(
        AppPreferences(
            server = "http://47.98.225.28",
            id = uniqueId,
            name = Build.DEVICE,
            preventClean = false,
            preventRequest = false,
            preventReset = false,
            storeNum = 20,
            adbPaired = false
        )
    )

    @SuppressLint("HardwareIds")
    private val appPreferencesFlow = context.appPreferencesDataStore.data.map {
        val server = it[PreferencesKeys.SERVER] ?: "http://47.98.225.28"
        var id = it[PreferencesKeys.ID] ?: ""
        if (id.isEmpty()) {
            id = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
            context.appPreferencesDataStore.edit { preferences ->
                preferences[PreferencesKeys.ID] = id
            }
        }
        val name =
            it[PreferencesKeys.NAME] ?: context.getSharedPreferences(
                BuildConfig.APPLICATION_ID,
                Context.MODE_PRIVATE
            )
                .getString("name", Build.DEVICE)!!
        val preventClean = it[PreferencesKeys.PREVENT_CLEAN] ?: false
        val preventRequest = it[PreferencesKeys.PREVENT_REQUEST] ?: false
        val preventReset = it[PreferencesKeys.PREVENT_RESET] ?: false
        val storeNum = it[PreferencesKeys.STORE_NUM] ?: 20
        val adbPaired = it[PreferencesKeys.ADB_PAIRED] ?: false
        AppPreferences(
            server = server,
            id = id,
            name = name,
            preventClean = preventClean,
            preventRequest = preventRequest,
            preventReset = preventReset,
            storeNum = storeNum,
            adbPaired = adbPaired
        )
    }

    init {
        CoroutineScope(Dispatchers.IO).launch {
            appPreferencesFlow.collect {
                appPrefs.emit(it)
            }
        }
    }

    //    suspend fun stateFlow() = appPreferencesFlow.stateIn(CoroutineScope(coroutineContext))
    suspend fun updateId() {
        val serialNo = shellRun("getprop ro.serialno").first.trim()
        if (serialNo.isNotBlank() && serialNo != appPrefs.value.id) {
            context.appPreferencesDataStore.edit { preferences ->
                preferences[PreferencesKeys.ID] = serialNo
            }
        }
    }

    suspend fun updateId(id: String) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.ID] = id
        }
    }

    suspend fun updateServer(server: String) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.SERVER] = server
        }
    }

    suspend fun updateName(name: String) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.NAME] = name
        }
    }

    suspend fun updatePreventClean(preventClean: Boolean) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.PREVENT_CLEAN] = preventClean
        }
    }

    suspend fun updatePreventRequest(preventRequest: Boolean) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.PREVENT_REQUEST] = preventRequest
        }
    }

    suspend fun updatePreventReset(preventReset: Boolean) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.PREVENT_RESET] = preventReset
        }
    }

    suspend fun updateStoreNum(storeNum: Int) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.STORE_NUM] = storeNum
        }
    }

    suspend fun updateAdbPaired(b: Boolean) {
        context.appPreferencesDataStore.edit { preferences ->
            preferences[PreferencesKeys.ADB_PAIRED] = b
        }
    }
}