<?php

namespace App\Livewire;

use App\Livewire\Concerns\WithFleetContext;
use App\Models\AuditEvent;
use App\Models\Server;
use App\Services\FleetService;
use Illuminate\Support\Facades\Cache;
use Livewire\Attributes\Layout;
use Livewire\Component;
use Throwable;

#[Layout('layouts.app')]
class Dashboard extends Component
{
    use WithFleetContext;

    public bool $ready = false;

    /** Page <title>; localized at runtime (attributes can't call __()). */
    public function title(): string
    {
        return __('dashboard.page_title');
    }

    /** @var array<int, array> notable systemd units (lazy-loaded over SSH) */
    public array $svcRows = [];

    /** Lazy: the SSH services read runs after the shell renders (wire:init). */
    public function load(FleetService $fleet): void
    {
        $this->svcRows = $this->liveServices($fleet, $this->activeServer());
        $this->ready = true;
    }

    /** Pad a real history series to a minimum length for a stable sparkline. */
    private function pad(array $values, float|int $current, int $min = 16): array
    {
        if ($values === []) {
            $values = [$current];
        }
        while (count($values) < $min) {
            array_unshift($values, $values[0]);
        }

        return $values;
    }

    /** @param  array<int,int>  $series */
    private function trend(array $series, string $suffix = '%'): array
    {
        $cur = (int) (end($series) ?: 0);
        $prev = (int) ($series[max(0, count($series) - 8)] ?? $cur);
        $d = $cur - $prev;

        return [
            'dir' => $d > 1 ? 'up' : ($d < -1 ? 'down' : 'flat'),
            'text' => ($d >= 0 ? '+' : '').$d.$suffix,
        ];
    }

    /** A handful of notable systemd units (failed + running first), cached. */
    private function liveServices(FleetService $fleet, ?Server $active): array
    {
        if (! $active || ! $active->credential_exists) {
            return [];
        }

        try {
            $svc = Cache::remember("svc:{$active->id}", 30, fn () => $fleet->systemd($active, 1)['services']);
        } catch (Throwable) {
            return [];
        }

        $rank = fn (array $s): int => match ($s['sub']) {
            'failed' => 0,
            'running' => 1,
            default => 2,
        };
        usort($svc, fn ($a, $b) => [$rank($a), $a['name']] <=> [$rank($b), $b['name']]);

        return array_slice($svc, 0, 8);
    }

    public function render(FleetService $fleet)
    {
        $active = $this->activeServer();

        // Metrics come from the poller (DB + cache) — no SSH on web render.
        $latest = $active ? $fleet->latest($active) : null;
        $cpu = (int) ($latest['cpu'] ?? $active?->cpu ?? 0);
        $mem = (int) ($latest['mem'] ?? $active?->mem ?? 0);
        $disk = (int) ($latest['disk'] ?? $active?->disk ?? 0);
        $load = (float) ($latest['load'] ?? 0);
        $cores = (int) ($latest['cores'] ?? ($active?->specs['cores'] ?? 1)) ?: 1;

        $hist = $active ? $fleet->history($active) : ['cpu' => [], 'mem' => [], 'disk' => [], 'load' => []];
        $cpuSeries = $this->pad($hist['cpu'], $cpu);
        $memSeries = $this->pad($hist['mem'], $mem);
        $diskSeries = $this->pad($hist['disk'], $disk);
        $loadSeries = $this->pad($hist['load'], $load);

        $pctTone = fn (int $v): string => $v >= 90 ? 'offline' : ($v >= 75 ? 'warning' : 'online');
        $loadRatio = $cores > 0 ? $load / $cores : $load;

        return view('livewire.dashboard', [
            'active' => $active,
            'cpu' => $cpu,
            'mem' => $mem,
            'disk' => $disk,
            'load' => $load,
            'cpuSeries' => $cpuSeries,
            'memSeries' => $memSeries,
            'diskSeries' => $diskSeries,
            'loadSeries' => $loadSeries,
            'cpuTrend' => $this->trend($cpuSeries),
            'memTrend' => $this->trend($memSeries),
            'diskTrend' => $this->trend($diskSeries),
            'loadTrend' => $this->trend($loadSeries, ''),
            'cpuTone' => $pctTone($cpu),
            'memTone' => $pctTone($mem),
            'diskTone' => $pctTone($disk),
            'loadTone' => $loadRatio >= 1.0 ? 'offline' : ($loadRatio >= 0.7 ? 'warning' : 'online'),
            'memSub' => isset($latest['mem_total']) && $latest['mem_total'] > 0
                ? number_format((float) $latest['mem_used'], 1, ',', '.').' / '.number_format((float) $latest['mem_total'], 1, ',', '.').' GB'
                : null,
            'diskSub' => isset($latest['disk_total']) && $latest['disk_total'] > 0
                ? $latest['disk_used'].' / '.$latest['disk_total'].' GB'
                : null,
            'loadSub' => $cores.' '.($cores === 1 ? __('dashboard.core') : __('dashboard.cores')),
            'services' => $this->svcRows,
            'events' => AuditEvent::with('server')->latest()->limit(6)->get(),
        ])->title($this->title());
    }
}
