import { useCallback, useEffect, useState } from 'react';
import { exchangeApi, settlementApi, type DexToken } from '../../config/dex';
import type { MoneySupply } from '../central-bank/useCentralBank';

export type M2Token = DexToken & {
  moneyLayer?: string;
  swappable?: boolean;
  convertible?: boolean;
  transferableInternal?: boolean;
  transferableExternal?: boolean;
};

async function fetchJson<T>(url: string): Promise<T | null> {
  try {
    const res = await fetch(url);
    return res.ok ? ((await res.json()) as T) : null;
  } catch {
    return null;
  }
}

async function loadOfficeMoneySupply(): Promise<MoneySupply | null> {
  for (const path of ['/public/money-supply', '/money-supply/public', '/health/ledger']) {
    const data = await fetchJson<MoneySupply>(settlementApi(path));
    if (data) return data;
  }
  const health = await fetchJson<{ moneySupply?: MoneySupply }>(
    `${settlementApi('/health')}?ledger=1`,
  );
  return health?.moneySupply ?? null;
}

export function useOffice24() {
  const [office, setOffice] = useState<Record<string, unknown> | null>(null);
  const [tokens, setTokens] = useState<M2Token[]>([]);
  const [health, setHealth] = useState<Record<string, unknown> | null>(null);
  const [moneySupply, setMoneySupply] = useState<MoneySupply | null>(null);
  const [loading, setLoading] = useState(true);

  const refresh = useCallback(async () => {
    setLoading(true);
    try {
      const [o, t, h, ms] = await Promise.all([
        fetchJson<Record<string, unknown>>(settlementApi('/office')),
        fetchJson<{ tokens?: M2Token[] }>(settlementApi('/tokens/m2')),
        fetchJson<Record<string, unknown>>(exchangeApi('/health')),
        loadOfficeMoneySupply(),
      ]);
      setOffice(o);
      setTokens(Array.isArray(t?.tokens) ? t.tokens : []);
      setHealth(h);
      setMoneySupply(
        ms ??
          (o
            ? { fineractConnected: true, fineractLive: false, officeId: 24 }
            : null),
      );
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    refresh();
  }, [refresh]);

  return { office, tokens, health, moneySupply, loading, refresh };
}
