<script lang="ts">
    import { onMount, onDestroy } from 'svelte';
    import { getSystemStats, type SystemStats } from '$lib/api/admin';

    let stats: SystemStats | null = $state(null);
    let error: string | null = $state(null);
    let timer: ReturnType<typeof setInterval> | null = null;

    async function refresh() {
        try {
            stats = await getSystemStats();
            error = null;
        } catch (e) {
            error = e instanceof Error ? e.message : 'refresh failed';
        }
    }

    onMount(() => {
        refresh();
        timer = setInterval(refresh, 5000);
    });
    onDestroy(() => {
        if (timer) clearInterval(timer);
    });

    function fmtBytes(n: number): string {
        const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
        let i = 0;
        let v = n;
        while (v >= 1024 && i < units.length - 1) {
            v /= 1024;
            i++;
        }
        return `${v.toFixed(2)} ${units[i]}`;
    }
</script>

<h1>System</h1>

{#if error}
    <p class="error" role="alert">{error}</p>
{/if}

{#if stats}
    {#if stats.alerts.length > 0}
        <section class="alerts">
            {#each stats.alerts as a (a.message)}
                <div class="alert">{a.message}</div>
            {/each}
        </section>
    {/if}

    <section class="grid">
        <article>
            <h2>Disk (storage_dir)</h2>
            {#if stats.disk}
                {@render Bar({ percent: stats.disk.percent_used })}
                <dl>
                    <dt>Total</dt>
                    <dd>{fmtBytes(stats.disk.total_bytes)}</dd>
                    <dt>Used</dt>
                    <dd>{fmtBytes(stats.disk.used_bytes)}</dd>
                    <dt>Free</dt>
                    <dd>{fmtBytes(stats.disk.free_bytes)}</dd>
                </dl>
            {:else}
                <p class="muted">n/a — non-local storage backend</p>
            {/if}
        </article>

        <article>
            <h2>Memory</h2>
            {@render Bar({ percent: stats.memory.percent_used })}
            <dl>
                <dt>Total</dt>
                <dd>{fmtBytes(stats.memory.total_bytes)}</dd>
                <dt>Used</dt>
                <dd>{fmtBytes(stats.memory.used_bytes)}</dd>
            </dl>
        </article>

        <article>
            <h2>CPU</h2>
            {@render Bar({ percent: stats.cpu.percent_used })}
        </article>
    </section>

    <p class="hint">refreshing every 5 s</p>
{:else}
    <p>Loading…</p>
{/if}

{#snippet Bar({ percent }: { percent: number })}
    <div
        class="bar"
        role="progressbar"
        aria-valuenow={percent}
        aria-valuemin="0"
        aria-valuemax="100"
        aria-label="{percent.toFixed(1)}% used"
    >
        <div
            class="fill"
            class:high={percent >= 90}
            class:mid={percent >= 70 && percent < 90}
            style:width="{Math.min(100, Math.max(0, percent))}%"
        ></div>
        <span class="label">{percent.toFixed(1)}%</span>
    </div>
{/snippet}

<style>
    h1 {
        margin: 0 0 var(--space-4) 0;
    }
    .grid {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
        gap: var(--space-3);
    }
    article {
        padding: var(--space-3);
        border: 1px solid var(--border);
        border-radius: var(--radius-md);
        background: var(--surface);
    }
    article h2 {
        margin: 0 0 var(--space-3) 0;
        font-size: var(--font-sm);
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 0.04em;
    }
    .bar {
        position: relative;
        background: var(--surface-elevated);
        border-radius: var(--radius-sm, 4px);
        height: 1.5rem;
        margin-bottom: var(--space-2);
        overflow: hidden;
    }
    .fill {
        height: 100%;
        background: #22c55e;
        transition: width 0.3s ease, background 0.3s ease;
    }
    .fill.mid {
        background: #f59e0b;
    }
    .fill.high {
        background: #dc2626;
    }
    .label {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        font-size: var(--font-sm);
        font-weight: var(--weight-semibold);
        color: var(--text);
    }
    dl {
        display: grid;
        grid-template-columns: max-content 1fr;
        gap: var(--space-1) var(--space-3);
        margin: 0;
        font-size: var(--font-sm);
    }
    dt {
        color: var(--text-muted);
    }
    dd {
        margin: 0;
        font-family: var(--font-mono, monospace);
    }
    .alerts {
        display: flex;
        flex-direction: column;
        gap: var(--space-2);
        margin-bottom: var(--space-4);
    }
    .alert {
        padding: var(--space-3);
        border-radius: var(--radius-md);
        background: var(--surface-elevated);
        border-left: 4px solid #f59e0b;
    }
    .hint {
        color: var(--text-muted);
        font-size: var(--font-sm);
        margin-top: var(--space-3);
    }
    .muted {
        color: var(--text-muted);
    }
    .error {
        color: var(--danger, #dc2626);
        padding: var(--space-2) var(--space-3);
        border: 1px solid var(--danger, #dc2626);
        border-radius: var(--radius-md);
        margin-bottom: var(--space-3);
    }
</style>
