package com.example.iot_controlhost.ui.compose

import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.example.iot_controlhost.base.BaseViewModel
import com.example.iot_controlhost.utils.MMKVUtil
import com.example.iot_controlhost.utils.MyUtil
import com.example.iot_controlhost.utils.global.RoomController
import com.example.iot_controlhost.utils.global.RoomSensor
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.util.Date

class PIDViewModel : BaseViewModel() {

    private val _logs = MutableStateFlow<List<String>>(emptyList())
    val logs = _logs.asStateFlow()

    var Kp by mutableStateOf(5.0)
    var Ki by mutableStateOf(0.1)
    var Kd by mutableStateOf(1.0)

    var air1State by mutableStateOf("")
    var air2State by mutableStateOf("")
    var floorTState by mutableStateOf("")

    var targetTemperature by mutableStateOf(22.0)

    var isVirtualTemp by mutableStateOf(false)
    var virtualCurTemp = 16.0

    var isVirtualFloor by mutableStateOf(false)
    var vFloorTState by mutableStateOf("关闭")


    // 采样时间间隔 单位：秒
    var dt by mutableStateOf(10.0)

    // 温度采集时间间隔
    var tp by mutableStateOf(10L)

    var currentTemperature by mutableStateOf(-1.0)

    var output by mutableStateOf(0.0)
    var isTuning by mutableStateOf(false)
    var isControl by mutableStateOf(false)

    // 积分项累加值
    var integral by mutableStateOf(0.0)

    // 上一个误差值
    var prevError by mutableStateOf(0.0)

    // 前一次温度变化斜率
    var prevSlope by mutableStateOf(0.0)

    // 前一次温度值（用于斜率计算）
    var lastTemp by mutableStateOf(0.0)

    // 自整定状态 默认空闲状态
    var tuneState = TuneState.Idle

    // 临界比例增益（Ziegler-Nichols参数）
    var ku by mutableStateOf(0.0)

    // 临界振荡周期（秒）
    var tu by mutableStateOf(0.0)

    // 自整定步骤计数器
    var stepCounter by mutableStateOf(0)

    // 最后峰值时间戳
    var lastPeakTime = System.currentTimeMillis()

    // 温度历史数据（用于振荡检测）
    val tempHistory: ArrayDeque<Double> = ArrayDeque()
    val tempList = mutableStateListOf<Double>()

    val kpList = mutableStateListOf<Double>()
    val kiList = mutableStateListOf<Double>()
    val kdList = mutableStateListOf<Double>()

    // 振荡周期记录
    val periods: MutableList<Double> = mutableListOf()

    init {
        doInIoThreadNoDialog {
            // 每10秒获取一次当前温度
            polling(tp) {
                air1State = RoomController.airConditionInfrared.state
                air2State = RoomController.airConditionInfrared2.state
                floorTState = RoomController.floor.state
                currentTemperature = if (isVirtualTemp) {
                    virtualCurTemp
                } else {
                    RoomSensor.getAverageIndoorTemperature()
                }
                if (isControl || isTuning) {
                    tempList.add(currentTemperature)
//                    tempList.add(Random(System.currentTimeMillis()).nextDouble(17.0,30.0))
                }
            }
        }
    }

    var tempLog = ""

    private fun log(msg: String) {
        if (msg == tempLog) return
        _logs.value = listOf(MyUtil.getFormatDateTime(Date()) + msg) + _logs.value
        tempLog = msg
    }

    /**
     * 开始使用PID控制
     */
    fun startControl() {
        doInIoThreadNoDialog {
            tempList.clear()
            log("开始控制")
            isControl = true
            while (isControl) {
                delay((dt * 1000).toLong()) // 等待 dt 秒
                if (isTuning) {
                    autoTuneStep()
                    kpList.add(Kp)
                    kiList.add(Ki)
                    kdList.add(Kd)
                    output = (Kp * (targetTemperature - currentTemperature)).coerceIn(0.0, 100.0)
                } else {
                    output = computePID()
                }
                // 控制逻辑
                controlLogic(output)
            }
        }
    }

    /**
     *  停止PID控制
     */
    fun stopControl() {
        doInIoThread("正在停止所有设备") {
            log("停止控制")
            isControl = false
            isTuning = false
            RoomController.closeAllControllers()
            vFloorTState = "关闭"
        }
    }

    fun computePID(): Double {
        val error = targetTemperature - currentTemperature
        val proportional = Kp * error

        if (Math.abs(error) < 5.0) {
            integral += error * dt
//            integral = integral.coerceIn(-100.0, 100.0)  // 防止积分风暴
            integral = integral.coerceIn(0.0, 100.0 / (Ki.takeIf { it != 0.0 } ?: 1.0))
        }
        val derivative = (prevError - error) / dt
        prevError = error

        return (proportional + Ki * integral + Kd * derivative).coerceIn(0.0, 100.0)
    }

    /**
     * 开始自整定
     */
    fun startAutoTune() {
        doInIoThreadNoDialog {
            tempList.clear()
            log("开始自整定 PID 控制器")
            tuneState = TuneState.StepUp
            Kp = 1.0
            Ki = 0.0
            Kd = 0.0
            integral = 0.0
            stepCounter = 0
            periods.clear()
            tempHistory.clear()
            kpList.clear()
            kiList.clear()
            kdList.clear()
            log("已重置所有参数")

            isTuning = true
        }
    }

    /**
     * 停止自整定
     */
    fun stopAutoTune() {
        doInIoThread("正在停止自整定") {
            log("停止自整定")
            isTuning = false
            tuneState = TuneState.Idle
            stepCounter = 0
            integral = 0.0
            prevError = 0.0
            log("重置部分参数")
        }
    }

    private fun controlLogic(output: Double) {
        if (output > 50) {
            log("PID:开启地暖")
            RoomController.floor.setGear(5)
        } else {
            log("PID:关闭地暖")
            RoomController.floor.setGear(0)
        }
        if (isVirtualFloor) {
            vFloorTState = if (output > 50) "开启" else "关闭"
        }
    }

    /**
     * 自整定步骤
     */
    private fun autoTuneStep() {
        when (tuneState) {
            // 比例增益提升阶段
            TuneState.StepUp -> {
                stepCounter++
                if (stepCounter % 5 == 0) {
                    Kp *= 1.2
                    log("尝试 Kp: ${Kp}")
                }
                tempHistory.addLast(currentTemperature)
                if (tempHistory.size > 10)
                    tempHistory.removeFirst()
                if (tempHistory.size == 10 && tempHistory.max() - tempHistory.min() > 0.5) {
                    log("检测到振荡，进入测量阶段")
                    ku = Kp
                    tuneState = TuneState.Measure
                    lastPeakTime = System.currentTimeMillis()
                }
                if (Kp > 50.0) {
                    log("自整定失败")
                }
            }

            // 振荡周期测量阶段
            TuneState.Measure -> {
                val now = System.currentTimeMillis()
                val temp = currentTemperature
                val slope = temp - lastTemp

                if ((temp > lastTemp && prevSlope < 0) || (temp < lastTemp && prevSlope > 0)) {
                    val period = (now - lastPeakTime) / 1000.0
                    lastPeakTime = now
                    periods.add(period)
                    log("振荡周期: $period 秒")
                    if (periods.size >= 3) {
                        tu = periods.average()
                        tuneState = TuneState.Complete
                    }
                }
                prevSlope = slope
                lastTemp = temp
            }

            // 自整定完成状态
            TuneState.Complete -> {
                Kp = 0.6 * ku
                Ki = 1.2 * ku / tu
                Kd = 0.075 * ku * tu
                log("自整定完成！Kp=${Kp}, Ki=${Ki}, Kd=${Kd}")
            }

            else -> {}
        }
    }

    fun saveParams() {
        doInIoThread {
            // 保存参数到数据库或文件
            MMKVUtil.put("pid_kp", Kp)
            MMKVUtil.put("pid_ki", Ki)
            MMKVUtil.put("pid_kd", Kd)
            log("保存 PID 参数: Kp=$Kp, Ki=$Ki, Kd=$Kd")
        }
    }

    fun loadParams() {
        doInIoThread {
            // 从数据库或文件加载参数
            Kp = MMKVUtil.get("pid_kp", 5.0)
            Ki = MMKVUtil.get("pid_ki", 0.1)
            Kd = MMKVUtil.get("pid_kd", 1.0)
            log("加载 PID 参数: Kp=$Kp, Ki=$Ki, Kd=$Kd")
        }
    }

    fun switchVirtualTemp() {
        isVirtualTemp = !isVirtualTemp
        log("虚拟温度开关：$isVirtualTemp")
    }

    fun switchVirtualFloor() {
        isVirtualFloor = !isVirtualFloor
        log("虚拟地暖开关：$isVirtualFloor")
    }

    fun addVirtualTemp() {
        doInIoThreadNoDialog {
            virtualCurTemp += 0.5
            log("虚拟温度增加0.5°C，当前温度：$virtualCurTemp，目标温度：$targetTemperature")
        }
    }

    fun reduceVirtualTemp() {
        doInIoThreadNoDialog {
            virtualCurTemp -= 0.5
            log("虚拟温度减少0.5°C，当前温度：$virtualCurTemp，目标温度：$targetTemperature")
        }
    }

    enum class TuneState {
        Idle,// 空闲状态
        StepUp,// 比例增益提升阶段
        Measure,// 振荡周期测量阶段
        Complete// 自整定完成状态
    }

}

