import axios from 'axios';
import { JsonRpcProvider, Contract, formatUnits } from 'ethers';
import { settlementUrl } from '../config';
import type { M2TokenCapabilities } from '@dbis/settlement-core';

const ERC20_ABI = ['function balanceOf(address) view returns (uint256)', 'function decimals() view returns (uint8)'];
export async function fetchFundLedger(officeId: number, apiKey?: string) {
  const headers: Record<string, string> = {};
  if (apiKey) headers.Authorization = `Bearer ${apiKey}`;
  const { data } = await axios.get(`${settlementUrl()}/api/v1/settlement/money-supply`, {
    headers,
    timeout: 60000,
  });
  return { officeId, fundLedger: data };
}
export async function fetchOfficeProfile() {
  const { data } = await axios.get(`${settlementUrl()}/api/v1/settlement/office`, { timeout: 15000 });
  return data;
}
export async function auditSwapToSettlement(payload: {
  idempotencyKey: string;
  amount: string;
  currency: string;
  recipientAddress: string;
  remittanceInfo: string;
  tokenLineId?: string;
  apiKey?: string;
}) {
  const lineId = payload.tokenLineId ?? `${payload.currency}-M2`;
  const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`;
  const { data } = await axios.post(
    `${settlementUrl()}/api/v1/settlement/convert/fiat-to-crypto`,
    {
      idempotencyKey: payload.idempotencyKey,
      amount: payload.amount,
      currency: payload.currency,
      creditorIban: 'GB82WEST12345698765432',
      beneficiaryName: 'DBIS Exchange settlement audit',
      remittanceInfo: payload.remittanceInfo,
      convertToCrypto: {
        enabled: true,
        targetChainId: 138,
        tokenLineId: lineId,
        recipientAddress: payload.recipientAddress,
      },
    },
    { headers, timeout: 120000, validateStatus: () => true },
  );
  return data;
}
export async function requestM2TokenLoad(payload: {
  idempotencyKey: string;
  lineId: string;
  symbol: string;
  tokenAddress: string;
  amount: string;
  recipientAddress: string;
  currency?: string;
  apiKey?: string;
}) {
  const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`;
  const { data } = await axios.post(
    `${settlementUrl()}/api/v1/settlement/token-load`,
    {
      idempotencyKey: payload.idempotencyKey,
      lineId: payload.lineId,
      symbol: payload.symbol,
      tokenAddress: payload.tokenAddress,
      amount: payload.amount,
      recipientAddress: payload.recipientAddress,
      currency: payload.currency,
    },
    { headers, timeout: 120000, validateStatus: () => true },
  );
  return data;
}
export async function requestInternalTransfer(payload: {
  idempotencyKey: string;
  tokenAddress: string;
  tokenSymbol: string;
  amount: string;
  recipientAddress: string;
  senderAddress?: string;
  apiKey?: string;
}) {
  const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`;
  const { data } = await axios.post(
    `${settlementUrl()}/api/v1/settlement/transfer/internal`,
    {
      ...payload,
      moneyLayers: ['M2'],
    },
    { headers, timeout: 120000, validateStatus: () => true },
  );
  return data;
}
export async function requestExternalTransfer(payload: {
  idempotencyKey: string;
  tokenAddress: string;
  tokenSymbol: string;
  amount: string;
  recipientAddress: string;
  creditorIban: string;
  beneficiaryName?: string;
  currency?: string;
  remittanceInfo?: string;
  apiKey?: string;
}) {
  const headers: Record<string, string> = { 'Content-Type': 'application/json' };
  if (payload.apiKey) headers.Authorization = `Bearer ${payload.apiKey}`;
  const { data } = await axios.post(
    `${settlementUrl()}/api/v1/settlement/transfer/external`,
    {
      ...payload,
      moneyLayers: ['M2'],
      rail: 'SWIFT',
    },
    { headers, timeout: 120000, validateStatus: () => true },
  );
  return data;
}
export async function fetchCryptoLedger(
  rpcUrl: string,
  wallet: string,
  tokens: { address: string; symbol: string; decimals: number; native?: boolean }[],
) {
  const provider = new JsonRpcProvider(rpcUrl);
  const balances: Record<string, string> = {};
  for (const t of tokens) {
    if (t.native || t.address === '0x0000000000000000000000000000000000000000') {
      const wei = await provider.getBalance(wallet);
      balances[t.symbol] = formatUnits(wei, 18);
      continue;
    }
    try {
      const c = new Contract(t.address, ERC20_ABI, provider);
      const raw = await c.balanceOf(wallet);
      balances[t.symbol] = formatUnits(raw, t.decimals);
    } catch {
      balances[t.symbol] = '0';
    }
  }
  return { wallet, balances };
}
export function resolveTokenLine(token: M2TokenCapabilities): string {
  return token.omnlLine;
}
