import { ref, computed, onMounted, onUnmounted, type Ref } from 'vue';
import axios from 'axios';
import { DEFAULT_CHAIN_ID } from '@/config';
import { resolveGraphqlEndpoint, formatGraphqlError } from '@/utils/graphqlRetry';
import { parseTokenAmount } from '@/utils/helper';
import logger from '@/utils/logger';

const GRAPHQL_TIMEOUT_MS = 15_000;
const POLL_INTERVAL_MS = 30_000;

export interface WalletPosition {
  id: string;
  share: number;
  taxRate: number;
  taxRateIndex: number;
  kraikenDeposit: string;
  taxPaid: string;
  snatched: number;
  status: string;
  creationTime: string;
  lastTaxTime: string;
  payout: string | null;
  totalSupplyInit: string;
  totalSupplyEnd: string | null;
}

export interface WalletStats {
  kraikenTotalSupply: string;
  lastEthReserve: string;
  floorPriceWei: string;
  currentPriceWei: string;
  ethReserveGrowthBps: number;
  recentersLastWeek: number;
  mintedLastWeek: string;
  burnedLastWeek: string;
  netSupplyChangeWeek: string;
  holderCount: number;
}

export function useWalletDashboard(address: Ref<string>) {
  const holderBalance = ref<string>('0');
  const holderTotalEthSpent = ref<string>('0');
  const holderTotalTokensAcquired = ref<string>('0');
  const stats = ref<WalletStats | null>(null);
  const positions = ref<WalletPosition[]>([]);
  const loading = ref(false);
  const error = ref<string | null>(null);
  let pollTimer: ReturnType<typeof setInterval> | null = null;

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

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

    let endpoint: string;
    try {
      endpoint = resolveGraphqlEndpoint(DEFAULT_CHAIN_ID);
    } catch (err) {
      error.value = err instanceof Error ? err.message : 'GraphQL endpoint not configured';
      loading.value = false;
      return;
    }

    try {
      const res = await axios.post(
        endpoint,
        {
          query: `query WalletDashboard($addr: String!) {
            holders(address: $addr) {
              address
              balance
              totalEthSpent
              totalTokensAcquired
            }
            statss(where: { id: "0x01" }) {
              items {
                kraikenTotalSupply
                lastEthReserve
                floorPriceWei
                currentPriceWei
                ethReserveGrowthBps
                recentersLastWeek
                mintedLastWeek
                burnedLastWeek
                netSupplyChangeWeek
                holderCount
              }
            }
            positionss(where: { owner: $addr }, limit: 1000) {
              items {
                id
                share
                taxRate
                taxRateIndex
                kraikenDeposit
                taxPaid
                snatched
                status
                creationTime
                lastTaxTime
                payout
                totalSupplyInit
                totalSupplyEnd
              }
            }
          }`,
          variables: { addr },
        },
        { timeout: GRAPHQL_TIMEOUT_MS }
      );

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

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

      const statsItems = res.data?.data?.statss?.items;
      stats.value = Array.isArray(statsItems) && statsItems.length > 0 ? (statsItems[0] as WalletStats) : null;

      const posItems = res.data?.data?.positionss?.items;
      positions.value = Array.isArray(posItems) ? (posItems as WalletPosition[]) : [];

      logger.info(`WalletDashboard loaded for ${addr}`);
    } catch (err) {
      error.value = formatGraphqlError(err);
      logger.info('WalletDashboard fetch error', err);
    } finally {
      loading.value = false;
    }
  }

  // Derived values
  const balanceKrk = computed(() => parseTokenAmount(holderBalance.value));

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

  const floorValue = computed(() => {
    if (!stats.value) return 0;
    const balance = balanceKrk.value;
    // floorPriceWei is price per token in wei → convert to ETH
    const floorPriceEth = parseTokenAmount(stats.value.floorPriceWei);
    return balance * floorPriceEth;
  });

  // Cost basis & P&L
  const avgCostBasis = computed(() => {
    const spent = parseTokenAmount(holderTotalEthSpent.value);
    const acquired = parseTokenAmount(holderTotalTokensAcquired.value);
    if (acquired === 0) return 0;
    return spent / acquired;
  });

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

  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;
  });

  const activePositions = computed(() => positions.value.filter(p => p.status === 'Active'));
  const closedPositions = computed(() => positions.value.filter(p => p.status === 'Closed'));

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

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

  return {
    loading,
    error,
    holderBalance,
    balanceKrk,
    ethBacking,
    floorValue,
    avgCostBasis,
    currentPriceEth,
    unrealizedPnlEth,
    unrealizedPnlPercent,
    stats,
    positions,
    activePositions,
    closedPositions,
    refresh: fetchData,
  };
}
