<template>
  <div v-if="!error && stats" class="live-stats">
    <div class="stats-grid" :class="{ 'has-floor': showFloorPrice }">
      <div class="stat-item">
        <div class="stat-label">ETH Reserve</div>
        <div class="stat-value">{{ ethReserveAmount }}</div>
        <div v-if="growthIndicator !== null" class="growth-badge" :class="growthClass">{{ growthIndicator }}</div>
      </div>
      <div class="stat-item">
        <div class="stat-label">Holders</div>
        <div class="stat-value">{{ holders }}</div>
      </div>
      <div class="stat-item" :class="{ 'pulse': isRecentRebalance }">
        <div class="stat-label">Last Rebalance</div>
        <div class="stat-value">{{ lastRebalance }}</div>
      </div>
      <div class="stat-item">
        <div class="stat-label">Fees Earned (7d)</div>
        <div class="stat-value">{{ feesEarned }}</div>
      </div>
      <div class="stat-item">
        <div class="stat-label">Total Supply</div>
        <div class="stat-value">{{ totalSupply }}</div>
      </div>
      <div v-if="showFloorPrice" class="stat-item">
        <div class="stat-label">Floor Price</div>
        <div class="stat-value">{{ floorPriceAmount }}</div>
        <div v-if="floorDistanceText" class="floor-distance">{{ floorDistanceText }}</div>
      </div>
    </div>
  </div>
  <div v-else-if="!error && !stats" class="live-stats">
    <div class="stats-grid">
      <div class="stat-item skeleton" v-for="i in 5" :key="i">
        <div class="stat-label skeleton-text"></div>
        <div class="stat-value skeleton-text"></div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue';

interface Stats {
  kraikenTotalSupply: string;
  holderCount: number;
  lastRecenterTimestamp: number;
  recentersLastWeek: number;
  lastEthReserve: string;
  taxPaidLastWeek: string;
  // New fields (batch1) — all nullable until indexer has sufficient history
  ethReserveGrowthBps: number | null;
  feesEarned7dEth: string | null;
  floorPriceWei: string | null;
  floorDistanceBps: number | null;
  currentPriceWei: string | null;
}

const stats = ref<Stats | null>(null);
const error = ref(false);
let refreshInterval: number | null = null;

// Helper: safely convert a Wei BigInt string to ETH float
function weiToEth(wei: string | null | undefined): number {
  if (!wei || wei === '0') return 0;
  try {
    return Number(BigInt(wei)) / 1e18;
  } catch {
    return 0;
  }
}

const ethReserveAmount = computed(() => {
  if (!stats.value) return '0.00 ETH';
  const eth = weiToEth(stats.value.lastEthReserve);
  return `${eth.toFixed(2)} ETH`;
});

// Growth indicator: null = hide (< 7 days history or missing)
const growthIndicator = computed((): string | null => {
  if (!stats.value || stats.value.ethReserveGrowthBps == null) return null;
  const bps = Number(stats.value.ethReserveGrowthBps);
  const pct = Math.abs(bps / 100);
  if (bps > 10) return `↑ ${pct.toFixed(1)}%`;
  if (bps < -10) return `↓ ${pct.toFixed(1)}%`;
  return `~ ${pct.toFixed(1)}%`;
});

const growthClass = computed(() => {
  if (!stats.value || stats.value.ethReserveGrowthBps == null) return '';
  const bps = Number(stats.value.ethReserveGrowthBps);
  if (bps > 10) return 'growth-up';
  if (bps < -10) return 'growth-down';
  return 'growth-flat';
});

const holders = computed(() => {
  if (!stats.value) return '0 holders';
  return `${stats.value.holderCount} holders`;
});

const lastRebalance = computed(() => {
  if (!stats.value) return 'Never';
  const now = Math.floor(Date.now() / 1000);
  const diff = now - stats.value.lastRecenterTimestamp;

  if (diff < 60) return 'Just now';
  if (diff < 3600) return `${Math.floor(diff / 60)} min ago`;
  if (diff < 86400) return `${Math.floor(diff / 3600)} hours ago`;
  return `${Math.floor(diff / 86400)} days ago`;
});

const isRecentRebalance = computed(() => {
  if (!stats.value) return false;
  const now = Math.floor(Date.now() / 1000);
  return (now - stats.value.lastRecenterTimestamp) < 3600;
});

// Fees earned: feesEarned7dEth may not be available yet (fee tracking deferred in batch1)
const feesEarned = computed(() => {
  if (!stats.value) return '0.00 ETH';
  const eth = weiToEth(stats.value.feesEarned7dEth);
  return `${eth.toFixed(2)} ETH`;
});

const totalSupply = computed(() => {
  if (!stats.value) return '0K KRK';
  const supply = Number(stats.value.kraikenTotalSupply) / 1e18;
  if (supply >= 1000000) {
    return `${(supply / 1000000).toFixed(1)}M KRK`;
  }
  return `${(supply / 1000).toFixed(1)}K KRK`;
});

// Floor price: only show when data is available
const showFloorPrice = computed(() => {
  return !!(stats.value?.floorPriceWei && stats.value.floorPriceWei !== '0');
});

const floorPriceAmount = computed(() => {
  if (!showFloorPrice.value || !stats.value?.floorPriceWei) return null;
  const eth = weiToEth(stats.value.floorPriceWei);
  return `${eth.toFixed(4)} ETH`;
});

const floorDistanceText = computed((): string | null => {
  if (!stats.value || stats.value.floorDistanceBps == null) return null;
  const distPct = Number(stats.value.floorDistanceBps) / 100;
  const aboveBelow = distPct >= 0 ? 'above' : 'below';
  return `(${Math.abs(distPct).toFixed(0)}% ${aboveBelow})`;
});

async function fetchStats() {
  try {
    const endpoint = `${window.location.origin}/api/graphql`;
    const response = await fetch(endpoint, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        query: `
          query ProtocolStats {
            statss(where: { id: "0x01" }) {
              items {
                kraikenTotalSupply
                holderCount
                lastRecenterTimestamp
                recentersLastWeek
                lastEthReserve
                taxPaidLastWeek
                ethReserveGrowthBps
                feesEarned7dEth
                floorPriceWei
                floorDistanceBps
                currentPriceWei
              }
            }
          }
        `,
      }),
    });

    if (!response.ok) {
      throw new Error('Failed to fetch stats');
    }

    const data = await response.json();

    if (data.data?.statss?.items?.[0]) {
      const s = data.data.statss.items[0];
      // If ETH reserve is 0 from Ponder (EthScarcity/EthAbundance events never emitted),
      // read WETH balance of the Uniswap V3 pool directly via RPC
      if (s.lastEthReserve === '0' || !s.lastEthReserve) {
        try {
          const rpc = `${window.location.origin}/api/rpc`;
          const deployResp = await fetch(`${window.location.origin}/app/deployments-local.json`);
          if (deployResp.ok) {
            const deployments = await deployResp.json();
            const krkAddr = deployments.contracts?.Kraiken;
            if (krkAddr) {
              const wethAddr = '0x4200000000000000000000000000000000000006';
              const factoryAddr = '0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24';
              const fee = 10000; // 1% fee tier

              // Step 1: factory.getPool(weth, kraiken, fee) → pool address
              // selector: 0x1698ee82
              const wethPad = wethAddr.slice(2).padStart(64, '0');
              const krkPad = krkAddr.slice(2).padStart(64, '0');
              const feePad = fee.toString(16).padStart(64, '0');
              const poolRes = await fetch(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'eth_call',
                  params: [{ to: factoryAddr, data: '0x1698ee82' + wethPad + krkPad + feePad }, 'latest'] }) });
              const poolJson = await poolRes.json();
              const poolAddr = '0x' + (poolJson.result || '').slice(26);

              if (poolAddr.length === 42 && poolAddr !== '0x' + '0'.repeat(40)) {
                // Step 2: weth.balanceOf(pool) → ETH reserve in pool
                const poolPad = poolAddr.slice(2).padStart(64, '0');
                const balRes = await fetch(rpc, { method: 'POST', headers: { 'Content-Type': 'application/json' },
                  body: JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'eth_call',
                    params: [{ to: wethAddr, data: '0x70a08231' + poolPad }, 'latest'] }) });
                const balJson = await balRes.json();
                const wethBal = BigInt(balJson.result || '0x0');
                if (wethBal > 0n) {
                  s.lastEthReserve = wethBal.toString();
                }
              }
            }
          }
        } catch { /* ignore RPC fallback errors */ }
      }
      stats.value = s;
      error.value = false;
    } else {
      throw new Error('No stats data');
    }
  } catch (err) {
    // eslint-disable-next-line no-console
    console.error('Failed to fetch protocol stats:', err);
    error.value = true;
  }
}

onMounted(() => {
  fetchStats();
  refreshInterval = window.setInterval(fetchStats, 30000); // Refresh every 30 seconds
});

onUnmounted(() => {
  if (refreshInterval) {
    clearInterval(refreshInterval);
  }
});
</script>

<style scoped lang="sass">
.live-stats
  width: 100%
  padding: 40px 0
  margin-top: 60px

.stats-grid
  display: grid
  grid-template-columns: 1fr
  gap: 24px
  max-width: 840px
  margin: 0 auto
  padding: 0 32px

  &.has-floor
    max-width: 1020px

  @media (min-width: 640px)
    grid-template-columns: repeat(2, 1fr)

  @media (min-width: 992px)
    grid-template-columns: repeat(5, 1fr)
    gap: 32px

    &.has-floor
      grid-template-columns: repeat(6, 1fr)

.stat-item
  display: flex
  flex-direction: column
  align-items: center
  gap: 6px
  padding: 20px
  background: rgba(255, 255, 255, 0.03)
  border: 1px solid rgba(255, 255, 255, 0.08)
  border-radius: 12px
  transition: all 0.3s ease

  &:hover
    background: rgba(255, 255, 255, 0.05)
    border-color: rgba(255, 255, 255, 0.12)

.stat-label
  font-size: 12px
  color: rgba(240, 240, 240, 0.6)
  text-transform: uppercase
  letter-spacing: 0.5px
  font-weight: 500

.stat-value
  font-size: 20px
  color: #F0F0F0
  font-weight: 600
  font-family: 'orbitron', sans-serif

  @media (min-width: 992px)
    font-size: 24px

.growth-badge
  font-size: 11px
  font-weight: 600
  letter-spacing: 0.5px

  &.growth-up
    color: #4ade80

  &.growth-down
    color: #f87171

  &.growth-flat
    color: rgba(240, 240, 240, 0.45)

.floor-distance
  font-size: 11px
  color: rgba(240, 240, 240, 0.5)
  letter-spacing: 0.3px

.pulse
  animation: pulse-glow 2s ease-in-out infinite

@keyframes pulse-glow
  0%, 100%
    background: rgba(117, 80, 174, 0.1)
    border-color: rgba(117, 80, 174, 0.3)
  50%
    background: rgba(117, 80, 174, 0.2)
    border-color: rgba(117, 80, 174, 0.5)

.skeleton
  pointer-events: none

  .skeleton-text
    background: linear-gradient(90deg, rgba(255, 255, 255, 0.05) 25%, rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0.05) 75%)
    background-size: 200% 100%
    animation: shimmer 1.5s infinite
    border-radius: 4px

    &.stat-label
      height: 12px
      width: 80px

    &.stat-value
      height: 24px
      width: 100px

@keyframes shimmer
  0%
    background-position: 200% 0
  100%
    background-position: -200% 0
</style>
