<script setup lang="ts">
import { computed, onMounted, onUnmounted } from "vue";
import { useStatsStore } from "../stores/stats";
import MinerCard from "../components/MinerCard.vue";
import PoolHero from "../components/PoolHero.vue";
import LotteryWidget from "../components/LotteryWidget.vue";
import ShareTicker from "../components/ShareTicker.vue";
import BlockCelebration from "../components/BlockCelebration.vue";
import Shameboard from "../components/Shameboard.vue";

const stats = useStatsStore();

onMounted(() => stats.start());
onUnmounted(() => stats.stop());

const totalThs = computed(() => stats.snapshot?.pool.combinedHashrateThs ?? 0);
const miners = computed(() => stats.snapshot?.miners ?? []);
const errorMsg = computed(() => stats.error);
const upstreamErr = computed(() => stats.snapshot?.error);

const bestWorkByMiner = computed(() => {
  const out: Record<string, number> = {};
  for (let i = 1; i < stats.history.length; i += 1) {
    const prev = stats.history[i - 1];
    const next = stats.history[i];
    if (!prev?.minerWork || !next?.minerWork || !prev.minerShares || !next.minerShares) continue;
    for (const [key, work] of Object.entries(next.minerWork)) {
      const shareDelta = (next.minerShares[key] ?? 0) - (prev.minerShares[key] ?? 0);
      const workDelta = work - (prev.minerWork[key] ?? work);
      if (shareDelta <= 0 || workDelta <= 0) continue;
      out[key] = Math.max(out[key] ?? 0, workDelta / shareDelta);
    }
  }
  return out;
});
const poolBestWork = computed(() => Math.max(0, ...Object.values(bestWorkByMiner.value)));
const boomerHeater = {
  authUsername: "fiat.heat",
  remoteHost: "wall-socket",
  nickname: "Boomer Heater",
  model: "Legacy Resistance Heater",
  location: "The Past",
  expectedHashrateThs: 0,
  watts: 2000,
  hashrateThs: 0,
  hashrateAgeS: null,
  lastShareAgeS: null,
  diffAcceptedSum: 0,
  diffAcceptedCount: 0,
  diffRejectedSum: 0,
  diffRejectedCount: 0,
  rejectPct: 0,
  vdiff: 0,
  userAgent: "CentralHeating/fiat-only",
  subscribed: false,
  status: "idle",
} as const;

function minerKey(m: { nickname: string; authUsername: string; remoteHost: string }): string {
  return m.nickname || m.authUsername || m.remoteHost;
}
</script>

<template>
  <BlockCelebration :snapshot="stats.snapshot" />

  <div v-if="errorMsg" class="banner err">
    ✗ {{ errorMsg }}
  </div>
  <div v-else-if="upstreamErr" class="banner warn">
    ⚠ datum: {{ upstreamErr.code }} — {{ upstreamErr.message }}
  </div>

  <PoolHero :snapshot="stats.snapshot" />

  <section class="best panel">
    <div>
      <div class="label">best accepted calculation observed</div>
      <strong class="glow-amber">
        {{ poolBestWork > 0 ? poolBestWork.toLocaleString(undefined, { maximumFractionDigits: 2 }) : "collecting" }}
      </strong>
    </div>
    <span class="muted">derived from accepted difficulty jumps while this browser has history</span>
  </section>

  <div class="grid-row">
    <LotteryWidget :total-ths="totalThs" />
    <ShareTicker :snapshot="stats.snapshot" />
  </div>

  <Shameboard :snapshot="stats.snapshot" :history="stats.history" />

  <div class="miners">
    <MinerCard
      v-for="m in miners"
      :key="m.authUsername || m.nickname"
      :miner="m"
      :best-work="bestWorkByMiner[minerKey(m)]"
    />
    <MinerCard
      key="boomer-heater"
      :miner="boomerHeater"
      :best-work="0"
    />
    <div v-if="!miners.length && !errorMsg" class="empty panel muted">
      waiting for the first poll · the boards are warming up
    </div>
  </div>
</template>

<style scoped>
.banner {
  padding: 10px 14px;
  margin-bottom: 16px;
  font-size: 12px;
  border: 1px solid var(--line);
}
.banner.err { border-color: var(--neon-red); color: var(--neon-red); }
.banner.warn { border-color: var(--neon-amber); color: var(--neon-amber); }
.grid-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin: 16px 0;
}
.best {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  margin-top: 16px;
}
.best strong {
  display: block;
  margin-top: 4px;
  font-size: 24px;
}
.best span {
  font-size: 11px;
  text-align: right;
}
.miners {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}
.empty {
  padding: 40px;
  text-align: center;
  font-style: italic;
}
@media (max-width: 800px) {
  .grid-row { grid-template-columns: 1fr; }
  .best {
    align-items: flex-start;
    flex-direction: column;
  }
  .best span {
    text-align: left;
  }
}
</style>
