/**
 * Compliance Queries — AML/KYC monitoring data layer
 * Dashboard deferred to backlog; queries available for alerting and future UI
 */
const { pool, fmtDate, fmtDateTime } = require('./helpers');

// Transactions above $3,000 threshold
async function fetchThresholdTransactions(start, end) {
  const conn = await pool.getConnection();
  try {
    const [brlUsd] = await conn.execute(`
      SELECT c.nome, t.id_conta, t.created_at as date, t.amount_usd as usd,
        t.amount_brl as brl, 'BRL→USD' as flow
      FROM br_transaction_to_usa t
      INNER JOIN conta c ON c.id_conta = t.id_conta
      WHERE DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND t.amount_usd >= 3000
      ORDER BY t.amount_usd DESC
    `, [start, end]);

    const [usdBrl] = await conn.execute(`
      SELECT c.nome, p.id_conta, p.created_at as date, p.valor as usd,
        ROUND(p.valor * p.cotacao, 2) as brl, 'USD→BRL' as flow
      FROM pagamento_br p
      INNER JOIN conta c ON c.id_conta = p.id_conta
      WHERE DATE(p.created_at) >= ? AND DATE(p.created_at) <= ?
        AND p.valor >= 3000
        AND p.cotacao IS NOT NULL AND p.cotacao > 0
        AND (p.pgto IS NULL OR p.pgto != 'balance')
      ORDER BY p.valor DESC
    `, [start, end]);

    return [...brlUsd, ...usdBrl].map(r => ({
      nome: r.nome,
      id_conta: r.id_conta,
      date: fmtDateTime(r.date),
      usd: Number(r.usd),
      brl: Number(r.brl),
      flow: r.flow
    })).sort((a, b) => b.usd - a.usd);
  } finally {
    conn.release();
  }
}

// Structuring alerts: multiple txs $2,500-$3,000 same client/day
async function fetchStructuringAlerts(start, end) {
  const conn = await pool.getConnection();
  try {
    const [brlUsd] = await conn.execute(`
      SELECT c.nome, t.id_conta, DATE(t.created_at) as date,
        COUNT(*) as tx_count,
        ROUND(SUM(t.amount_usd), 2) as total_usd,
        'BRL→USD' as flow
      FROM br_transaction_to_usa t
      INNER JOIN conta c ON c.id_conta = t.id_conta
      WHERE DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND t.amount_usd BETWEEN 2500 AND 3000
      GROUP BY t.id_conta, c.nome, DATE(t.created_at)
      HAVING COUNT(*) >= 2
      ORDER BY tx_count DESC
    `, [start, end]);

    const [usdBrl] = await conn.execute(`
      SELECT c.nome, p.id_conta, DATE(p.created_at) as date,
        COUNT(*) as tx_count,
        ROUND(SUM(p.valor), 2) as total_usd,
        'USD→BRL' as flow
      FROM pagamento_br p
      INNER JOIN conta c ON c.id_conta = p.id_conta
      WHERE DATE(p.created_at) >= ? AND DATE(p.created_at) <= ?
        AND p.valor BETWEEN 2500 AND 3000
        AND p.cotacao IS NOT NULL AND p.cotacao > 0
        AND (p.pgto IS NULL OR p.pgto != 'balance')
      GROUP BY p.id_conta, c.nome, DATE(p.created_at)
      HAVING COUNT(*) >= 2
      ORDER BY tx_count DESC
    `, [start, end]);

    return [...brlUsd, ...usdBrl].map(r => ({
      nome: r.nome,
      id_conta: r.id_conta,
      date: fmtDate(r.date),
      tx_count: Number(r.tx_count),
      total_usd: Number(r.total_usd),
      flow: r.flow
    })).sort((a, b) => b.tx_count - a.tx_count);
  } finally {
    conn.release();
  }
}

// Velocity anomalies: frequency spikes vs 30-day avg
async function fetchVelocityAnomalies(start, end) {
  const conn = await pool.getConnection();
  try {
    const [rows] = await conn.execute(`
      SELECT c.nome, curr.id_conta,
        curr.daily_count as current_daily_count,
        curr.date as spike_date,
        ROUND(avg30.avg_daily, 1) as avg_daily_30d,
        ROUND(curr.daily_count / GREATEST(avg30.avg_daily, 1), 1) as multiple
      FROM (
        SELECT id_conta, DATE(created_at) as date, COUNT(*) as daily_count
        FROM br_transaction_to_usa
        WHERE DATE(created_at) >= ? AND DATE(created_at) <= ?
        GROUP BY id_conta, DATE(created_at)
        HAVING COUNT(*) >= 3
      ) curr
      INNER JOIN (
        SELECT id_conta, COUNT(*) / 30.0 as avg_daily
        FROM br_transaction_to_usa
        WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 60 DAY)
          AND created_at < DATE_SUB(CURDATE(), INTERVAL 30 DAY)
        GROUP BY id_conta
      ) avg30 ON avg30.id_conta = curr.id_conta
      INNER JOIN conta c ON c.id_conta = curr.id_conta
      WHERE curr.daily_count > avg30.avg_daily * 3
      ORDER BY multiple DESC
      LIMIT 50
    `, [start, end]);

    return rows.map(r => ({
      nome: r.nome,
      id_conta: r.id_conta,
      spike_date: fmtDate(r.spike_date),
      current_daily_count: Number(r.current_daily_count),
      avg_daily_30d: Number(r.avg_daily_30d),
      multiple: Number(r.multiple)
    }));
  } finally {
    conn.release();
  }
}

// IOF reconciliation: calculated vs expected IOF delta
async function fetchIOFReconciliation(start, end) {
  const conn = await pool.getConnection();
  try {
    const [rows] = await conn.execute(`
      SELECT
        c.nome, t.id_conta, t.created_at as date,
        t.amount_usd, t.iof as iof_pct,
        ROUND(t.iof / 100 * t.amount_usd * t.exchange_rate, 2) as iof_calculated,
        ROUND(t.amount_brl - (t.amount_usd * t.exchange_rate), 2) as iof_implied,
        ROUND(
          ABS((t.iof / 100 * t.amount_usd * t.exchange_rate) - (t.amount_brl - (t.amount_usd * t.exchange_rate))),
          2
        ) as delta
      FROM br_transaction_to_usa t
      INNER JOIN conta c ON c.id_conta = t.id_conta
      WHERE DATE(t.created_at) >= ? AND DATE(t.created_at) <= ?
        AND t.iof > 0
      HAVING delta > 10
      ORDER BY delta DESC
      LIMIT 100
    `, [start, end]);

    return rows.map(r => ({
      nome: r.nome,
      id_conta: r.id_conta,
      date: fmtDateTime(r.date),
      amount_usd: Number(r.amount_usd),
      iof_pct: Number(r.iof_pct),
      iof_calculated: Number(r.iof_calculated),
      iof_implied: Number(r.iof_implied),
      delta: Number(r.delta)
    }));
  } finally {
    conn.release();
  }
}

module.exports = {
  fetchThresholdTransactions,
  fetchStructuringAlerts,
  fetchVelocityAnomalies,
  fetchIOFReconciliation
};
