import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Io
import "../../../config" as Cfg

ColumnLayout {
    id: root
    spacing: 0

    readonly property var t: Cfg.Config.theme

    property string osName:       "Linux"
    property string kernelVer:    ""
    property real   cpuPct:       0
    property real   memPct:       0
    property real   memUsedGb:    0
    property real   swapPct:      0
    property real   swapUsedGb:   0
    property bool   hasSwap:      false
    property real   diskPct:      0
    property real   diskUsedGb:   0
    property string uptimeStr:    "—"
    property real   battPct:      -1
    property bool   battCharging: false
    property real   cpuTemp:      -1
    property real   gpuTemp:      -1
    property bool   netOnline:    false
    property var    _cpuPrev:     ({ total: 0, idle: 0 })

    Behavior on cpuPct     { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on memPct     { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on memUsedGb  { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on swapPct    { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on swapUsedGb { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on diskPct    { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on diskUsedGb { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on battPct    { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on cpuTemp    { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
    Behavior on gpuTemp    { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }

    Process {
        running: true
        command: ["sh", "-c",
            "grep '^PRETTY_NAME=' /etc/os-release 2>/dev/null | cut -d'\"' -f2 || echo Linux"]
        stdout: SplitParser { onRead: d => { root.osName = d.trim() } }
    }
    Process {
        running: true
        command: ["uname", "-r"]
        stdout: SplitParser { onRead: d => { root.kernelVer = d.trim() } }
    }

    Process {
        id: cpuTempProc
        property string _buf: ""
        command: ["sh", "-c",
            "t=-1; for d in /sys/class/hwmon/hwmon*; do " +
            "n=$(cat $d/name 2>/dev/null); " +
            "if echo \"$n\" | grep -qiE " +
            "'coretemp|k10temp|cpu_thermal|zenpower|acpitz|x86_pkg_temp|thinkpad|nct6775'; then " +
            "t=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " +
            "fi; done; echo $t"]
        stdout: SplitParser { onRead: d => { cpuTempProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            root.cpuTemp = parseInt(_buf)
            _buf = ""
        }
    }

    Process {
        id: gpuTempProc
        property string _buf: ""
        command: ["sh", "-c",
            "t=-1; for d in /sys/class/hwmon/hwmon*; do " +
            "n=$(cat $d/name 2>/dev/null); " +
            "if echo \"$n\" | grep -qiE 'amdgpu|radeon|nouveau'; then " +
            "t=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " +
            "fi; done; " +
            "[ \"$t\" = \"-1\" ] && " +
            "t=$(nvidia-smi --query-gpu=temperature.gpu " +
            "--format=csv,noheader 2>/dev/null | head -n 1); " +
            "echo $t"]
        stdout: SplitParser { onRead: d => { gpuTempProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            root.gpuTemp = parseInt(_buf)
            _buf = ""
        }
    }

    Process {
        id: cpuProc
        property string _buf: ""
        command: ["sh", "-c", "grep '^cpu ' /proc/stat | head -1"]
        stdout: SplitParser { onRead: d => { cpuProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            var p = _buf.trim().split(/\s+/)
            var user = +p[1], nice = +p[2], sys = +p[3]
            var idle = +p[4], iow  = +p[5], irq = +p[6], sirq = +p[7]
            var total   = user + nice + sys + idle + iow + irq + sirq
            var idleSum = idle + iow
            if (root._cpuPrev.total > 0) {
                var dt = total   - root._cpuPrev.total
                var di = idleSum - root._cpuPrev.idle
                root.cpuPct = dt > 0 ? Math.round((dt - di) / dt * 100) : 0
            }
            root._cpuPrev = { total: total, idle: idleSum }
            _buf = ""
        }
    }

    Process {
        id: memProc
        property string _buf: ""
        command: ["sh", "-c",
            "awk '/MemTotal/{t=$2}/MemAvailable/{a=$2}END" +
            "{print t*1024, (t-a)*1024, a*1024}' /proc/meminfo"]
        stdout: SplitParser { onRead: d => { memProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            var p          = _buf.trim().split(/\s+/)
            var total      = +p[0], avail = +p[2]
            var used       = total - avail
            root.memUsedGb = used / 1073741824
            root.memPct    = total > 0 ? (used / total * 100) : 0
            _buf = ""
        }
    }

    Process {
        id: swapProc
        property string _buf: ""
        command: ["sh", "-c",
            "awk '/SwapTotal/{t=$2}/SwapFree/{f=$2}END" +
            "{print t*1024, (t-f)*1024}' /proc/meminfo"]
        stdout: SplitParser { onRead: d => { swapProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            var p       = _buf.trim().split(/\s+/)
            var total   = +p[0], used = +p[1]
            root.hasSwap    = total > 0
            root.swapUsedGb = total > 0 ? used / 1073741824 : 0
            root.swapPct    = total > 0 ? (used / total * 100) : 0
            _buf = ""
        }
    }

    Process {
        id: uptimeProc
        property string _buf: ""
        command: ["sh", "-c",
            "u=$(awk '{print int($1)}' /proc/uptime); " +
            "d=$((u/86400)); h=$(((u%86400)/3600)); m=$(((u%3600)/60)); " +
            "[ $d -gt 0 ] && echo ${d}d${h}h || [ $h -gt 0 ] && echo ${h}h${m}m || echo ${m}m"]
        stdout: SplitParser { onRead: d => { uptimeProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            root.uptimeStr = _buf.trim()
            _buf = ""
        }
    }

    Process {
        id: diskProc
        property string _buf: ""
        command: ["sh", "-c", "df -B1 / | awk 'NR==2{print $3,$2}'"]
        stdout: SplitParser { onRead: d => { diskProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            var p         = _buf.trim().split(/\s+/)
            var used = +p[0], total = +p[1]
            root.diskUsedGb = used  / 1073741824
            root.diskPct    = total > 0 ? (used / total * 100) : 0
            _buf = ""
        }
    }

    Process {
        id: battProc
        property string _buf: ""
        command: ["sh", "-c",
            "p=/sys/class/power_supply/BAT0; " +
            "[ -f $p/capacity ] && echo $(cat $p/capacity) $(cat $p/status) || echo -1 Unknown"]
        stdout: SplitParser { onRead: d => { battProc._buf = d } }
        onRunningChanged: {
            if (running || !_buf) return
            var p = _buf.trim().split(/\s+/)
            root.battPct      = parseInt(p[0])
            root.battCharging = (p[1] === "Charging" || p[1] === "Full")
            _buf = ""
        }
    }

    Process {
        id: netProc
        property string _buf: ""
        command: ["sh", "-c", "ip route show default 2>/dev/null | grep -c default || echo 0"]
        stdout: SplitParser { onRead: d => { netProc._buf = d } }
        onRunningChanged: {
            if (running) return
            root.netOnline = parseInt(netProc._buf.trim()) > 0
            _buf = ""
        }
    }

    function refresh() {
        if (!cpuProc.running)    cpuProc.running    = true
        if (!memProc.running)    memProc.running    = true
        if (!swapProc.running)   swapProc.running   = true
        if (!diskProc.running)   diskProc.running   = true
        if (!uptimeProc.running) uptimeProc.running = true
        if (!battProc.running)   battProc.running   = true
        if (!netProc.running)    netProc.running    = true
        if (!cpuTempProc.running) cpuTempProc.running = true
        if (!gpuTempProc.running) gpuTempProc.running = true
    }

    Timer {
        interval: 5000
        running: true
        repeat: true
        triggeredOnStart: true
        onTriggered: root.refresh()
    }

    RowLayout {
        Layout.fillWidth: true
        spacing: 10

        Rectangle {
            width: 32; height: 32
            radius: 8
            color: Qt.alpha(root.t.sysInfoAccent, 0.12)
            border.color: Qt.alpha(root.t.sysInfoAccent, 0.22)
            border.width: 1
            Layout.alignment: Qt.AlignVCenter

            Text {
                anchors.centerIn: parent
                text: "󰌽"
                color: root.t.sysInfoAccent
                font.pixelSize: 20
                font.weight: Font.Bold
            }
        }

        ColumnLayout {
            spacing: 2
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter

            Text {
                text: root.osName
                color: root.t.sysInfoTextMain
                font.pixelSize: 13
                font.weight: Font.Bold
                elide: Text.ElideRight
                Layout.fillWidth: true
            }
            Text {
                text: root.kernelVer
                color: root.t.sysInfoTextDim
                font.pixelSize: 10
                font.weight: Font.Bold
                opacity: 0.75
                elide: Text.ElideRight
                Layout.fillWidth: true
            }
        }
    }

    Item { Layout.preferredHeight: 12 }

    Rectangle {
        Layout.fillWidth: true
        height: 1
        gradient: Gradient {
            orientation: Gradient.Horizontal
            GradientStop { position: 0.0; color: Qt.alpha(root.t.sysInfoAccent, 0.5) }
            GradientStop { position: 1.0; color: "transparent" }
        }
    }

    Item { Layout.preferredHeight: 10 }

    SysInfoRow {
        Layout.fillWidth: true
        icon:      "󰻠"
        label:     "CPU"
        value:     Math.round(root.cpuPct) + "%"
        iconColor: root.t.sysInfoCpuColor
        dimColor:  root.t.sysInfoTextDim
        textColor: root.t.sysInfoTextMain
        showBar:   true
        barPct:    root.cpuPct
        barColor:  root.t.sysInfoCpuColor
        trackColor: root.t.sysInfoTrackColor
    }

    Item { Layout.preferredHeight: 9 }

    SysInfoRow {
        Layout.fillWidth: true
        visible: root.cpuTemp >= 0
        icon:      "󰔄"
        label:     "CPU Temp"
        value:     root.cpuTemp >= 0 ? Math.round(root.cpuTemp) + "°C" : "—"
        iconColor: root.cpuTemp > 80 ? root.t.statusErr
                 : root.cpuTemp > 60 ? root.t.statusWarn
                 : root.t.sysInfoCpuTempColor
        dimColor:  root.t.sysInfoTextDim
        textColor: root.t.sysInfoTextMain
        showBar:   true
        barPct:    Math.min(100, Math.round(root.cpuTemp * 100 / 95))
        barColor:  root.cpuTemp > 80 ? root.t.statusErr
                 : root.cpuTemp > 60 ? root.t.statusWarn
                 : root.t.sysInfoCpuTempColor
        trackColor: root.t.sysInfoTrackColor
    }

    Item {
        Layout.fillWidth: true
        implicitHeight: root.gpuTemp >= 0 ? 9 : 0
        visible: root.gpuTemp >= 0
    }

    SysInfoRow {
        Layout.fillWidth: true
        visible: root.gpuTemp >= 0
        icon:      "󰾲"
        label:     "GPU Temp"
        value:     Math.round(root.gpuTemp) + "°C"
        iconColor: root.gpuTemp > 80 ? root.t.statusErr
                 : root.gpuTemp > 65 ? root.t.statusWarn
                 : root.t.sysInfoGpuColor
        dimColor:  root.t.sysInfoTextDim
        textColor: root.t.sysInfoTextMain
        showBar:   true
        barPct:    Math.min(100, Math.round(root.gpuTemp * 100 / 95))
        barColor:  root.gpuTemp > 80 ? root.t.statusErr
                 : root.gpuTemp > 65 ? root.t.statusWarn
                 : root.t.sysInfoGpuColor
        trackColor: root.t.sysInfoTrackColor
    }

    Item { Layout.preferredHeight: 9 }

    SysInfoRow {
        Layout.fillWidth: true
        icon:      "󰍛"
        label:     "Memory"
        value:     root.memUsedGb.toFixed(2) + " GB"
        iconColor: root.t.sysInfoMemColor
        dimColor:  root.t.sysInfoTextDim
        textColor: root.t.sysInfoTextMain
        showBar:   true
        barPct:    root.memPct
        barColor:  root.t.sysInfoMemColor
        trackColor: root.t.sysInfoTrackColor
    }

    Item { Layout.preferredHeight: 9 }

    SysInfoRow {
        Layout.fillWidth: true
        icon:      "󰋊"
        label:     "Disk (/)"
        value:     root.diskUsedGb.toFixed(1) + " GB"
        iconColor: root.t.sysInfoDiskColor
        dimColor:  root.t.sysInfoTextDim
        textColor: root.t.sysInfoTextMain
        showBar:   true
        barPct:    root.diskPct
        barColor:  root.t.sysInfoDiskColor
        trackColor: root.t.sysInfoTrackColor
    }

    Item {
        Layout.fillWidth: true
        implicitHeight: root.hasSwap ? swapItem.implicitHeight + 9 : 0
        visible: root.hasSwap
        clip: true

        ColumnLayout {
            id: swapItem
            anchors { top: parent.top; left: parent.left; right: parent.right }
            anchors.topMargin: 9
            spacing: 5

            SysInfoRow {
                Layout.fillWidth: true
                icon:      "󰾫"
                label:     "Swap"
                value:     root.swapUsedGb.toFixed(1) + " GB"
                iconColor: root.t.sysInfoMemColor
                dimColor:  root.t.sysInfoTextDim
                textColor: root.t.sysInfoTextMain
                showBar:   true
                barPct:    root.swapPct
                barColor:  root.t.sysInfoMemColor
                trackColor: root.t.sysInfoTrackColor
            }
        }
    }

    Item { Layout.preferredHeight: 9 }

    RowLayout {
        Layout.fillWidth: true
        spacing: 10

        Rectangle {
            width: 18; height: 18
            radius: 4
            color: Qt.alpha(root.t.sysInfoAccent, 0.15)
            Layout.alignment: Qt.AlignVCenter

            Text {
                anchors.centerIn: parent
                text: "󰅐"
                color: root.t.sysInfoAccent
                font.pixelSize: 12
                font.weight: Font.Bold
            }
        }

        Text {
            text: "Uptime"
            color: root.t.sysInfoTextDim
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter
        }

        Text {
            text: root.uptimeStr
            color: root.t.sysInfoTextMain
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.alignment: Qt.AlignVCenter
        }
    }

    Item { Layout.preferredHeight: 9 }

    RowLayout {
        Layout.fillWidth: true
        spacing: 10

        Rectangle {
            width: 18; height: 18
            radius: 4
            color: Qt.alpha(root.t.sysInfoAccent, 0.15)
            Layout.alignment: Qt.AlignVCenter

            Text {
                anchors.centerIn: parent
                text: ""
                color: root.t.sysInfoAccent
                font.pixelSize: 12
                font.weight: Font.Bold
            }
        }

        Text {
            text: "Kernel"
            color: root.t.sysInfoTextDim
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter
        }

        Text {
            text: root.kernelVer
            color: root.t.sysInfoTextMain
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.alignment: Qt.AlignVCenter
        }
    }

    Item {
        Layout.fillWidth: true
        implicitHeight: root.battPct >= 0 ? battItem.implicitHeight + 9 : 0
        visible: root.battPct >= 0
        clip: true

        ColumnLayout {
            id: battItem
            anchors { top: parent.top; left: parent.left; right: parent.right }
            anchors.topMargin: 9
            spacing: 5

            RowLayout {
                Layout.fillWidth: true
                spacing: 10

                Rectangle {
                    width: 18; height: 18
                    radius: 4
                    color: Qt.alpha(battIconColor, 0.15)
                    Layout.alignment: Qt.AlignVCenter
                    readonly property color battIconColor:
                        root.battPct <= 20 ? root.t.statusErr
                      : root.battPct <= 40 ? root.t.statusWarn
                      : root.battCharging  ? root.t.statusOk
                      : root.t.sysInfoAccent

                    Text {
                        anchors.centerIn: parent
                        text: root.battCharging ? "󰂄"
                            : root.battPct > 80  ? "󰁹"
                            : root.battPct > 60  ? "󰂀"
                            : root.battPct > 40  ? "󰁿"
                            : root.battPct > 20  ? "󰁾"
                            : "󰂃"
                        color: parent.battIconColor
                        font.pixelSize: 12
                        font.weight: Font.Bold
                    }
                }

                Text {
                    text: "Battery"
                    color: root.t.sysInfoTextDim
                    font.pixelSize: 12
                    font.weight: Font.Bold
                    Layout.fillWidth: true
                    Layout.alignment: Qt.AlignVCenter
                }

                Text {
                    text: Math.round(root.battPct) + "%"
                    color: root.t.sysInfoTextMain
                    font.pixelSize: 12
                    font.weight: Font.Bold
                    Layout.alignment: Qt.AlignVCenter
                }
            }

            Rectangle {
                Layout.fillWidth: true
                height: 3
                radius: 2
                color: root.t.sysInfoTrackColor

                readonly property color fillColor:
                    root.battPct <= 20 ? root.t.statusErr
                  : root.battPct <= 40 ? root.t.statusWarn
                  : root.battCharging  ? root.t.statusOk
                  : root.t.sysInfoAccent

                Rectangle {
                    width: parent.width * Math.max(0, Math.min(root.battPct, 100)) / 100
                    height: parent.height
                    radius: parent.radius
                    color: parent.fillColor
                    Behavior on width  { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } }
                    Behavior on color  { ColorAnimation  { duration: 400 } }
                }
            }
        }
    }

    Item { Layout.preferredHeight: 9 }

    RowLayout {
        Layout.fillWidth: true
        spacing: 10

        Rectangle {
            width: 18; height: 18
            radius: 4
            color: Qt.alpha(root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim, 0.15)
            Layout.alignment: Qt.AlignVCenter

            Text {
                anchors.centerIn: parent
                text: root.netOnline ? "󰤨" : "󰤭"
                color: root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim
                font.pixelSize: 12
                font.weight: Font.Bold
            }
        }

        Text {
            text: "Network"
            color: root.t.sysInfoTextDim
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter
        }

        Text {
            text: root.netOnline ? "Connected" : "Offline"
            color: root.netOnline ? root.t.statusOk : root.t.statusErr
            font.pixelSize: 12
            font.weight: Font.Bold
            Layout.alignment: Qt.AlignVCenter
        }
    }
}
