import { exchangeClientForAccount } from "../exchange/index.js";
import { findRowById } from "../accounts/repository.js";
import { list as listAccounts } from "../accounts/repository.js";
import { upsertAd } from "../repos/ads.js";
import { upsertOrder } from "../repos/orders.js";
import { upsertCounterparty } from "../repos/counterparties.js";
import type { Exchange } from "../exchange/types.js";

/**
 * Sync: espelha anúncios e ordens da exchange no banco. Só leitura na
 * exchange + escrita local — seguro para rodar periodicamente.
 */

export interface SyncResult {
  accountId: number;
  ads: number;
  orders: number;
  errors: string[];
}

export async function syncAdsForAccount(accountId: number): Promise<number> {
  const client = await exchangeClientForAccount(accountId);
  const ads = await client.listMyAds();
  for (const ad of ads) {
    await upsertAd(accountId, ad);
  }
  return ads.length;
}

export async function syncOrdersForAccount(accountId: number): Promise<number> {
  const row = await findRowById(accountId);
  if (!row) throw new Error(`Conta ${accountId} não encontrada.`);
  const exchange: Exchange = row.exchange;
  const client = await exchangeClientForAccount(accountId);

  const orders = await client.listOrders({ rows: 50 });
  for (const order of orders) {
    let counterpartyId: number | null = null;
    if (order.counterpartyRef) {
      const cp = await upsertCounterparty(exchange, order.counterpartyRef, order.counterpartyName);
      counterpartyId = cp.id;
    }
    await upsertOrder(accountId, order, counterpartyId);
  }
  return orders.length;
}

export async function syncAccount(accountId: number): Promise<SyncResult> {
  const result: SyncResult = { accountId, ads: 0, orders: 0, errors: [] };
  try {
    result.ads = await syncAdsForAccount(accountId);
  } catch (err) {
    result.errors.push(`ads: ${errMsg(err)}`);
  }
  try {
    result.orders = await syncOrdersForAccount(accountId);
  } catch (err) {
    result.errors.push(`orders: ${errMsg(err)}`);
  }
  return result;
}

/** Sincroniza todas as contas ativas. */
export async function syncAllActive(): Promise<SyncResult[]> {
  const accounts = await listAccounts();
  const active = accounts.filter((a) => a.active);
  const results: SyncResult[] = [];
  for (const acc of active) {
    results.push(await syncAccount(acc.id));
  }
  return results;
}

function errMsg(err: unknown): string {
  return err instanceof Error ? err.message : String(err);
}
