/* global React */
// Thin client for the OTC backend with safe JSON parsing, API key + idempotency.
//
// `window.OTC_CONFIG` is delivered by the server at /api/config.js (loaded ahead of
// this file in index.html). Single-tenant prototype — protection is "outside the
// browser" (servers / bots / curl), not "between users sharing this page".

const CONFIG = (typeof window !== "undefined" && window.OTC_CONFIG) || {};

async function safeJson(res) {
  const text = await res.text();
  if (!text) return { body: null };
  try { return { body: JSON.parse(text) }; }
  catch { return { body: { ok: false, error: "Resposta inválida do servidor", raw: text.slice(0, 200) } }; }
}

function newIdempotencyKey() {
  if (typeof crypto !== "undefined" && crypto.randomUUID) return crypto.randomUUID();
  return `${Date.now()}-${Math.random().toString(16).slice(2, 12)}`;
}

async function call(path, init = {}, { idempotent = false } = {}) {
  const headers = { ...(init.headers || {}) };
  if (CONFIG.apiKey) headers["X-OTC-Key"] = CONFIG.apiKey;
  if (idempotent && !headers["Idempotency-Key"]) headers["Idempotency-Key"] = newIdempotencyKey();

  let res;
  try {
    res = await fetch(path, { ...init, headers });
  } catch (e) {
    return { ok: false, error: `Falha de rede: ${e.message || e}` };
  }
  const { body } = await safeJson(res);
  if (body && typeof body === "object" && !Array.isArray(body)) {
    if (typeof body.ok === "undefined") body.ok = res.ok;
    if (!res.ok && typeof body.error === "undefined") body.error = `HTTP ${res.status}`;
    return body;
  }
  return { ok: res.ok, status: res.status, body };
}

const API = {
  config: () => CONFIG,

  health: () => call("/api/health"),

  quotes: (symbols = ["BTC", "ETH", "USDT", "USDC"], spreadBps) => {
    const qs = new URLSearchParams({ symbols: symbols.join(",") });
    if (spreadBps != null) qs.set("spread_bps", String(spreadBps));
    return call(`/api/quotes?${qs}`);
  },

  buy: ({ assetSymbol, brlAmountCents, clientWalletId }, opts) =>
    call("/api/orders/buy", {
      method: "POST",
      headers: { "Content-Type": "application/json", ...(opts?.headers || {}) },
      body: JSON.stringify({ assetSymbol, brlAmountCents, clientWalletId }),
    }, { idempotent: true }),

  sell: ({ assetSymbol, cryptoQty, clientWalletId }, opts) =>
    call("/api/orders/sell", {
      method: "POST",
      headers: { "Content-Type": "application/json", ...(opts?.headers || {}) },
      body: JSON.stringify({ assetSymbol, cryptoQty, clientWalletId }),
    }, { idempotent: true }),

  listOrders: () => call("/api/orders"),
  getOrder: (id) => call(`/api/orders/${encodeURIComponent(id)}`),
  ledger: (walletId) => call(`/api/balances/${encodeURIComponent(walletId)}`),
  mutualBalance: (walletId) => call(`/api/mutual/balance/${encodeURIComponent(walletId)}`),
  mbAccounts: () => call("/api/mb/accounts"),
  mbBalances: () => call("/api/mb/balances"),

  depositAddress: (asset, network) => {
    const qs = new URLSearchParams({ asset });
    if (network) qs.set("network", network);
    return call(`/api/deposit-address?${qs}`);
  },

  networks: (asset) => call(`/api/networks/${encodeURIComponent(asset)}`),
  fees: (asset, network) => {
    const qs = new URLSearchParams();
    if (network) qs.set("network", network);
    return call(`/api/fees/${encodeURIComponent(asset)}${qs.size ? "?" + qs : ""}`);
  },

  withdrawCrypto: ({ asset, address, qty, network, txFee, description, destinationTag }) =>
    call("/api/withdraws/crypto", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ asset, address, qty, network, txFee, description, destinationTag }),
    }, { idempotent: true }),

  settingsSchema: () => call("/api/settings/schema"),
  settingsAll: () => call("/api/settings"),
  settingsSave: (provider, kv) =>
    call(`/api/settings/${encodeURIComponent(provider)}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(kv),
    }),
  settingsTest: (provider) =>
    call(`/api/settings/${encodeURIComponent(provider)}/test`, {
      method: "POST",
    }),

  diag: () => call("/api/diag"),
};

window.API = API;
