<script lang="ts">
  import { snap } from "../stores/snapshot.svelte";
  import { selection, clearSelection } from "../stores/selection.svelte";
  import {
    formatHashrate,
    formatDifficulty,
    formatAgo,
    detectHardware,
  } from "../format";
  import type { User, Worker, StratumClient } from "../types";

  const address = $derived(selection.user);

  const user = $derived.by<User | null>(() => {
    if (!address) return null;
    return (snap.data?.users ?? []).find((u) => u.user === address) ?? null;
  });

  const workerRows = $derived.by(() => {
    if (!address) return [];
    const workers = (snap.data?.workers ?? []).filter((w) => w.user === address);
    const clients = (snap.data?.clients ?? []).filter(
      (c: StratumClient) => c.address === address,
    );
    const clientByWorker = new Map<string, StratumClient>();
    for (const c of clients) {
      const wname = c.workername || `${c.address}.unnamed`;
      clientByWorker.set(wname, c);
    }
    const seen = new Set<string>();
    const rows: Array<{
      worker: string;
      hardware: string;
      hashrate1m: number;
      hashrate1h: number;
      diff: number;
      bestRound: number;
      bestEver: number;
      lastShare: number;
      online: boolean;
      idle: boolean;
    }> = [];
    for (const w of workers as Worker[]) {
      const c = clientByWorker.get(w.worker);
      seen.add(w.worker);
      rows.push({
        worker: w.worker,
        hardware: c ? detectHardware(c.useragent) : "offline",
        hashrate1m: (c?.dsps1 ?? w.dsps1) * 2 ** 32,
        hashrate1h: (c?.dsps60 ?? w.dsps60) * 2 ** 32,
        diff: c?.diff ?? w.mindiff,
        bestRound: c?.bestdiff ?? w.bestdiff,
        bestEver: w.bestever,
        lastShare: c?.lastshare ?? w.lastshare,
        online: !!c,
        idle: !!(c?.idle ?? w.idle),
      });
    }
    for (const c of clients) {
      const wname = c.workername || `${c.address}.unnamed`;
      if (seen.has(wname)) continue;
      rows.push({
        worker: wname,
        hardware: detectHardware(c.useragent),
        hashrate1m: c.dsps1 * 2 ** 32,
        hashrate1h: c.dsps60 * 2 ** 32,
        diff: c.diff,
        bestRound: c.bestdiff,
        bestEver: 0,
        lastShare: c.lastshare,
        online: true,
        idle: c.idle,
      });
    }
    rows.sort((a, b) => b.hashrate1h - a.hashrate1h);
    return rows;
  });

  const totals = $derived.by(() => {
    if (user) {
      return {
        hs1m: user.dsps1 * 2 ** 32,
        hs5m: user.dsps5 * 2 ** 32,
        hs1h: user.dsps60 * 2 ** 32,
        hs24h: user.dsps1440 * 2 ** 32,
        bestDiff: user.bestdiff,
        bestEver: user.bestever,
        workers: user.workers,
        lastShare: user.lastshare,
      };
    }
    let hs1m = 0, hs1h = 0;
    let bestDiff = 0, bestEver = 0, lastShare = 0;
    for (const r of workerRows) {
      hs1m += r.hashrate1m;
      hs1h += r.hashrate1h;
      if (r.bestRound > bestDiff) bestDiff = r.bestRound;
      if (r.bestEver > bestEver) bestEver = r.bestEver;
      if (r.lastShare > lastShare) lastShare = r.lastShare;
    }
    return {
      hs1m, hs5m: 0, hs1h, hs24h: 0,
      bestDiff, bestEver,
      workers: workerRows.length,
      lastShare,
    };
  });

  function onKey(ev: KeyboardEvent): void {
    if (ev.key === "Escape") clearSelection();
  }
</script>

<svelte:window onkeydown={onKey} />

<section class="page">
  <nav class="crumbs">
    <button type="button" class="back" onclick={clearSelection}>
      &larr; Back to dashboard
    </button>
  </nav>

  <header class="head">
    <div class="stat-label">User</div>
    <h2 class="addr mono">{address}</h2>
  </header>

  <section class="totals grid-4">
    <div class="card">
      <div class="stat-label">Hashrate</div>
      <div class="stat-value">{formatHashrate(totals.hs1m)}</div>
      <div class="stat-sub">
        {#if totals.hs5m > 0}5m {formatHashrate(totals.hs5m)} · {/if}
        1h {formatHashrate(totals.hs1h)}
        {#if totals.hs24h > 0} · 24h {formatHashrate(totals.hs24h)}{/if}
      </div>
    </div>
    <div class="card">
      <div class="stat-label">Best share (ever)</div>
      <div class="stat-value">{formatDifficulty(totals.bestEver || totals.bestDiff)}</div>
      <div class="stat-sub">round best {formatDifficulty(totals.bestDiff)}</div>
    </div>
    <div class="card">
      <div class="stat-label">Workers</div>
      <div class="stat-value">{totals.workers}</div>
      <div class="stat-sub">{workerRows.filter(r => r.online).length} online</div>
    </div>
    <div class="card">
      <div class="stat-label">Last share</div>
      <div class="stat-value">{formatAgo(totals.lastShare)}</div>
      <div class="stat-sub">across all this user's workers</div>
    </div>
  </section>

  <section class="card">
    <h3>Workers</h3>
    {#if workerRows.length === 0}
      <div class="empty">No worker data yet for this address.</div>
    {:else}
      <div class="table-wrap">
        <table>
          <thead>
            <tr>
              <th>Worker</th>
              <th>Hardware</th>
              <th class="num">Hashrate (1m)</th>
              <th class="num">Hashrate (1h)</th>
              <th class="num">Diff</th>
              <th class="num">Best (round)</th>
              <th class="num">Best (ever)</th>
              <th class="num">Last share</th>
            </tr>
          </thead>
          <tbody>
            {#each workerRows as r (r.worker)}
              <tr class:offline={!r.online} class:idle={r.idle}>
                <td class="mono">{r.worker}</td>
                <td>{r.hardware}</td>
                <td class="num">{formatHashrate(r.hashrate1m)}</td>
                <td class="num">{formatHashrate(r.hashrate1h)}</td>
                <td class="num">{formatDifficulty(r.diff)}</td>
                <td class="num">{formatDifficulty(r.bestRound)}</td>
                <td class="num">{formatDifficulty(r.bestEver)}</td>
                <td class="num">{formatAgo(r.lastShare)}</td>
              </tr>
            {/each}
          </tbody>
        </table>
      </div>
    {/if}
  </section>
</section>

<style>
  .page {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
  }
  .crumbs {
    margin-bottom: 0.25rem;
  }
  .back {
    font: inherit;
    color: var(--fg-dim);
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 0.4em 0.85em;
    cursor: pointer;
  }
  .back:hover {
    color: var(--fg);
    border-color: var(--accent);
    background: var(--bg-hover);
  }
  .head {
    display: flex;
    flex-direction: column;
    gap: 0.4em;
    margin-bottom: 0.25rem;
  }
  .addr {
    margin: 0;
    font-size: 1.35rem;
    font-weight: 600;
    word-break: break-all;
    line-height: 1.25;
  }
  .totals {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1rem;
  }
  @media (max-width: 900px) {
    .totals {
      grid-template-columns: repeat(2, minmax(0, 1fr));
    }
  }
  @media (max-width: 520px) {
    .totals {
      grid-template-columns: 1fr;
    }
  }
  h3 {
    margin: 0 0 1rem;
    font-size: 1.05rem;
    font-weight: 600;
  }
  .empty {
    color: var(--fg-dim);
    padding: 1rem 0;
  }
  .table-wrap {
    overflow-x: auto;
  }
  tr.offline {
    opacity: 0.5;
  }
  tr.idle td {
    color: var(--fg-dim);
  }
</style>
