/**
 * Client 360 Queries
 * Client profiles, search, transaction data, merchant checkout data
 */
const { pool, fmtDate, fmtDateTime, fmtTrendRows, calcPrevPeriod } = require('./helpers');

// Top 20 clients by total USD volume (including checkout volume for merchants)
async function fetchTopClients() {
  const conn = await pool.getConnection();
  try {
    const [rows] = await conn.execute(`
      SELECT c.id_conta, c.nome,
        COALESCE(t1.vol_usd, 0) + COALESCE(t2.vol_usd, 0) + COALESCE(t3.vol_usd, 0) AS total_vol_usd,
        COALESCE(t1.cnt, 0) + COALESCE(t2.cnt, 0) + COALESCE(t3.cnt, 0) AS total_ops,
        GREATEST(COALESCE(t1.months_active, 0), COALESCE(t2.months_active, 0), COALESCE(t3.months_active, 0)) AS months_active,
        GREATEST(COALESCE(t1.last_op, '1970-01-01'), COALESCE(t2.last_op, '1970-01-01'), COALESCE(t3.last_op, '1970-01-01')) AS last_op
      FROM conta c
      LEFT JOIN (
        SELECT id_conta,
          SUM(amount_usd) AS vol_usd,
          COUNT(*) AS cnt,
          COUNT(DISTINCT DATE_FORMAT(created_at, '%Y-%m')) AS months_active,
          MAX(created_at) AS last_op
        FROM br_transaction_to_usa
        WHERE (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
        GROUP BY id_conta
      ) t1 ON t1.id_conta = c.id_conta
      LEFT JOIN (
        SELECT id_conta,
          SUM(valor / cotacao) AS vol_usd,
          COUNT(*) AS cnt,
          COUNT(DISTINCT DATE_FORMAT(created_at, '%Y-%m')) AS months_active,
          MAX(created_at) AS last_op
        FROM pagamento_br GROUP BY id_conta
      ) t2 ON t2.id_conta = c.id_conta
      LEFT JOIN (
        SELECT e.id_conta,
          SUM(t.amount_usd) AS vol_usd,
          COUNT(*) AS cnt,
          COUNT(DISTINCT DATE_FORMAT(t.created_at, '%Y-%m')) AS months_active,
          MAX(t.created_at) AS last_op
        FROM br_cb_empresas e
        INNER JOIN br_cb_cobranca cb ON cb.empresa_id = e.id
        INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
        WHERE e.active = 1
        GROUP BY e.id_conta
      ) t3 ON t3.id_conta = c.id_conta
      WHERE COALESCE(t1.cnt, 0) + COALESCE(t2.cnt, 0) + COALESCE(t3.cnt, 0) > 0
      ORDER BY total_vol_usd DESC
      LIMIT 20
    `);
    return rows.map(r => ({
      id: r.id_conta,
      nome: r.nome,
      vol: Math.round(r.total_vol_usd || 0),
      ops: r.total_ops || 0,
      months: r.months_active || 0,
      lastOp: r.last_op && String(r.last_op) !== '1970-01-01' ? (r.last_op instanceof Date ? r.last_op.toISOString().slice(0, 10) : String(r.last_op).slice(0, 10)) : null
    }));
  } finally {
    conn.release();
  }
}

// Search clients by name (server-side, max 15 results) — includes merchants
async function fetchClientSearch(query) {
  const conn = await pool.getConnection();
  try {
    const [rows] = await conn.execute(`
      SELECT c.id_conta, c.nome FROM conta c
      WHERE c.id_conta IN (
        SELECT DISTINCT id_conta FROM br_transaction_to_usa
        UNION SELECT DISTINCT id_conta FROM pagamento_br
        UNION SELECT DISTINCT id_conta FROM br_cb_empresas WHERE active = 1
      ) AND c.nome LIKE CONCAT('%', ?, '%')
      ORDER BY c.nome LIMIT 15
    `, [query]);
    return rows.map(r => ({ id: r.id_conta, nome: r.nome }));
  } finally {
    conn.release();
  }
}

// Client lifetime profile (no date filter)
async function fetchClientProfile(clienteId) {
  const conn = await pool.getConnection();
  try {
    const [conta] = await conn.execute('SELECT nome FROM conta WHERE id_conta = ?', [clienteId]);
    const nome = conta[0]?.nome || 'Cliente #' + clienteId;

    const [brl] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(amount_usd),0),2) as vol_usd,
        ROUND(COALESCE(SUM(amount_brl),0),2) as vol_brl,
        ROUND(COALESCE(SUM((exchange_rate - ptax) / exchange_rate * amount_usd),0),2) as spread_revenue,
        MIN(created_at) as first_op, MAX(created_at) as last_op
      FROM br_transaction_to_usa WHERE id_conta = ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
    `, [clienteId]);

    const [usd] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(valor),0),2) as vol_usd,
        ROUND(COALESCE(SUM(valor_sol),0),2) as vol_brl,
        ROUND(COALESCE(SUM((ptax - cotacao) / ptax * valor),0),2) as spread_revenue,
        MIN(created_at) as first_op, MAX(created_at) as last_op
      FROM pagamento_br WHERE id_conta = ?
        AND cotacao IS NOT NULL AND cotacao > 0
        AND (pgto IS NULL OR pgto != 'balance')
    `, [clienteId]);

    const brlData = brl[0] || {};
    const usdData = usd[0] || {};

    const dates = [brlData.first_op, usdData.first_op].filter(Boolean);
    const lastDates = [brlData.last_op, usdData.last_op].filter(Boolean);
    const firstOp = dates.length > 0 ? new Date(Math.min(...dates.map(d => new Date(d).getTime()))) : null;
    const lastOp = lastDates.length > 0 ? new Date(Math.max(...lastDates.map(d => new Date(d).getTime()))) : null;
    const daysInactive = lastOp ? Math.round((Date.now() - lastOp.getTime()) / 86400000) : null;

    const brlQtd = Number(brlData.qtd) || 0;
    const usdQtd = Number(usdData.qtd) || 0;
    const totalOps = brlQtd + usdQtd;
    const totalVolUsd = (Number(brlData.vol_usd) || 0) + (Number(usdData.vol_usd) || 0);
    const totalSpreadRev = (Number(brlData.spread_revenue) || 0) + (Number(usdData.spread_revenue) || 0);

    const [monthsRows] = await conn.execute(`
      SELECT COUNT(DISTINCT mes) as months_active FROM (
        SELECT DATE_FORMAT(created_at, '%Y-%m') as mes FROM br_transaction_to_usa WHERE id_conta = ?
          AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
        UNION
        SELECT DATE_FORMAT(created_at, '%Y-%m') as mes FROM pagamento_br WHERE id_conta = ?
          AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
      ) m
    `, [clienteId, clienteId]);
    const monthsActive = Number(monthsRows[0]?.months_active) || 0;

    return {
      id: clienteId,
      nome,
      first_op: firstOp ? firstOp.toISOString().slice(0, 10) : null,
      last_op: lastOp ? lastOp.toISOString().slice(0, 10) : null,
      days_inactive: daysInactive,
      total_ops: totalOps,
      total_vol_usd: totalVolUsd,
      total_vol_brl: (Number(brlData.vol_brl) || 0) + (Number(usdData.vol_brl) || 0),
      total_spread_revenue: totalSpreadRev,
      months_active: monthsActive,
      avg_monthly_vol: monthsActive > 0 ? Math.round(totalVolUsd / monthsActive) : 0,
      avg_monthly_ops: monthsActive > 0 ? Math.round(totalOps / monthsActive * 10) / 10 : 0,
      avg_monthly_revenue: monthsActive > 0 ? Math.round(totalSpreadRev / monthsActive * 100) / 100 : 0,
      ltv: totalSpreadRev,
      brlUsd: { qtd: brlQtd, vol_usd: Number(brlData.vol_usd) || 0 },
      usdBrl: { qtd: usdQtd, vol_usd: Number(usdData.vol_usd) || 0 }
    };
  } finally {
    conn.release();
  }
}

// Client data for a period — full analytics
async function fetchClientData(clienteId, dataInicio, dataFim) {
  const conn = await pool.getConnection();
  try {
    const { prevStartStr, prevEndStr } = calcPrevPeriod(dataInicio, dataFim);

    // KPIs BRL->USD
    const [kpiBrl] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(amount_usd),0),2) as vol_usd,
        ROUND(COALESCE(SUM(amount_brl),0),2) as vol_brl,
        ROUND(COALESCE(SUM((exchange_rate - ptax) / exchange_rate * amount_usd),0),2) as spread_revenue,
        ROUND(COALESCE(AVG((exchange_rate - ptax) / exchange_rate * 100),0),2) as avg_spread_pct
      FROM br_transaction_to_usa WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
    `, [clienteId, dataInicio, dataFim]);

    // KPIs USD->BRL
    const [kpiUsd] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(valor),0),2) as vol_usd,
        ROUND(COALESCE(SUM(valor_sol),0),2) as vol_brl,
        ROUND(COALESCE(SUM((ptax - cotacao) / ptax * valor),0),2) as spread_revenue,
        ROUND(COALESCE(AVG(CASE WHEN cotacao > 0 THEN (ptax - cotacao) / ptax * 100 ELSE 0 END),0),2) as avg_spread_pct
      FROM pagamento_br WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
    `, [clienteId, dataInicio, dataFim]);

    // Previous period
    const [prevBrl] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(amount_usd),0),2) as vol_usd,
        ROUND(COALESCE(SUM((exchange_rate - ptax) / exchange_rate * amount_usd),0),2) as spread_revenue
      FROM br_transaction_to_usa WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
    `, [clienteId, prevStartStr, prevEndStr]);
    const [prevUsd] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(valor),0),2) as vol_usd,
        ROUND(COALESCE(SUM((ptax - cotacao) / ptax * valor),0),2) as spread_revenue
      FROM pagamento_br WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
    `, [clienteId, prevStartStr, prevEndStr]);

    // Trend BRL->USD
    const [trendBrl] = await conn.execute(`
      SELECT DATE(created_at) as dia, COUNT(*) as qtd,
        ROUND(SUM(amount_usd),2) as vol_usd,
        ROUND(AVG((exchange_rate - ptax) / exchange_rate * 100),2) as avg_spread
      FROM br_transaction_to_usa WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY DATE(created_at) ORDER BY dia
    `, [clienteId, dataInicio, dataFim]);

    // Trend USD->BRL
    const [trendUsd] = await conn.execute(`
      SELECT DATE(created_at) as dia, COUNT(*) as qtd,
        ROUND(SUM(valor),2) as vol_usd,
        ROUND(AVG(CASE WHEN cotacao > 0 THEN (ptax - cotacao) / ptax * 100 ELSE 0 END),2) as avg_spread
      FROM pagamento_br WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
      GROUP BY DATE(created_at) ORDER BY dia
    `, [clienteId, dataInicio, dataFim]);

    // Individual transactions BRL->USD
    const [txBrl] = await conn.execute(`
      SELECT t.created_at as date, 'BRL→USD' as flow,
        t.amount_usd as usd, t.amount_brl as brl,
        ROUND(t.exchange_rate,4) as rate, ROUND(t.ptax,4) as ptax,
        ROUND((t.exchange_rate - t.ptax) / t.exchange_rate * 100, 2) as spread_pct,
        t.iof, t.status,
        COALESCE(pm.provider, '') as provider
      FROM br_transaction_to_usa t
      LEFT JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      WHERE t.id_conta = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
      ORDER BY t.created_at DESC
    `, [clienteId, dataInicio, dataFim]);

    // Individual transactions USD->BRL
    const [txUsd] = await conn.execute(`
      SELECT p.created_at as date, 'USD→BRL' as flow,
        p.valor as usd, ROUND(p.valor * p.cotacao, 2) as brl,
        ROUND(p.cotacao,4) as rate, ROUND(p.ptax,4) as ptax,
        CASE WHEN p.cotacao > 0 THEN ROUND((p.ptax - p.cotacao) / p.ptax * 100, 2) ELSE 0 END as spread_pct,
        0 as iof, COALESCE(p.pgto, '') as status,
        COALESCE(p.tipo_envio, '') as provider
      FROM pagamento_br p
      WHERE p.id_conta = ? AND DATE(p.created_at) >= ? AND DATE(p.created_at) <= ?
        AND p.cotacao IS NOT NULL AND p.cotacao > 0 AND (p.pgto IS NULL OR p.pgto != 'balance')
      ORDER BY p.created_at DESC
    `, [clienteId, dataInicio, dataFim]);

    // Day of week
    const [dowBrl] = await conn.execute(`
      SELECT DAYOFWEEK(created_at) as dow, COUNT(*) as qtd, ROUND(SUM(amount_usd),2) as vol_usd
      FROM br_transaction_to_usa WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY DAYOFWEEK(created_at)
    `, [clienteId, dataInicio, dataFim]);
    const [dowUsd] = await conn.execute(`
      SELECT DAYOFWEEK(created_at) as dow, COUNT(*) as qtd, ROUND(SUM(valor),2) as vol_usd
      FROM pagamento_br WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
      GROUP BY DAYOFWEEK(created_at)
    `, [clienteId, dataInicio, dataFim]);

    // Providers
    const [provBrl] = await conn.execute(`
      SELECT COALESCE(pm.provider, 'N/A') as name, COUNT(*) as qtd, ROUND(SUM(t.amount_usd),2) as vol_usd
      FROM br_transaction_to_usa t
      LEFT JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      WHERE t.id_conta = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY pm.provider
    `, [clienteId, dataInicio, dataFim]);
    const [provUsd] = await conn.execute(`
      SELECT COALESCE(p.tipo_envio, 'N/A') as name, COUNT(*) as qtd, ROUND(SUM(p.valor),2) as vol_usd
      FROM pagamento_br p
      WHERE p.id_conta = ? AND DATE(p.created_at) >= ? AND DATE(p.created_at) <= ?
        AND p.cotacao IS NOT NULL AND p.cotacao > 0 AND (p.pgto IS NULL OR p.pgto != 'balance')
      GROUP BY p.tipo_envio
    `, [clienteId, dataInicio, dataFim]);

    // Monthly breakdown
    const [monthlyBrl] = await conn.execute(`
      SELECT DATE_FORMAT(created_at, '%Y-%m') as mes, COUNT(*) as qtd,
        ROUND(SUM(amount_usd),2) as vol_usd,
        ROUND(SUM((exchange_rate - ptax) / exchange_rate * amount_usd),2) as spread_revenue
      FROM br_transaction_to_usa WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND (status IN ('boleto_pago','finalizado') OR date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY DATE_FORMAT(created_at, '%Y-%m') ORDER BY mes
    `, [clienteId, dataInicio, dataFim]);
    const [monthlyUsd] = await conn.execute(`
      SELECT DATE_FORMAT(created_at, '%Y-%m') as mes, COUNT(*) as qtd,
        ROUND(SUM(valor),2) as vol_usd,
        ROUND(SUM((ptax - cotacao) / ptax * valor),2) as spread_revenue
      FROM pagamento_br WHERE id_conta = ? AND DATE(created_at) >= ? AND DATE(created_at) <= ?
        AND cotacao IS NOT NULL AND cotacao > 0 AND (pgto IS NULL OR pgto != 'balance')
      GROUP BY DATE_FORMAT(created_at, '%Y-%m') ORDER BY mes
    `, [clienteId, dataInicio, dataFim]);

    const b = kpiBrl[0] || {};
    const u = kpiUsd[0] || {};
    const bQtd = Number(b.qtd) || 0;
    const uQtd = Number(u.qtd) || 0;
    const totalQtd = bQtd + uQtd;
    const totalVolUsd = (Number(b.vol_usd) || 0) + (Number(u.vol_usd) || 0);

    // Merge day of week
    const dowMap = {};
    for (let i = 1; i <= 7; i++) dowMap[i] = { qtd: 0, vol_usd: 0 };
    dowBrl.forEach(r => { dowMap[r.dow].qtd += Number(r.qtd); dowMap[r.dow].vol_usd += Number(r.vol_usd); });
    dowUsd.forEach(r => { dowMap[r.dow].qtd += Number(r.qtd); dowMap[r.dow].vol_usd += Number(r.vol_usd); });

    // Merge providers
    const provMap = {};
    [...provBrl, ...provUsd].forEach(r => {
      const n = r.name || 'N/A';
      if (!provMap[n]) provMap[n] = { name: n, qtd: 0, vol_usd: 0 };
      provMap[n].qtd += Number(r.qtd);
      provMap[n].vol_usd += Number(r.vol_usd);
    });

    // Merge monthly data
    const monthMap = {};
    [...monthlyBrl, ...monthlyUsd].forEach(r => {
      if (!monthMap[r.mes]) monthMap[r.mes] = { mes: r.mes, qtd: 0, vol_usd: 0, spread_revenue: 0 };
      monthMap[r.mes].qtd += Number(r.qtd);
      monthMap[r.mes].vol_usd += Number(r.vol_usd);
      monthMap[r.mes].spread_revenue += Number(r.spread_revenue);
    });

    const transactions = [
      ...txBrl.map(r => ({
        date: fmtDateTime(r.date), flow: r.flow, usd: Number(r.usd), brl: Number(r.brl),
        rate: Number(r.rate), ptax: Number(r.ptax), spread_pct: Number(r.spread_pct),
        iof: Number(r.iof), status: r.status, provider: r.provider
      })),
      ...txUsd.map(r => ({
        date: fmtDateTime(r.date), flow: r.flow, usd: Number(r.usd), brl: Number(r.brl),
        rate: Number(r.rate), ptax: Number(r.ptax), spread_pct: Number(r.spread_pct),
        iof: Number(r.iof), status: r.status, provider: r.provider
      }))
    ].sort((a, b) => b.date.localeCompare(a.date));

    return {
      kpis: {
        brlUsd: { qtd: bQtd, vol_usd: Number(b.vol_usd)||0, vol_brl: Number(b.vol_brl)||0, spread_revenue: Number(b.spread_revenue)||0, avg_spread_pct: Number(b.avg_spread_pct)||0, ticket_medio: bQtd > 0 ? Math.round((Number(b.vol_usd)||0) / bQtd) : 0 },
        usdBrl: { qtd: uQtd, vol_usd: Number(u.vol_usd)||0, vol_brl: Number(u.vol_brl)||0, spread_revenue: Number(u.spread_revenue)||0, avg_spread_pct: Number(u.avg_spread_pct)||0, ticket_medio: uQtd > 0 ? Math.round((Number(u.vol_usd)||0) / uQtd) : 0 },
        total: {
          qtd: totalQtd, vol_usd: totalVolUsd, vol_brl: (Number(b.vol_brl)||0) + (Number(u.vol_brl)||0),
          spread_revenue: (Number(b.spread_revenue)||0) + (Number(u.spread_revenue)||0),
          avg_spread_pct: totalQtd > 0 ? ((Number(b.avg_spread_pct)||0) * bQtd + (Number(u.avg_spread_pct)||0) * uQtd) / totalQtd : 0,
          ticket_medio: totalQtd > 0 ? Math.round(totalVolUsd / totalQtd) : 0
        }
      },
      comparison: {
        prev_qtd: (Number(prevBrl[0]?.qtd)||0) + (Number(prevUsd[0]?.qtd)||0),
        prev_vol_usd: (Number(prevBrl[0]?.vol_usd)||0) + (Number(prevUsd[0]?.vol_usd)||0),
        prev_spread: (Number(prevBrl[0]?.spread_revenue)||0) + (Number(prevUsd[0]?.spread_revenue)||0)
      },
      trend: { brlUsd: fmtTrendRows(trendBrl), usdBrl: fmtTrendRows(trendUsd) },
      transactions,
      dayOfWeek: dowMap,
      providers: Object.values(provMap).sort((a, b) => b.vol_usd - a.vol_usd),
      monthly: Object.values(monthMap).map(m => ({ mes: m.mes, qtd: m.qtd, vol_usd: Math.round(m.vol_usd * 100) / 100, spread_revenue: Math.round(m.spread_revenue * 100) / 100, avg_usd: m.qtd > 0 ? Math.round(m.vol_usd / m.qtd) : 0 })).sort((a, b) => a.mes.localeCompare(b.mes))
    };
  } finally {
    conn.release();
  }
}

// Detect if client is a merchant
async function fetchMerchantProfile(clienteId) {
  const conn = await pool.getConnection();
  try {
    const [empresa] = await conn.execute(
      'SELECT id, nome_empresa FROM br_cb_empresas WHERE id_conta = ? AND active = 1 LIMIT 1',
      [clienteId]
    );
    if (!empresa.length) return { is_merchant: false };

    const empresaId = empresa[0].id;
    const nomeEmpresa = empresa[0].nome_empresa;

    const [stats] = await conn.execute(`
      SELECT
        COUNT(*) as tx_count,
        ROUND(COALESCE(SUM(t.amount_usd), 0), 2) as vol_usd,
        COUNT(DISTINCT t.id_conta) as unique_payers,
        MIN(t.created_at) as first_op,
        MAX(t.created_at) as last_op,
        COUNT(DISTINCT DATE_FORMAT(t.created_at, '%Y-%m')) as months_active
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      WHERE cb.empresa_id = ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId]);

    const [rev] = await conn.execute(`
      SELECT ROUND(COALESCE(SUM(
        (
          ROUND((t.amount_brl - IF(pm.provider IN ('ouribank','bs2'), 0, t.fee)) / t.ptax, 2)
          - COALESCE(t.pfee, 0)
        ) - (
          t.amount_usd + COALESCE(t.bonus_valor, 0) - COALESCE(t.taxa_cr, 0)
        )
      ), 0), 2) as revenue
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      INNER JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      WHERE cb.empresa_id = ?
        AND pm.provider IN ('dlocal','bexs','braza','bs2','ouribank','msb')
        AND t.ptax IS NOT NULL AND t.ptax > 0
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId]);

    const s = stats[0] || {};
    return {
      is_merchant: true,
      empresa_id: empresaId,
      nome_empresa: nomeEmpresa,
      checkout: {
        tx_count: Number(s.tx_count) || 0,
        vol_usd: Number(s.vol_usd) || 0,
        unique_payers: Number(s.unique_payers) || 0,
        revenue: Number(rev[0]?.revenue) || 0,
        first_op: s.first_op ? (s.first_op instanceof Date ? s.first_op.toISOString().slice(0, 10) : String(s.first_op).slice(0, 10)) : null,
        last_op: s.last_op ? (s.last_op instanceof Date ? s.last_op.toISOString().slice(0, 10) : String(s.last_op).slice(0, 10)) : null,
        months_active: Number(s.months_active) || 0
      }
    };
  } finally {
    conn.release();
  }
}

// Merchant checkout data for a period
async function fetchMerchantData(empresaId, dataInicio, dataFim) {
  const conn = await pool.getConnection();
  try {
    const { prevStartStr, prevEndStr } = calcPrevPeriod(dataInicio, dataFim);

    const [kpi] = await conn.execute(`
      SELECT
        COUNT(*) as qtd,
        ROUND(COALESCE(SUM(t.amount_usd), 0), 2) as vol_usd,
        COUNT(DISTINCT t.id_conta) as unique_payers,
        ROUND(COALESCE(AVG((t.exchange_rate - t.ptax) / t.exchange_rate * 100), 0), 2) as avg_spread_pct
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId, dataInicio, dataFim]);

    const [rev] = await conn.execute(`
      SELECT ROUND(COALESCE(SUM(
        (
          ROUND((t.amount_brl - IF(pm.provider IN ('ouribank','bs2'), 0, t.fee)) / t.ptax, 2)
          - COALESCE(t.pfee, 0)
        ) - (
          t.amount_usd + COALESCE(t.bonus_valor, 0) - COALESCE(t.taxa_cr, 0)
        )
      ), 0), 2) as revenue
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      INNER JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND pm.provider IN ('dlocal','bexs','braza','bs2','ouribank','msb')
        AND t.ptax IS NOT NULL AND t.ptax > 0
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId, dataInicio, dataFim]);

    const [prevKpi] = await conn.execute(`
      SELECT COUNT(*) as qtd, ROUND(COALESCE(SUM(t.amount_usd), 0), 2) as vol_usd
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId, prevStartStr, prevEndStr]);

    const [prevRev] = await conn.execute(`
      SELECT ROUND(COALESCE(SUM(
        (
          ROUND((t.amount_brl - IF(pm.provider IN ('ouribank','bs2'), 0, t.fee)) / t.ptax, 2)
          - COALESCE(t.pfee, 0)
        ) - (
          t.amount_usd + COALESCE(t.bonus_valor, 0) - COALESCE(t.taxa_cr, 0)
        )
      ), 0), 2) as revenue
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      INNER JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND pm.provider IN ('dlocal','bexs','braza','bs2','ouribank','msb')
        AND t.ptax IS NOT NULL AND t.ptax > 0
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
    `, [empresaId, prevStartStr, prevEndStr]);

    const [monthly] = await conn.execute(`
      SELECT DATE_FORMAT(t.created_at, '%Y-%m') as mes,
        COUNT(*) as qtd,
        ROUND(SUM(t.amount_usd), 2) as vol_usd,
        COUNT(DISTINCT t.id_conta) as unique_payers
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY DATE_FORMAT(t.created_at, '%Y-%m') ORDER BY mes
    `, [empresaId, dataInicio, dataFim]);

    const [topPayers] = await conn.execute(`
      SELECT c.nome, t.id_conta, COUNT(*) as tx_count, ROUND(SUM(t.amount_usd), 2) as vol_usd
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      INNER JOIN conta c ON c.id_conta = t.id_conta
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND (t.status IN ('boleto_pago','finalizado') OR t.date_sent_usa <> '0000-00-00 00:00:00')
      GROUP BY t.id_conta, c.nome
      ORDER BY vol_usd DESC LIMIT 10
    `, [empresaId, dataInicio, dataFim]);

    const [txRows] = await conn.execute(`
      SELECT t.created_at as date, t.amount_usd as usd, t.amount_brl as brl,
        ROUND(t.exchange_rate, 4) as rate, ROUND(t.ptax, 4) as ptax,
        ROUND((t.exchange_rate - t.ptax) / t.exchange_rate * 100, 2) as spread_pct,
        t.iof, t.status, COALESCE(pm.provider, '') as provider,
        c.nome as payer_name, t.id_conta as payer_id
      FROM br_cb_cobranca cb
      INNER JOIN br_transaction_to_usa t ON t.cobranca_id = cb.id
      LEFT JOIN br_payment_methods pm ON t.payment_method_id = pm.id
      LEFT JOIN conta c ON c.id_conta = t.id_conta
      WHERE cb.empresa_id = ? AND DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
      ORDER BY t.created_at DESC LIMIT 500
    `, [empresaId, dataInicio, dataFim]);

    const k = kpi[0] || {};
    const qtd = Number(k.qtd) || 0;
    const volUsd = Number(k.vol_usd) || 0;
    const revenue = Number(rev[0]?.revenue) || 0;

    return {
      kpis: {
        qtd,
        vol_usd: volUsd,
        unique_payers: Number(k.unique_payers) || 0,
        avg_spread_pct: Number(k.avg_spread_pct) || 0,
        revenue,
        ticket_medio: qtd > 0 ? Math.round(volUsd / qtd) : 0
      },
      comparison: {
        prev_qtd: Number(prevKpi[0]?.qtd) || 0,
        prev_vol_usd: Number(prevKpi[0]?.vol_usd) || 0,
        prev_revenue: Number(prevRev[0]?.revenue) || 0
      },
      monthly: monthly.map(r => ({
        mes: r.mes,
        qtd: Number(r.qtd),
        vol_usd: Number(r.vol_usd),
        unique_payers: Number(r.unique_payers)
      })),
      topPayers: topPayers.map(r => ({
        nome: r.nome,
        id_conta: r.id_conta,
        tx_count: Number(r.tx_count),
        vol_usd: Number(r.vol_usd)
      })),
      transactions: txRows.map(r => ({
        date: fmtDateTime(r.date), flow: 'Checkout', usd: Number(r.usd), brl: Number(r.brl),
        rate: Number(r.rate), ptax: Number(r.ptax), spread_pct: Number(r.spread_pct),
        iof: Number(r.iof), status: r.status, provider: r.provider,
        payer_name: r.payer_name || '', payer_id: r.payer_id
      }))
    };
  } finally {
    conn.release();
  }
}

module.exports = {
  fetchTopClients,
  fetchClientSearch,
  fetchClientProfile,
  fetchClientData,
  fetchMerchantProfile,
  fetchMerchantData
};
