package com.framework.mvvm.mv

import android.content.SharedPreferences
import android.util.Log
import androidx.core.content.edit
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cn.sagacloud.cadengine.OkhttpUtil
import com.framework.app.*
import com.framework.app.http.FileInfo
import com.framework.app.http.FileUploadInfo
import com.framework.app.tools.md5
import com.framework.app.tools.toBytes
import com.framework.mvvm.model.data.*
import com.framework.mvvm.model.db.entity.task.ObjectEntity
import com.framework.mvvm.model.repository.AdmRepository
import com.framework.mvvm.model.vo.AdmRequest
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File


class AdmViewModel(private val repository: AdmRepository) : ViewModel() {

    /**
     * 请求字典数据
     */
    fun requestDict(request: AdmRequest, block: (() -> Unit)? = null) {
        viewModelScope.launch {
            repository.requestDict(request)
            block?.invoke()
        }
    }

    /**
     * 请求配置信息
     */
    fun requestConfig(request: AdmRequest, block: (() -> Unit)? = null) {
        viewModelScope.launch {
            repository.requestConfig(request)
            block?.invoke()
        }
    }

    /**
     * 请求框架数据
     */
    fun requestFrame(request: AdmRequest, block: (() -> Unit)? = null) {
        viewModelScope.launch {
            repository.requestFrame(request)
            block?.invoke()
        }
    }

    /**
     * 上传建筑数据
     */
    fun uploadBuilding(block: (() -> Unit)? = null) {
        viewModelScope.launch(Dispatchers.IO) {
            val buildings = repository.getBuildings()
            for (building in buildings) {
                repository.uploadBuilding(building.projectId!!, building.id)
            }
            withContext(Dispatchers.Main) {
                block?.invoke()
            }
        }
    }

    /**
     *  下载建筑数据
     */
    fun downloadBuilding(
        sp: SharedPreferences,
        isOnlyRelation: Boolean = false,
        block: (() -> Unit)? = null
    ) {
        viewModelScope.launch(Dispatchers.IO) {
            val buildings = repository.getBuildings()
            println("downloadBuilding will download : ${buildings.size} $buildings")
            for (building in buildings) {
                repository.requestBuilding(
                    AdmRequest(
                        userId = "bdtp",
                        projectId = building.projectId!!,
                        groupCode = "BR",
                        buildingId = if(isOnlyRelation) "" else building.id,
                        uploadFlag = sp.getString(DEVICE_ID, "") ?: "",
                        bdtpDownloadTs = sp.getLong("${building.buildingId}.$BDTP_TS", 0L),
                        admDownloadTs = sp.getLong("${building.buildingId}.$ADM_TS", 0L)
                    )
                ) {
                    Log.e(
                        "downloadBuilding",
                        "bdtpDownloadTs:${it.bdtpDownloadTs}, admDownloadTs:${it.admDownloadTs}"
                    )
                    sp.edit { putLong("${it.buildingId}.$BDTP_TS", it.bdtpDownloadTs) }
                    sp.edit { putLong("${it.buildingId}.$ADM_TS", it.admDownloadTs) }
                }
            }

            // 下载地图
            val floors = repository.getFloors()
            floors.forEach {
                val json = it.infos?.asJsonObject
                val floorMap = json?.get("floorMap")?.asString ?: ""
                if (floorMap.isNotEmpty()) {
                    val map = OkhttpUtil.getGzipMap("$IP$pathDownloadMap${floorMap}")
                    it.floorMap = map
                    repository.updateObject(it)
                }
            }

            withContext(Dispatchers.Main) {
                block?.invoke()
            }
        }
    }

    /**
     * 获取建筑数量
     */
    val buildings: StateFlow<List<ObjectEntity>> = flow {
        emit(repository.getBuildings())
    }.stateIn(
        scope = viewModelScope,
        started = WhileSubscribed(5000),
        initialValue = arrayListOf()
    )

    /**
     * 获取本地数据中的建筑信息
     */
    suspend fun getBuildings(): List<ObjectEntity> {
        return repository.getBuildings()
    }

    /**
     * 获取文件上传信息
     */
    private suspend fun getFileUploadInfo(basic: FileInfo): Response<FileUploadInfo> {
        return request { repository.getFileUploadInfo(basic) }
    }

    /**
     * 上传文件
     */
    private suspend fun uploadFile(url: String, file: RequestBody): String {
        return repository.uploadFile(url, file)
    }

    /**
     * 上传文件
     */
    fun fileUpload(file: File) {
        val bytes = file.toBytes()

        val md5 = md5(bytes)

        val info = FileInfo(
            fileMd5 = md5,
            fileName = file.name,
            fileSize = bytes.size
        )

        viewModelScope.launch(Dispatchers.IO) {
            val response = getFileUploadInfo(info)
            if (response is SuccessResponse) {
                val data = response.data
                val url = data.content?.get(0)?.uploadUrl ?: ""
                if (url.isNotEmpty()) {
                    val body = bytes.toRequestBody()
                    val result = uploadFile(url, body)

                    Log.d("fileUpload", "success: $result")
                }
            } else {
                Log.d("fileUpload", "upload file has something error：$response")
            }
        }
    }
}