<x-filament-widgets::widget
    x-data="{
        poller: null,
        init() {
            this.poller = setInterval(() => {
                $wire.refreshData();
            }, 60000);
            $wire.refreshData();
        },
        stop() {
            if (this.poller) {
                clearInterval(this.poller);
                this.poller = null;
            }
        }
    }"
    x-on:livewire:navigating.window="stop()"
    x-on:beforeunload.window="stop()"
    wire:poll.60s="refreshData"
>
    @php
        $data = $this->getData();
        $cpu = $data['cpu'] ?? [];
        $memory = $data['memory'] ?? [];
        $disk = $data['disk'] ?? [];
        $partitions = $disk['partitions'] ?? [];
        $load = $data['load'] ?? [];
        $uptime = $data['uptime'] ?? 'N/A';
        $range = $this->range;
        $historyPoints = match ($range) {
            '5m' => 5,
            '30m' => 30,
            'day' => 24,
            'week' => 28,
            'month' => 30,
            default => 30,
        };
        $historyIntervalSeconds = match ($range) {
            '5m' => 60,
            '30m' => 60,
            'day' => 3600,
            'week' => 21600,
            'month' => 86400,
            default => 60,
        };
        $historyLabelFormat = match ($range) {
            '5m' => 'H:i',
            '30m' => 'H:i',
            'day' => 'H:00',
            'week' => 'M d H:00',
            'month' => 'M d',
            default => 'H:i',
        };

        $cpuCores = max(1, (int)($cpu['cores'] ?? 1));
        $load1 = (float)($load['1min'] ?? 0);
        $load5 = (float)($load['5min'] ?? 0);
        $load15 = (float)($load['15min'] ?? 0);
        $ioWait = (float)($cpu['iowait'] ?? 0);
        $memUsage = $memory['usage'] ?? 0;
        $history = $this->getHistory(
            $load1,
            $ioWait,
            (float) $memUsage,
            (float) ($memory['swap_usage'] ?? 0),
            $partitions,
        );
        $historyLabels = $history['labels'] ?? [];
        $historyLoad = $history['load'] ?? [];
        $historyIoWait = $history['iowait'] ?? [];
        $historyMemory = $history['memory'] ?? [];
        $historySwap = $history['swap'] ?? [];
        // Memory values are in MB from agent
        $memUsedGB = ($memory['used'] ?? 0) / 1024;
        $memTotalGB = ($memory['total'] ?? 0) / 1024;
        $swapUsedGB = ($memory['swap_used'] ?? 0) / 1024;
        $swapTotalGB = ($memory['swap_total'] ?? 0) / 1024;
        $hasSwap = $swapTotalGB > 0;

        $diskMounts = collect($partitions)
            ->map(fn (array $partition) => $partition['mount'] ?? $partition['filesystem'] ?? null)
            ->filter()
            ->unique()
            ->values()
            ->all();
        $diskTotals = [];
        $diskUsedTotal = 0;
        $diskTotal = 0;
        foreach ($partitions as $partition) {
            $mount = $partition['mount'] ?? $partition['filesystem'] ?? null;
            if ($mount === null) {
                continue;
            }
            $used = (float) ($partition['used'] ?? 0);
            $total = (float) ($partition['total'] ?? 0);
            $diskTotals[$mount] = $total > 0 ? round($total / 1024 / 1024 / 1024, 2) : 0;
            $diskUsedTotal += $used;
            $diskTotal += $total;
        }
        $diskUsedTotalGB = $diskUsedTotal > 0 ? $diskUsedTotal / 1024 / 1024 / 1024 : 0;
        $diskTotalGB = $diskTotal > 0 ? $diskTotal / 1024 / 1024 / 1024 : 0;
        $diskUsedSeries = [];
        $diskFreeSeries = [];
        foreach ($diskMounts as $mount) {
            $partition = collect($partitions)->first(fn (array $row) => ($row['mount'] ?? $row['filesystem'] ?? null) === $mount);
            $used = $partition ? ((float) ($partition['used'] ?? 0)) / 1024 / 1024 / 1024 : 0;
            $total = $partition ? ((float) ($partition['total'] ?? 0)) / 1024 / 1024 / 1024 : 0;
            $diskUsedSeries[] = round($used, 2);
            $diskFreeSeries[] = round(max(0, $total - $used), 2);
        }
    @endphp

    <style>
        .server-charts-grid {
            display: grid;
            grid-template-columns: repeat(1, minmax(0, 1fr));
            gap: 0;
        }
        @media (min-width: 640px) {
            .server-charts-grid {
                grid-template-columns: repeat(2, minmax(0, 1fr));
            }
        }
        @media (min-width: 1024px) {
            .server-charts-grid {
                grid-template-columns: repeat(3, minmax(0, 1fr));
            }
        }
        .chart-card {
            padding: 0.5rem;
        }
        .chart-container {
            height: 220px;
            width: 100%;
            position: relative;
            pointer-events: auto;
            overflow: visible;
        }
        .chart-container canvas,
        .chart-container > div {
            pointer-events: auto;
        }
        .chart-tooltip {
            position: absolute;
            top: 0;
            left: 0;
            transform: translate(-9999px, -9999px);
            opacity: 0;
            transition: opacity 120ms ease;
            background: #ffffff;
            color: #111827;
            border: 1px solid #e5e7eb;
            border-radius: 0.5rem;
            padding: 0.4rem 0.6rem;
            font-size: 0.75rem;
            line-height: 1.1rem;
            white-space: nowrap;
            pointer-events: none;
            z-index: 50;
            box-shadow: 0 8px 24px rgba(15, 23, 42, 0.15);
        }
        .dark .chart-tooltip {
            background: #111827;
            color: #e5e7eb;
            border-color: #374151;
            box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
        }
        @media (min-width: 640px) {
            .chart-container {
                height: 240px;
            }
        }
        @media (min-width: 1024px) {
            .chart-container {
                height: 260px;
            }
        }
        .chart-label {
            display: flex;
            align-items: center;
            justify-content: flex-start;
            gap: 0.5rem;
            margin-top: 0.5rem;
        }
        .chart-title {
            font-weight: 600;
            font-size: 0.875rem;
            color: rgb(17 24 39);
        }
        .dark .chart-title {
            color: white;
        }
        .chart-subtitle {
            font-size: 0.75rem;
            color: rgb(107 114 128);
            text-align: left;
            margin-top: 0.25rem;
        }
        .dark .chart-subtitle {
            color: rgb(156 163 175);
        }
    </style>

    <div class="mb-4 flex flex-wrap items-center gap-2">
        <x-filament::button
            size="sm"
            :color="$range === '5m' ? 'primary' : 'gray'"
            wire:click="setRange('5m')"
        >
            {{ __('Last 5 minutes') }}
        </x-filament::button>
        <x-filament::button
            size="sm"
            :color="$range === '30m' ? 'primary' : 'gray'"
            wire:click="setRange('30m')"
        >
            {{ __('Last 30 minutes') }}
        </x-filament::button>
        <x-filament::button
            size="sm"
            :color="$range === 'day' ? 'primary' : 'gray'"
            wire:click="setRange('day')"
        >
            {{ __('Last day') }}
        </x-filament::button>
        <x-filament::button
            size="sm"
            :color="$range === 'week' ? 'primary' : 'gray'"
            wire:click="setRange('week')"
        >
            {{ __('Last week') }}
        </x-filament::button>
        <x-filament::button
            size="sm"
            :color="$range === 'month' ? 'primary' : 'gray'"
            wire:click="setRange('month')"
        >
            {{ __('Last month') }}
        </x-filament::button>
    </div>
    @if(!empty($data['warning']))
        <div class="mb-3 text-xs text-warning-600 dark:text-warning-400">
            {{ __('Agent unavailable, showing local metrics.') }}
        </div>
    @endif

    {{-- Main Charts Grid (3 columns) --}}
    <div class="server-charts-grid">
        {{-- CPU Usage Chart --}}
        <div class="chart-card">
            <div
                x-data="{
                    chart: null,
                    labels: @js($historyLabels),
                    series: @js($historyLoad),
                    ioWaitSeries: @js($historyIoWait),
                    value: {{ $load1 }},
                    ioWaitValue: {{ $ioWait }},
                    maxValue: {{ $cpuCores }},
                    maxPoints: {{ $historyPoints }},
                    intervalSeconds: {{ $historyIntervalSeconds }},
                    labelFormat: @js($historyLabelFormat),
                    tooltipBound: false,
                    tooltipEl: null,
                    init() {
                        if (!this.labels.length || !this.series.length) {
                            this.seedSeries();
                        }
                        this.initChart();
                        Livewire.on('server-charts-range-changed', (data) => {
                            const payload = data[0] ?? data;
                            if (payload?.label_format) {
                                this.labelFormat = payload.label_format;
                            }
                            if (payload?.interval_seconds) {
                                this.intervalSeconds = payload.interval_seconds;
                            }
                            this.applyHistory(payload?.history, payload?.history_points);
                        });
                        Livewire.on('server-charts-updated', (data) => {
                            const payload = data[0] ?? data;
                            if (payload?.history) {
                                this.applyHistory(payload.history, payload.history_points);
                                return;
                            }
                            const newValue = payload?.load;
                            const ioWaitValue = payload?.iowait;
                            const label = payload?.label ?? null;
                            if (newValue !== undefined) {
                                this.pushPoint(newValue, ioWaitValue, label);
                            }
                        });
                    },
                    applyHistory(history, points) {
                        if (!history) {
                            return;
                        }
                        this.labels = history.labels ?? [];
                        this.series = history.load ?? [];
                        this.ioWaitSeries = history.iowait ?? [];
                        if (this.ioWaitSeries.length !== this.labels.length) {
                            this.ioWaitSeries = this.labels.map(() => this.ioWaitValue);
                        }
                        this.maxPoints = points ?? (this.labels.length || this.maxPoints);
                        if (history.label_format) {
                            this.labelFormat = history.label_format;
                        }
                        if (history.interval_seconds) {
                            this.intervalSeconds = history.interval_seconds;
                        }
                        this.updateChart();
                    },
                    seedSeries() {
                        const now = new Date();
                        for (let i = this.maxPoints - 1; i >= 0; i--) {
                            const stamp = new Date(now.getTime() - (i * this.intervalSeconds * 1000));
                            this.labels.push(this.formatTime(stamp));
                            this.series.push(this.value);
                            this.ioWaitSeries.push(this.ioWaitValue);
                        }
                    },
                    formatTime(date) {
                        const pad = (value) => String(value).padStart(2, '0');
                        const hours = pad(date.getHours());
                        const minutes = pad(date.getMinutes());
                        const seconds = pad(date.getSeconds());
                        const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                        const month = months[date.getMonth()];
                        const day = pad(date.getDate());

                        switch (this.labelFormat) {
                            case 'H:i:s':
                                return `${hours}:${minutes}:${seconds}`;
                            case 'H:00':
                                return `${hours}:00`;
                            case 'M d H:00':
                                return `${month} ${day} ${hours}:00`;
                            case 'M d':
                                return `${month} ${day}`;
                            default:
                                return `${hours}:${minutes}:${seconds}`;
                        }
                    },
                    pushPoint(value, ioWaitValue, label) {
                        const nextLabel = label ?? this.formatTime(new Date());
                        const nextIoWait = ioWaitValue ?? this.ioWaitValue;
                        if (this.labels.length && this.labels[this.labels.length - 1] === nextLabel) {
                            this.series[this.series.length - 1] = value;
                            this.ioWaitSeries[this.ioWaitSeries.length - 1] = nextIoWait;
                            this.updateChart();
                            return;
                        }
                        this.series.push(value);
                        this.ioWaitSeries.push(nextIoWait);
                        this.labels.push(nextLabel);
                        if (this.series.length > this.maxPoints) {
                            this.series.shift();
                            this.ioWaitSeries.shift();
                            this.labels.shift();
                        }
                        this.updateChart();
                    },
                    axisInterval() {
                        return this.labels.length > 0 ? Math.max(0, Math.floor(this.labels.length / 6)) : 0;
                    },
                    updateChart() {
                        if (!this.chart) {
                            return;
                        }
                        const ratio = this.maxValue > 0 ? (this.series[this.series.length - 1] / this.maxValue) * 100 : this.series[this.series.length - 1];
                        const color = ratio >= 90 ? '#ef4444' : (ratio >= 70 ? '#f59e0b' : '#22c55e');
                        const areaColor = ratio >= 90 ? 'rgba(239,68,68,0.15)' : (ratio >= 70 ? 'rgba(245,158,11,0.15)' : 'rgba(34,197,94,0.15)');
                        const ioWaitColor = '#38bdf8';
                        const loadPeak = this.series.length ? Math.max(...this.series) : 0;
                        const loadMax = Math.max(this.maxValue, loadPeak);
                        this.chart.setOption({
                            xAxis: { data: this.labels, axisLabel: { interval: this.axisInterval() } },
                            yAxis: [
                                { min: 0, max: loadMax },
                                { min: 0, max: 100 }
                            ],
                            series: [
                                {
                                    name: 'Load',
                                    data: this.series,
                                    yAxisIndex: 0,
                                    lineStyle: { color: color },
                                    itemStyle: { color: color },
                                    areaStyle: { color: areaColor }
                                },
                                {
                                    name: 'IO wait',
                                    data: this.ioWaitSeries,
                                    yAxisIndex: 1,
                                    lineStyle: { width: 2, type: 'dashed', color: ioWaitColor },
                                    itemStyle: { color: ioWaitColor },
                                    symbolSize: 4,
                                    showSymbol: true
                                }
                            ]
                        });
                    },
                    bindTooltip() {
                        if (this.tooltipBound) {
                            return;
                        }
                        this.tooltipBound = true;
                        this.setupTooltip();
                        const dom = this.$refs.chart;
                        const handleMove = (event) => {
                            const rect = dom.getBoundingClientRect();
                            const x = (event.clientX ?? 0) - rect.left;
                            const y = (event.clientY ?? 0) - rect.top;
                            if (Number.isNaN(x) || Number.isNaN(y)) {
                                return;
                            }
                            const width = rect.width || 1;
                            const ratio = Math.min(1, Math.max(0, x / width));
                            const index = Math.round(ratio * (this.series.length - 1));
                            this.showTooltip(index, x, y);
                        };
                        dom.addEventListener('mousemove', handleMove);
                        dom.addEventListener('mouseleave', () => this.hideTooltip());
                    },
                    setupTooltip() {
                        if (this.tooltipEl) {
                            return;
                        }
                        this.tooltipEl = document.createElement('div');
                        this.tooltipEl.className = 'chart-tooltip';
                        this.$refs.chart.appendChild(this.tooltipEl);
                    },
                    showTooltip(index, x, y) {
                        if (!this.tooltipEl || index < 0 || index >= this.labels.length) {
                            return;
                        }
                        const label = this.labels[index] ?? '';
                        const value = Number(this.series[index] ?? 0).toFixed(2);
                        const ioWaitValue = Number(this.ioWaitSeries[index] ?? 0).toFixed(1);
                        this.tooltipEl.innerHTML = `${label}<br>Load: ${value}<br>IO wait: ${ioWaitValue}%`;
                        this.tooltipEl.style.opacity = '1';
                        const rect = this.$refs.chart.getBoundingClientRect();
                        const tooltipRect = this.tooltipEl.getBoundingClientRect();
                        let left = x + 12;
                        let top = y - tooltipRect.height - 12;
                        if (left + tooltipRect.width > rect.width) {
                            left = x - tooltipRect.width - 12;
                        }
                        if (top < 0) {
                            top = y + 12;
                        }
                        this.tooltipEl.style.transform = `translate(${left}px, ${top}px)`;
                    },
                    hideTooltip() {
                        if (!this.tooltipEl) {
                            return;
                        }
                        this.tooltipEl.style.opacity = '0';
                    },
                    initChart() {
                        if (typeof window.echarts === 'undefined') {
                            setTimeout(() => this.initChart(), 100);
                            return;
                        }
                        const isDark = document.documentElement.classList.contains('dark');
                        const ratio = this.maxValue > 0 ? (this.value / this.maxValue) * 100 : this.value;
                        const color = ratio >= 90 ? '#ef4444' : (ratio >= 70 ? '#f59e0b' : '#22c55e');
                        const areaColor = ratio >= 90 ? 'rgba(239,68,68,0.15)' : (ratio >= 70 ? 'rgba(245,158,11,0.15)' : 'rgba(34,197,94,0.15)');
                        const ioWaitColor = '#38bdf8';
                        this.chart = echarts.init(this.$refs.chart);
                        this.chart.setOption({
                            grid: { left: 36, right: 36, top: 24, bottom: 28 },
                            tooltip: { show: false },
                            xAxis: {
                                type: 'category',
                                boundaryGap: false,
                                data: this.labels,
                                axisLabel: {
                                    color: isDark ? '#9ca3af' : '#6b7280',
                                    fontSize: 10,
                                    interval: this.axisInterval()
                                },
                                axisLine: { lineStyle: { color: isDark ? '#374151' : '#e5e7eb' } },
                                axisTick: { show: false }
                            },
                            yAxis: [
                                {
                                    type: 'value',
                                    min: 0,
                                    max: (value) => Math.max(this.maxValue, value.max),
                                    axisLabel: { color: isDark ? '#9ca3af' : '#6b7280', fontSize: 10 },
                                    splitLine: { lineStyle: { color: isDark ? '#374151' : '#f3f4f6' } }
                                },
                                {
                                    type: 'value',
                                    min: 0,
                                    max: 100,
                                    axisLabel: { color: isDark ? '#9ca3af' : '#6b7280', fontSize: 10, formatter: '{value}%' },
                                    splitLine: { show: false },
                                    axisLine: { lineStyle: { color: isDark ? '#374151' : '#e5e7eb' } },
                                    axisTick: { show: false }
                                }
                            ],
                            series: [
                                {
                                    name: 'Load',
                                    type: 'line',
                                    data: this.series,
                                    smooth: true,
                                    showSymbol: true,
                                    symbolSize: 4,
                                    lineStyle: { width: 2, color: color },
                                    itemStyle: { color: color },
                                    areaStyle: { color: areaColor }
                                },
                                {
                                    name: 'IO wait',
                                    type: 'line',
                                    data: this.ioWaitSeries,
                                    smooth: true,
                                    showSymbol: true,
                                    symbolSize: 4,
                                    yAxisIndex: 1,
                                    lineStyle: { width: 2, type: 'dashed', color: ioWaitColor },
                                    itemStyle: { color: ioWaitColor }
                                }
                            ]
                        });
                        this.bindTooltip();
                        window.addEventListener('resize', () => this.chart?.resize());
                    },
                    destroy() {
                        this.chart?.dispose();
                    }
                }"
                wire:ignore
            >
                <div x-ref="chart" class="chart-container"></div>
            </div>
            <div class="chart-label">
                <x-filament::icon icon="heroicon-o-chart-bar" class="h-5 w-5 text-primary-500" />
                <span class="chart-title">{{ __('Load') }}</span>
            </div>
            <div class="chart-subtitle">{{ $cpuCores }} {{ __('cores') }} · {{ __('Load') }}: {{ $load1 }} / {{ $load5 }} / {{ $load15 }}</div>
        </div>

        {{-- Memory Usage Chart --}}
        <div class="chart-card">
            <div
                x-data="{
                    chart: null,
                    labels: @js($historyLabels),
                    series: @js($historyMemory),
                    swapSeries: @js($historySwap),
                    value: {{ $memUsage }},
                    swapValue: {{ $memory['swap_usage'] ?? 0 }},
                    hasSwap: {{ $hasSwap ? 'true' : 'false' }},
                    maxValue: 100,
                    maxPoints: {{ $historyPoints }},
                    intervalSeconds: {{ $historyIntervalSeconds }},
                    labelFormat: @js($historyLabelFormat),
                    tooltipBound: false,
                    init() {
                        if (!this.labels.length || !this.series.length) {
                            this.seedSeries();
                        }
                        this.initChart();
                        Livewire.on('server-charts-range-changed', (data) => {
                            const payload = data[0] ?? data;
                            if (payload?.label_format) {
                                this.labelFormat = payload.label_format;
                            }
                            if (payload?.interval_seconds) {
                                this.intervalSeconds = payload.interval_seconds;
                            }
                            this.applyHistory(payload?.history, payload?.history_points);
                        });
                        Livewire.on('server-charts-updated', (data) => {
                            const payload = data[0] ?? data;
                            if (payload?.history) {
                                this.applyHistory(payload.history, payload.history_points);
                                return;
                            }
                            const newValue = payload?.memory;
                            const swapValue = payload?.swap;
                            const label = payload?.label ?? null;
                            if (newValue !== undefined) {
                                this.pushPoint(newValue, swapValue, label);
                            }
                        });
                    },
                    applyHistory(history, points) {
                        if (!history) {
                            return;
                        }
                        this.labels = history.labels ?? [];
                        this.series = history.memory ?? [];
                        this.swapSeries = history.swap ?? [];
                        if (this.hasSwap && this.swapSeries.length !== this.labels.length) {
                            this.swapSeries = this.labels.map(() => 0);
                        }
                        this.maxPoints = points ?? (this.labels.length || this.maxPoints);
                        this.updateChart();
                    },
                    seedSeries() {
                        const now = new Date();
                        for (let i = this.maxPoints - 1; i >= 0; i--) {
                            const stamp = new Date(now.getTime() - (i * this.intervalSeconds * 1000));
                            this.labels.push(this.formatTime(stamp));
                            this.series.push(this.value);
                            if (this.hasSwap) {
                                this.swapSeries.push(this.swapValue);
                            }
                        }
                    },
                    formatTime(date) {
                        const pad = (value) => String(value).padStart(2, '0');
                        const hours = pad(date.getHours());
                        const minutes = pad(date.getMinutes());
                        const seconds = pad(date.getSeconds());
                        const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                        const month = months[date.getMonth()];
                        const day = pad(date.getDate());

                        switch (this.labelFormat) {
                            case 'H:i:s':
                                return `${hours}:${minutes}:${seconds}`;
                            case 'H:00':
                                return `${hours}:00`;
                            case 'M d H:00':
                                return `${month} ${day} ${hours}:00`;
                            case 'M d':
                                return `${month} ${day}`;
                            default:
                                return `${hours}:${minutes}:${seconds}`;
                        }
                    },
                    pushPoint(value, swapValue, label) {
                        const nextLabel = label ?? this.formatTime(new Date());
                        const nextSwap = swapValue ?? this.swapValue ?? 0;
                        if (this.labels.length && this.labels[this.labels.length - 1] === nextLabel) {
                            this.series[this.series.length - 1] = value;
                            if (this.hasSwap) {
                                this.swapSeries[this.swapSeries.length - 1] = nextSwap;
                            }
                            this.updateChart();
                            return;
                        }
                        this.series.push(value);
                        this.labels.push(nextLabel);
                        if (this.hasSwap) {
                            this.swapSeries.push(nextSwap);
                        }
                        if (this.series.length > this.maxPoints) {
                            this.series.shift();
                            this.labels.shift();
                            if (this.hasSwap) {
                                this.swapSeries.shift();
                            }
                        }
                        this.updateChart();
                    },
                    axisInterval() {
                        return this.labels.length > 0 ? Math.max(0, Math.floor(this.labels.length / 6)) : 0;
                    },
                    updateChart() {
                        if (!this.chart) {
                            return;
                        }
                        const value = this.series[this.series.length - 1];
                        const color = value >= 90 ? '#ef4444' : (value >= 70 ? '#f59e0b' : '#22c55e');
                        const areaColor = value >= 90 ? 'rgba(239,68,68,0.15)' : (value >= 70 ? 'rgba(245,158,11,0.15)' : 'rgba(34,197,94,0.15)');
                        const seriesOptions = [{
                            name: 'Memory',
                            data: this.series,
                            lineStyle: { color: color },
                            itemStyle: { color: color },
                            areaStyle: { color: areaColor }
                        }];
                        if (this.hasSwap) {
                            seriesOptions.push({
                                name: 'Swap',
                                data: this.swapSeries,
                                lineStyle: { color: '#3b82f6', type: 'dashed' },
                                itemStyle: { color: '#3b82f6' },
                                areaStyle: { color: 'rgba(59,130,246,0.12)' }
                            });
                        }
                        this.chart.setOption({
                            xAxis: { data: this.labels, axisLabel: { interval: this.axisInterval() } },
                            series: seriesOptions
                        });
                    },
                    bindTooltip() {
                        if (this.tooltipBound) {
                            return;
                        }
                        this.tooltipBound = true;
                        this.setupTooltip();
                        const dom = this.$refs.chart;
                        const handleMove = (event) => {
                            const rect = dom.getBoundingClientRect();
                            const x = (event.clientX ?? 0) - rect.left;
                            const y = (event.clientY ?? 0) - rect.top;
                            if (Number.isNaN(x) || Number.isNaN(y)) {
                                return;
                            }
                            const width = rect.width || 1;
                            const ratio = Math.min(1, Math.max(0, x / width));
                            const index = Math.round(ratio * (this.series.length - 1));
                            this.showTooltip(index, x, y);
                        };
                        dom.addEventListener('mousemove', handleMove);
                        dom.addEventListener('mouseleave', () => this.hideTooltip());
                    },
                    setupTooltip() {
                        if (this.tooltipEl) {
                            return;
                        }
                        this.tooltipEl = document.createElement('div');
                        this.tooltipEl.className = 'chart-tooltip';
                        this.$refs.chart.appendChild(this.tooltipEl);
                    },
                    showTooltip(index, x, y) {
                        if (!this.tooltipEl || index < 0 || index >= this.labels.length) {
                            return;
                        }
                        const label = this.labels[index] ?? '';
                        const memoryValue = Number(this.series[index] ?? 0).toFixed(1);
                        let lines = `${label}<br>Memory: ${memoryValue}%`;
                        if (this.hasSwap) {
                            const swapValue = Number(this.swapSeries[index] ?? 0).toFixed(1);
                            lines += `<br>Swap: ${swapValue}%`;
                        }
                        this.tooltipEl.innerHTML = lines;
                        this.tooltipEl.style.opacity = '1';
                        const rect = this.$refs.chart.getBoundingClientRect();
                        const tooltipRect = this.tooltipEl.getBoundingClientRect();
                        let left = x + 12;
                        let top = y - tooltipRect.height - 12;
                        if (left + tooltipRect.width > rect.width) {
                            left = x - tooltipRect.width - 12;
                        }
                        if (top < 0) {
                            top = y + 12;
                        }
                        this.tooltipEl.style.transform = `translate(${left}px, ${top}px)`;
                    },
                    hideTooltip() {
                        if (!this.tooltipEl) {
                            return;
                        }
                        this.tooltipEl.style.opacity = '0';
                    },
                    initChart() {
                        if (typeof window.echarts === 'undefined') {
                            setTimeout(() => this.initChart(), 100);
                            return;
                        }
                        const isDark = document.documentElement.classList.contains('dark');
                        const color = this.value >= 90 ? '#ef4444' : (this.value >= 70 ? '#f59e0b' : '#22c55e');
                        const areaColor = this.value >= 90 ? 'rgba(239,68,68,0.15)' : (this.value >= 70 ? 'rgba(245,158,11,0.15)' : 'rgba(34,197,94,0.15)');
                        const seriesOptions = [{
                            name: 'Memory',
                            type: 'line',
                            data: this.series,
                            smooth: true,
                            showSymbol: true,
                            symbolSize: 4,
                            lineStyle: { width: 2, color: color },
                            itemStyle: { color: color },
                            areaStyle: { color: areaColor }
                        }];
                        if (this.hasSwap) {
                            seriesOptions.push({
                                name: 'Swap',
                                type: 'line',
                                data: this.swapSeries,
                                smooth: true,
                                showSymbol: true,
                                symbolSize: 4,
                                lineStyle: { width: 2, color: '#3b82f6', type: 'dashed' },
                                itemStyle: { color: '#3b82f6' },
                                areaStyle: { color: 'rgba(59,130,246,0.12)' }
                            });
                        }
                        this.chart = echarts.init(this.$refs.chart);
                        this.chart.setOption({
                            grid: { left: 36, right: 16, top: 24, bottom: 28 },
                            tooltip: { show: false },
                            xAxis: {
                                type: 'category',
                                boundaryGap: false,
                                data: this.labels,
                                axisLabel: {
                                    color: isDark ? '#9ca3af' : '#6b7280',
                                    fontSize: 10,
                                    interval: this.axisInterval()
                                },
                                axisLine: { lineStyle: { color: isDark ? '#374151' : '#e5e7eb' } },
                                axisTick: { show: false }
                            },
                            yAxis: {
                                type: 'value',
                                min: 0,
                                max: 100,
                                axisLabel: { color: isDark ? '#9ca3af' : '#6b7280', fontSize: 10 },
                                splitLine: { lineStyle: { color: isDark ? '#374151' : '#f3f4f6' } }
                            },
                            series: seriesOptions
                        });
                        this.bindTooltip();
                        window.addEventListener('resize', () => this.chart?.resize());
                    },
                    destroy() {
                        this.chart?.dispose();
                    }
                }"
                wire:ignore
            >
                <div x-ref="chart" class="chart-container"></div>
            </div>
            <div class="chart-label">
                <x-filament::icon icon="heroicon-o-server" class="h-5 w-5 text-info-500" />
                <span class="chart-title">{{ __('Memory') }}</span>
            </div>
            <div class="chart-subtitle">
                {{ number_format($memUsedGB, 1) }} GB {{ __('used') }} / {{ number_format($memTotalGB, 1) }} GB {{ __('total') }}
                @if($hasSwap)
                    · {{ __('Swap') }} {{ number_format($swapUsedGB, 1) }} GB / {{ number_format($swapTotalGB, 1) }} GB
                @endif
            </div>
        </div>

        {{-- Disk Usage Chart --}}
        @if(!empty($diskMounts))
            <div class="chart-card">
                <div
                    x-data="{
                        chart: null,
                        mounts: @js($diskMounts),
                        usedSeries: @js($diskUsedSeries),
                        freeSeries: @js($diskFreeSeries),
                        totals: @js($diskTotals),
                        labels: {
                            used: @js(__('used')),
                            free: @js(__('free')),
                            total: @js(__('total')),
                        },
                        tooltipBound: false,
                        tooltipEl: null,
                        init() {
                            this.initChart();
                        },
                        withOpacity(color, opacity) {
                            const hex = color.replace('#', '');
                            const bigint = parseInt(hex, 16);
                            const r = (bigint >> 16) & 255;
                            const g = (bigint >> 8) & 255;
                            const b = bigint & 255;
                            return `rgba(${r}, ${g}, ${b}, ${opacity})`;
                        },
                        bindTooltip() {
                            if (this.tooltipBound) {
                                return;
                            }
                            this.tooltipBound = true;
                            this.setupTooltip();
                            const dom = this.$refs.chart;
                            const handleMove = (event) => {
                                const rect = dom.getBoundingClientRect();
                                const x = (event.clientX ?? 0) - rect.left;
                                const y = (event.clientY ?? 0) - rect.top;
                                if (Number.isNaN(x) || Number.isNaN(y)) {
                                    return;
                                }
                                const width = rect.width || 1;
                                const ratio = Math.min(1, Math.max(0, x / width));
                                const index = Math.round(ratio * (this.mounts.length - 1));
                                this.showTooltip(index, x, y);
                            };
                            dom.addEventListener('mousemove', handleMove);
                            dom.addEventListener('mouseleave', () => this.hideTooltip());
                        },
                        setupTooltip() {
                            if (this.tooltipEl) {
                                return;
                            }
                            this.tooltipEl = document.createElement('div');
                            this.tooltipEl.className = 'chart-tooltip';
                            this.$refs.chart.appendChild(this.tooltipEl);
                        },
                        showTooltip(index, x, y) {
                            if (!this.tooltipEl || index < 0 || index >= this.mounts.length) {
                                return;
                            }
                            const mount = this.mounts[index] ?? '';
                            const used = Number(this.usedSeries[index] ?? 0);
                            const free = Number(this.freeSeries[index] ?? 0);
                            const total = Number(this.totals[mount] ?? (used + free));
                            this.tooltipEl.innerHTML = `<strong>${mount}</strong><br>${used.toFixed(2)} GB ${this.labels.used}<br>${free.toFixed(2)} GB ${this.labels.free}<br>${total.toFixed(2)} GB ${this.labels.total}`;
                            this.tooltipEl.style.opacity = '1';
                            const rect = this.$refs.chart.getBoundingClientRect();
                            const tooltipRect = this.tooltipEl.getBoundingClientRect();
                            let left = x + 12;
                            let top = y - tooltipRect.height - 12;
                            if (left + tooltipRect.width > rect.width) {
                                left = x - tooltipRect.width - 12;
                            }
                            if (top < 0) {
                                top = y + 12;
                            }
                            this.tooltipEl.style.transform = `translate(${left}px, ${top}px)`;
                        },
                        hideTooltip() {
                            if (!this.tooltipEl) {
                                return;
                            }
                            this.tooltipEl.style.opacity = '0';
                        },
                        initChart() {
                            if (typeof window.echarts === 'undefined') {
                                setTimeout(() => this.initChart(), 100);
                                return;
                            }
                            const isDark = document.documentElement.classList.contains('dark');
                            this.chart = echarts.init(this.$refs.chart);
                            this.chart.setOption({
                                grid: { left: 48, right: 16, top: 24, bottom: 32 },
                                tooltip: { show: false },
                                xAxis: {
                                    type: 'category',
                                    boundaryGap: true,
                                    data: this.mounts,
                                    axisLabel: {
                                        color: isDark ? '#9ca3af' : '#6b7280',
                                        fontSize: 10,
                                    },
                                    axisLine: { lineStyle: { color: isDark ? '#374151' : '#e5e7eb' } },
                                    axisTick: { show: false }
                                },
                                yAxis: {
                                    type: 'value',
                                    min: 0,
                                    axisLabel: { color: isDark ? '#9ca3af' : '#6b7280', fontSize: 10, formatter: '{value} GB' },
                                    splitLine: { lineStyle: { color: isDark ? '#374151' : '#f3f4f6' } }
                                },
                                series: [
                                    {
                                        name: 'Used',
                                        type: 'bar',
                                        stack: 'disk',
                                        data: this.usedSeries,
                                        barMaxWidth: 32,
                                        itemStyle: { color: '#f59e0b' },
                                    },
                                    {
                                        name: 'Free',
                                        type: 'bar',
                                        stack: 'disk',
                                        data: this.freeSeries,
                                        barMaxWidth: 32,
                                        itemStyle: { color: this.withOpacity('#22c55e', 0.35) },
                                    }
                                ]
                            });
                            this.bindTooltip();
                            window.addEventListener('resize', () => this.chart?.resize());
                        },
                        destroy() {
                            this.chart?.dispose();
                        }
                    }"
                    wire:ignore
                >
                    <div x-ref="chart" class="chart-container"></div>
                </div>
                <div class="chart-label">
                    <x-filament::icon icon="heroicon-o-circle-stack" class="h-5 w-5 text-warning-500" />
                    <span class="chart-title">{{ __('Disk Usage') }}</span>
                </div>
                <div class="chart-subtitle">{{ number_format($diskUsedTotalGB, 1) }} GB {{ __('used') }} / {{ number_format($diskTotalGB, 1) }} GB {{ __('total') }}</div>
            </div>
        @endif
    </div>

</x-filament-widgets::widget>
