import { ref, computed, onMounted, onUnmounted, type Ref } from 'vue';

const POLL_INTERVAL_MS = 30_000;

function formatTokenAmount(rawWei: string, decimals = 18): number {
  try {
    const big = BigInt(rawWei);
    // Use BigInt arithmetic to avoid float64 precision loss at high values
    return Number(big * 10000n / (10n ** BigInt(decimals))) / 10000;
  } catch {
    return 0;
  }
}

export function useHolderDashboard(address: Ref<string>, graphqlUrl: string | Ref<string> = '/api/graphql') {
  const holderBalance = ref<string>('0');
  const holderTotalEthSpent = ref<string>('0');
  const holderTotalTokensAcquired = ref<string>('0');
  const currentPriceWei = ref<string | null>(null);
  const lastEthReserve = ref<string>('0');
  const kraikenTotalSupply = ref<string>('0');
  const loading = ref(false);
  const error = ref<string | null>(null);
  let pollTimer: ReturnType<typeof setInterval> | null = null;

  function resolveUrl(): string {
    return typeof graphqlUrl === 'string' ? graphqlUrl : graphqlUrl.value;
  }

  async function fetchData() {
    const addr = address.value?.toLowerCase();
    if (!addr) return;

    loading.value = true;
    error.value = null;

    try {
      const res = await fetch(resolveUrl(), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          query: `query HolderDashboard {
            holders(address: "${addr}") {
              balance
              totalEthSpent
              totalTokensAcquired
            }
            statss(where: { id: "0x01" }) {
              items {
                kraikenTotalSupply
                lastEthReserve
                currentPriceWei
              }
            }
          }`,
        }),
      });

      const json = await res.json();

      if (Array.isArray(json?.errors) && json.errors.length > 0) {
        const msgs = json.errors.map((e: { message?: string }) => e.message ?? 'GraphQL error').join(', ');
        throw new Error(msgs);
      }

      const holder = json?.data?.holders;
      holderBalance.value = holder?.balance ?? '0';
      holderTotalEthSpent.value = holder?.totalEthSpent ?? '0';
      holderTotalTokensAcquired.value = holder?.totalTokensAcquired ?? '0';

      const statsItems = json?.data?.statss?.items;
      const statsRow = Array.isArray(statsItems) && statsItems.length > 0 ? statsItems[0] : null;
      currentPriceWei.value = statsRow?.currentPriceWei ?? null;
      lastEthReserve.value = statsRow?.lastEthReserve ?? '0';
      kraikenTotalSupply.value = statsRow?.kraikenTotalSupply ?? '0';
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'Failed to load holder data';
    } finally {
      loading.value = false;
    }
  }

  const balanceKrk = computed(() => formatTokenAmount(holderBalance.value));

  const ethBacking = computed(() => {
    const balance = balanceKrk.value;
    const reserve = formatTokenAmount(lastEthReserve.value);
    const totalSupply = formatTokenAmount(kraikenTotalSupply.value);
    if (totalSupply === 0) return 0;
    return balance * (reserve / totalSupply);
  });

  const avgCostBasis = computed(() => {
    const spent = formatTokenAmount(holderTotalEthSpent.value);
    const acquired = formatTokenAmount(holderTotalTokensAcquired.value);
    if (acquired === 0) return 0;
    return spent / acquired;
  });

  const currentPriceEth = computed(() => {
    if (!currentPriceWei.value) return 0;
    return formatTokenAmount(currentPriceWei.value);
  });

  const unrealizedPnlEth = computed(() => {
    const basis = avgCostBasis.value;
    if (basis === 0) return 0;
    return (currentPriceEth.value - basis) * balanceKrk.value;
  });

  const unrealizedPnlPercent = computed(() => {
    const basis = avgCostBasis.value;
    if (basis === 0) return 0;
    return (currentPriceEth.value / basis - 1) * 100;
  });

  onMounted(async () => {
    await fetchData();
    pollTimer = setInterval(() => void fetchData(), POLL_INTERVAL_MS);
  });

  onUnmounted(() => {
    if (pollTimer) {
      clearInterval(pollTimer);
      pollTimer = null;
    }
  });

  return {
    loading,
    error,
    balanceKrk,
    avgCostBasis,
    currentPriceEth,
    unrealizedPnlEth,
    unrealizedPnlPercent,
    ethBacking,
    refresh: fetchData,
  };
}
